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
35 extern int DEBUGLEVEL;
37 extern files_struct Files[];
38 extern connection_struct Connections[];
40 extern fstring local_machine;
42 #define NERR_Success 0
43 #define NERR_badpass 86
44 #define NERR_notsupported 50
46 #define NERR_BASE (2100)
47 #define NERR_BufTooSmall (NERR_BASE+23)
48 #define NERR_JobNotFound (NERR_BASE+51)
49 #define NERR_DestNotFound (NERR_BASE+52)
50 #define ERROR_INVALID_LEVEL 124
51 #define ERROR_MORE_DATA 234
53 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
55 #define ACCESS_READ 0x01
56 #define ACCESS_WRITE 0x02
57 #define ACCESS_CREATE 0x04
59 #define SHPWLEN 8 /* share password length */
60 #define NNLEN 12 /* 8.3 net name length */
61 #define SNLEN 15 /* service name length */
62 #define QNLEN 12 /* queue name maximum length */
66 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
71 if (!src || !dst || !n || !(*dst)) return(0);
73 StrnCpy(buf,src,sizeof(buf)/2);
74 string_sub(buf,"%S",lp_servicename(snum));
75 standard_sub(cnum,buf);
83 static int CopyAndAdvance(char** dst, char* src, int* n)
86 if (!src || !dst || !n || !(*dst)) return(0);
94 static int StrlenExpanded(int cnum, int snum, char* s)
98 StrnCpy(buf,s,sizeof(buf)/2);
99 string_sub(buf,"%S",lp_servicename(snum));
100 standard_sub(cnum,buf);
101 return strlen(buf) + 1;
104 static char* Expand(int cnum, int snum, char* s)
107 if (!s) return(NULL);
108 StrnCpy(buf,s,sizeof(buf)/2);
109 string_sub(buf,"%S",lp_servicename(snum));
110 standard_sub(cnum,buf);
114 /*******************************************************************
115 check a API string for validity when we only need to check the prefix
116 ******************************************************************/
117 static BOOL prefix_ok(char *str,char *prefix)
119 return(strncmp(str,prefix,strlen(prefix)) == 0);
123 /****************************************************************************
125 ****************************************************************************/
126 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
127 int ldata,int lparam,int lsetup)
130 int this_ldata,this_lparam;
131 int tot_data=0,tot_param=0;
134 this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */
135 this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam));
137 align = (this_lparam%4);
139 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
141 memcpy(smb_buf(outbuf),param,this_lparam);
143 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
145 SSVAL(outbuf,smb_vwv0,lparam);
146 SSVAL(outbuf,smb_vwv1,ldata);
147 SSVAL(outbuf,smb_vwv3,this_lparam);
148 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
149 SSVAL(outbuf,smb_vwv5,0);
150 SSVAL(outbuf,smb_vwv6,this_ldata);
151 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
152 SSVAL(outbuf,smb_vwv8,0);
153 SSVAL(outbuf,smb_vwv9,lsetup);
154 for (i=0;i<lsetup;i++)
155 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
158 send_smb(Client,outbuf);
160 tot_data = this_ldata;
161 tot_param = this_lparam;
163 while (tot_data < ldata || tot_param < lparam)
165 this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
166 this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
168 align = (this_lparam%4);
170 set_message(outbuf,10,this_ldata+this_lparam+align,False);
172 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
174 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
176 SSVAL(outbuf,smb_vwv3,this_lparam);
177 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
178 SSVAL(outbuf,smb_vwv5,tot_param);
179 SSVAL(outbuf,smb_vwv6,this_ldata);
180 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
181 SSVAL(outbuf,smb_vwv8,tot_data);
182 SSVAL(outbuf,smb_vwv9,0);
185 send_smb(Client,outbuf);
187 tot_data += this_ldata;
188 tot_param += this_lparam;
194 /****************************************************************************
196 ****************************************************************************/
199 char* format; /* formatstring for structure */
200 char* subformat; /* subformat for structure */
201 char* base; /* baseaddress of buffer */
202 int buflen; /* remaining size for fixed part; on init: length of base */
203 int subcount; /* count of substructures */
204 char* structbuf; /* pointer into buffer for remaining fixed part */
205 int stringlen; /* remaining size for variable part */
206 char* stringbuf; /* pointer into buffer for remaining variable part */
207 int neededlen; /* total needed size */
208 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
209 char* curpos; /* current position; pointer into format or subformat */
213 static int get_counter(char** p)
216 if (!p || !(*p)) return(1);
217 if (!isdigit(**p)) return 1;
221 n = 10 * n + (i - '0');
228 static int getlen(char* p)
234 case 'W': /* word (2 byte) */
237 case 'N': /* count of substructures (word) at end */
240 case 'D': /* double word (4 byte) */
241 case 'z': /* offset to zero terminated string (4 byte) */
242 case 'l': /* offset to user data (4 byte) */
245 case 'b': /* offset to data (with counter) (4 byte) */
249 case 'B': /* byte (with optional counter) */
250 n += get_counter(&p);
257 static BOOL init_package(struct pack_desc* p, int count, int subcount)
262 if (!p->format || !p->base) return(False);
264 i = count * getlen(p->format);
265 if (p->subformat) i += subcount * getlen(p->subformat);
266 p->structbuf = p->base;
270 p->curpos = p->format;
273 p->errcode = NERR_BufTooSmall;
276 p->errcode = NERR_Success;
279 p->stringbuf = p->base + i;
281 return(p->errcode == NERR_Success);
285 static int package(struct pack_desc* p, ...)
288 static int package(va_alist)
294 int needed=0, stringneeded;
296 int is_string=0, stringused;
303 p = va_arg(args,struct pack_desc *);
308 p->curpos = p->format;
310 p->curpos = p->subformat;
315 str = va_arg(args,char*);
316 if (strncmp(str,p->curpos,strlen(str)) != 0) {
317 DEBUG(2,("type error in package: %s instead of %*s\n",str,
318 strlen(str),p->curpos));
328 if (!p->curpos) return(0);
330 switch( *p->curpos++ ) {
331 case 'W': /* word (2 byte) */
333 temp = va_arg(args,int);
334 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
336 case 'N': /* count of substructures (word) at end */
338 p->subcount = va_arg(args,int);
339 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
341 case 'D': /* double word (4 byte) */
343 temp = va_arg(args,int);
344 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
346 case 'B': /* byte (with optional counter) */
347 needed = get_counter(&p->curpos);
349 char *s = va_arg(args,char*);
350 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
353 case 'z': /* offset to zero terminated string (4 byte) */
354 str = va_arg(args,char*);
355 stringneeded = (str ? strlen(str)+1 : 0);
358 case 'l': /* offset to user data (4 byte) */
359 str = va_arg(args,char*);
360 stringneeded = va_arg(args,int);
363 case 'b': /* offset to data (with counter) (4 byte) */
364 str = va_arg(args,char*);
365 stringneeded = get_counter(&p->curpos);
370 if (stringneeded >= 0) {
372 if (p->buflen >= needed) {
373 stringused = stringneeded;
374 if (stringused > p->stringlen) {
375 stringused = (is_string ? p->stringlen : 0);
376 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
379 SIVAL(p->structbuf,0,0);
381 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
382 memcpy(p->stringbuf,str?str:"",stringused);
383 if (is_string) p->stringbuf[stringused-1] = '\0';
384 p->stringbuf += stringused;
385 p->stringlen -= stringused;
386 p->usedlen += stringused;
389 p->neededlen += stringneeded;
391 p->neededlen += needed;
392 if (p->buflen >= needed) {
393 p->structbuf += needed;
395 p->usedlen += needed;
398 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
404 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
405 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
407 #define PACK(desc,t,v) package(desc,v)
408 #define PACKl(desc,t,v,l) package(desc,v,l)
411 static void PACKI(struct pack_desc* desc,char *t,int v)
416 static void PACKS(struct pack_desc* desc,char *t,char *v)
421 static void PackDriverData(struct pack_desc* desc)
423 char drivdata[4+4+32];
424 SIVAL(drivdata,0,sizeof drivdata); /* cb */
425 SIVAL(drivdata,4,1000); /* lVersion */
426 memset(drivdata+8,0,32); /* szDeviceName */
427 strcpy(drivdata+8,"NULL");
428 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
431 static int check_printq_info(struct pack_desc* desc,
432 int uLevel, const char* id1, const char* id2)
434 desc->subformat = NULL;
437 desc->format = "B13";
440 desc->format = "B13BWWWzzzzzWW";
443 desc->format = "B13BWWWzzzzzWN";
444 desc->subformat = "WB21BB16B10zWWzDDz";
447 desc->format = "zWWWWzzzzWWzzl";
450 desc->format = "zWWWWzzzzWNzzl";
451 desc->subformat = "WWzWWDDzz";
456 default: return False;
458 if (strcmp(desc->format,id1) != 0) return False;
459 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
463 static void fill_printjob_info(int cnum, int snum, int uLevel,
464 struct pack_desc* desc,
465 print_queue_struct* queue, int n)
467 time_t t = queue->time;
469 /* the client expects localtime */
470 t += GMT_TO_LOCAL*TimeDiff(t);
472 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
474 PACKS(desc,"B21",queue->user); /* szUserName */
475 PACKS(desc,"B",""); /* pad */
476 PACKS(desc,"B16",""); /* szNotifyName */
477 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
478 PACKS(desc,"z",""); /* pszParms */
479 PACKI(desc,"W",n+1); /* uPosition */
480 PACKI(desc,"W",queue->status); /* fsStatus */
481 PACKS(desc,"z",""); /* pszStatus */
482 PACKI(desc,"D",queue->time); /* ulSubmitted */
483 PACKI(desc,"D",queue->size); /* ulSize */
484 PACKS(desc,"z",queue->file); /* pszComment */
486 if (uLevel == 2 || uLevel == 3) {
487 PACKI(desc,"W",queue->priority); /* uPriority */
488 PACKS(desc,"z",queue->user); /* pszUserName */
489 PACKI(desc,"W",n+1); /* uPosition */
490 PACKI(desc,"W",queue->status); /* fsStatus */
491 PACKI(desc,"D",queue->time); /* ulSubmitted */
492 PACKI(desc,"D",queue->size); /* ulSize */
493 PACKS(desc,"z","Samba"); /* pszComment */
494 PACKS(desc,"z",queue->file); /* pszDocument */
496 PACKS(desc,"z",""); /* pszNotifyName */
497 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
498 PACKS(desc,"z",""); /* pszParms */
499 PACKS(desc,"z",""); /* pszStatus */
500 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
501 PACKS(desc,"z","lpd"); /* pszQProcName */
502 PACKS(desc,"z",""); /* pszQProcParms */
503 PACKS(desc,"z","NULL"); /* pszDriverName */
504 PackDriverData(desc); /* pDriverData */
505 PACKS(desc,"z",""); /* pszPrinterName */
510 static void fill_printq_info(int cnum, int snum, int uLevel,
511 struct pack_desc* desc,
512 int count, print_queue_struct* queue,
513 print_status_struct* status)
516 PACKS(desc,"B13",SERVICE(snum));
518 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
520 if (uLevel == 1 || uLevel == 2) {
521 PACKS(desc,"B",""); /* alignment */
522 PACKI(desc,"W",5); /* priority */
523 PACKI(desc,"W",0); /* start time */
524 PACKI(desc,"W",0); /* until time */
525 PACKS(desc,"z",""); /* pSepFile */
526 PACKS(desc,"z","lpd"); /* pPrProc */
527 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
528 PACKS(desc,"z",""); /* pParms */
530 PACKS(desc,"z","UNKNOWN PRINTER");
531 PACKI(desc,"W",LPSTAT_ERROR);
533 else if (!status || !status->message[0]) {
534 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
535 PACKI(desc,"W",LPSTAT_OK); /* status */
537 PACKS(desc,"z",status->message);
538 PACKI(desc,"W",status->status); /* status */
540 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
542 if (uLevel == 3 || uLevel == 4) {
543 PACKI(desc,"W",5); /* uPriority */
544 PACKI(desc,"W",0); /* uStarttime */
545 PACKI(desc,"W",0); /* uUntiltime */
546 PACKI(desc,"W",5); /* pad1 */
547 PACKS(desc,"z",""); /* pszSepFile */
548 PACKS(desc,"z","lpd"); /* pszPrProc */
549 PACKS(desc,"z",""); /* pszParms */
550 if (!status || !status->message[0]) {
551 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
552 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
554 PACKS(desc,"z",status->message); /* pszComment */
555 PACKI(desc,"W",status->status); /* fsStatus */
557 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
558 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
559 PACKS(desc,"z","NULL"); /* pszDriverName */
560 PackDriverData(desc); /* pDriverData */
562 if (uLevel == 2 || uLevel == 4) {
564 for (i=0;i<count;i++)
565 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
568 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
571 static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
572 int mdrcnt,int mprcnt,
573 char **rdata,char **rparam,
574 int *rdata_len,int *rparam_len)
576 char *str1 = param+2;
577 char *str2 = skip_string(str1,1);
578 char *p = skip_string(str2,1);
584 struct pack_desc desc;
585 print_queue_struct *queue=NULL;
586 print_status_struct status;
588 bzero(&status,sizeof(status));
589 bzero(&desc,sizeof(desc));
591 p = skip_string(p,1);
596 if ((p = strchr(QueueName,'%'))) *p = 0;
598 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
600 /* check it's a supported varient */
601 if (!prefix_ok(str1,"zWrLh")) return False;
602 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
604 snum = lp_servicenumber(QueueName);
605 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
606 int pnum = lp_servicenumber(PRINTERS_NAME);
608 lp_add_printer(QueueName,pnum);
609 snum = lp_servicenumber(QueueName);
613 if (snum < 0 || !VALID_SNUM(snum)) return(False);
615 count = get_printqueue(snum,cnum,&queue,&status);
616 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
618 desc.buflen = mdrcnt;
619 if (init_package(&desc,1,count)) {
620 desc.subcount = count;
621 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
624 *rdata_len = desc.usedlen;
627 *rparam = REALLOC(*rparam,*rparam_len);
628 SSVALS(*rparam,0,desc.errcode);
630 SSVAL(*rparam,4,desc.neededlen);
632 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
634 if (queue) free(queue);
640 /****************************************************************************
641 view list of all print jobs on all queues
642 ****************************************************************************/
643 static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
644 int mdrcnt, int mprcnt,
645 char **rdata, char** rparam,
646 int *rdata_len, int *rparam_len)
648 char *param_format = param+2;
649 char *output_format1 = skip_string(param_format,1);
650 char *p = skip_string(output_format1,1);
651 int uLevel = SVAL(p,0);
652 char *output_format2 = p + 4;
653 int services = lp_numservices();
655 struct pack_desc desc;
656 print_queue_struct **queue = NULL;
657 print_status_struct *status = NULL;
658 int* subcntarr = NULL;
659 int queuecnt, subcnt=0, succnt=0;
661 bzero(&desc,sizeof(desc));
663 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
665 if (prefix_ok(param_format,"WrLeh")) return False;
666 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
669 for (i = 0; i < services; i++)
670 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
673 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
674 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
675 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
676 memset(status,0,queuecnt*sizeof(print_status_struct));
677 subcntarr = (int*)malloc(queuecnt*sizeof(int));
680 for (i = 0; i < services; i++)
681 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
682 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
683 subcnt += subcntarr[n];
687 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
689 desc.buflen = mdrcnt;
691 if (init_package(&desc,queuecnt,subcnt)) {
694 for (i = 0; i < services; i++)
695 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
696 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
698 if (desc.errcode == NERR_Success) succnt = n;
702 if (subcntarr) free(subcntarr);
704 *rdata_len = desc.usedlen;
706 *rparam = REALLOC(*rparam,*rparam_len);
707 SSVALS(*rparam,0,desc.errcode);
709 SSVAL(*rparam,4,succnt);
710 SSVAL(*rparam,6,queuecnt);
712 for (i = 0; i < queuecnt; i++) {
713 if (queue && queue[i]) free(queue[i]);
716 if (queue) free(queue);
717 if (status) free(status);
722 /****************************************************************************
723 get info level for a server list query
724 ****************************************************************************/
725 static BOOL check_server_info(int uLevel, char* id)
729 if (strcmp(id,"B16") != 0) return False;
732 if (strcmp(id,"B16BBDz") != 0) return False;
740 /* used for server information: client, nameserv and ipc */
741 struct srv_info_struct
746 fstring domain; /* used ONLY in ipc.c NOT namework.c */
747 BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
750 /*******************************************************************
751 filter out unwanted server info
752 ******************************************************************/
753 static BOOL filter_server_info(struct srv_info_struct *server,
757 return(strequal(domain, server->domain));
759 return (True); /* be indiscriminate: get all servers! */
762 /*******************************************************************
763 find server in the files saved by nmbd. Return True if we find it.
764 ******************************************************************/
765 static BOOL find_server(struct srv_info_struct *servers, int num_servers,
766 char *domain, char *name)
770 if (!servers || num_servers == 0) return (False);
772 for (count = 0; count < num_servers; count++) {
773 struct srv_info_struct *s;
777 if (strequal(name, s->name)) {
778 StrnCpy(domain, s->domain, sizeof(pstring)-1);
786 /*******************************************************************
787 get server info lists from the files saved by nmbd. Return the
789 ******************************************************************/
790 static int get_server_info(uint32 servertype,
791 struct srv_info_struct **servers)
799 strcpy(fname,lp_lockdir());
800 trim_string(fname,NULL,"/");
802 strcat(fname,SERVER_LIST);
804 f = fopen(fname,"r");
807 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
810 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
815 struct srv_info_struct *s;
819 fgets(line,sizeof(line)-1,f);
820 if (!*line) continue;
822 if (count == alloced) {
824 (*servers) = (struct srv_info_struct *)
825 Realloc(*servers,sizeof(**servers)*alloced);
826 if (!(*servers)) return(0);
827 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
829 s = &(*servers)[count];
831 s->server_added = True;
833 if (!next_token(&ptr,s->name , NULL)) continue;
834 if (!next_token(&ptr,stype , NULL)) continue;
835 if (!next_token(&ptr,s->comment, NULL)) continue;
836 if (!next_token(&ptr,s->domain , NULL)) {
837 /* this allows us to cop with an old nmbd */
838 strcpy(s->domain,my_workgroup());
841 if (sscanf(stype,"%X",&s->type) != 1) continue;
843 /* doesn't match up: don't want it */
844 if (!(servertype & s->type)) continue;
846 /* server entry is a domain, we haven't asked for domains: don't want it */
847 if ((s->type&SV_TYPE_DOMAIN_ENUM) && !(servertype&SV_TYPE_DOMAIN_ENUM))
850 DEBUG(4,("Server %20s %8x %25s %15s\n",
851 s->name, stype, s->comment, s->domain));
860 /*******************************************************************
861 fill in a server info structure
862 ******************************************************************/
863 static int fill_srv_info(struct srv_info_struct *service,
864 int uLevel, char **buf, int *buflen,
865 char **stringbuf, int *stringspace, char *baseaddr)
874 case 0: struct_len = 16; break;
875 case 1: struct_len = 26; break;
885 len = strlen(service->comment)+1;
889 if (buflen) *buflen = struct_len;
890 if (stringspace) *stringspace = len;
891 return struct_len + len;
896 if (*buflen < struct_len) return -1;
905 l2 = *buflen - struct_len;
907 if (!baseaddr) baseaddr = p;
912 StrnCpy(p,service->name,15);
916 StrnCpy(p,service->name,15);
917 SIVAL(p,18,service->type);
918 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
919 len += CopyAndAdvance(&p2,service->comment,&l2);
925 *buf = p + struct_len;
926 *buflen -= struct_len;
939 /****************************************************************************
940 view list of servers available (or possibly domains). The info is
941 extracted from lists saved by nmbd on the local host
942 ****************************************************************************/
943 static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
944 int mdrcnt, int mprcnt, char **rdata,
945 char **rparam, int *rdata_len, int *rparam_len)
947 char *str1 = param+2;
948 char *str2 = skip_string(str1,1);
949 char *p = skip_string(str2,1);
950 int uLevel = SVAL(p,0);
951 int buf_len = SVAL(p,2);
952 uint32 servertype = IVAL(p,4);
954 int data_len, fixed_len, string_len;
956 struct srv_info_struct *servers=NULL;
957 int counted=0,total=0;
960 BOOL domain_request = (servertype & SV_TYPE_DOMAIN_ENUM) &&
961 !(servertype == SV_TYPE_ALL);
966 if (!prefix_ok(str1,"WrLehD")) return False;
967 if (!check_server_info(uLevel,str2)) return False;
969 DEBUG(4, ("server request level: %s\n", str2));
971 if (strcmp(str1, "WrLehDO") == 0)
973 /* asking for servers. we will have to work out which workgroup was
974 requested, as we maintain lists for multiple workgroups */
976 else if (strcmp(str1, "WrLehDz") == 0)
978 /* asking for a specific workgroup */
979 StrnCpy(domain, p, sizeof(fstring)-1);
982 if (lp_browse_list())
984 total = get_server_info(servertype,&servers);
987 if (!domain[0] && !domain_request) {
988 extern fstring remote_machine;
989 /* must be a server request with an assumed domain. find a domain */
991 if (find_server(servers, total, domain, remote_machine)) {
992 DEBUG(4, ("No domain specified: using %s for %s\n",
993 domain, remote_machine));
995 /* default to soemthing sensible */
996 strcpy(domain,my_workgroup());
1000 data_len = fixed_len = string_len = 0;
1002 for (i=0;i<total;i++)
1003 if (filter_server_info(&servers[i],domain)) {
1004 data_len += fill_srv_info(&servers[i],uLevel,0,&f_len,0,&s_len,0);
1005 if (data_len <= buf_len)
1009 string_len += s_len;
1013 *rdata_len = fixed_len + string_len;
1014 *rdata = REALLOC(*rdata,*rdata_len);
1015 bzero(*rdata,*rdata_len);
1017 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1023 int count2 = counted;
1024 for (i = 0; i < total && count2;i++) {
1025 if (filter_server_info(&servers[i],domain)) {
1026 fill_srv_info(&servers[i],uLevel,&p,&f_len,&p2,&s_len,*rdata);
1033 *rparam = REALLOC(*rparam,*rparam_len);
1034 SSVAL(*rparam,0,NERR_Success);
1036 SSVAL(*rparam,4,counted);
1037 SSVAL(*rparam,6,total);
1039 if (servers) free(servers);
1041 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1042 domain,uLevel,counted,total));
1048 /****************************************************************************
1049 get info about a share
1050 ****************************************************************************/
1051 static BOOL check_share_info(int uLevel, char* id)
1055 if (strcmp(id,"B13") != 0) return False;
1058 if (strcmp(id,"B13BWz") != 0) return False;
1061 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1064 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1066 default: return False;
1071 static int fill_share_info(int cnum, int snum, int uLevel,
1072 char** buf, int* buflen,
1073 char** stringbuf, int* stringspace, char* baseaddr)
1082 case 0: struct_len = 13; break;
1083 case 1: struct_len = 20; break;
1084 case 2: struct_len = 40; break;
1085 case 91: struct_len = 68; break;
1093 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1094 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1095 if (buflen) *buflen = struct_len;
1096 if (stringspace) *stringspace = len;
1097 return struct_len + len;
1102 if ((*buflen) < struct_len) return -1;
1110 p2 = p + struct_len;
1111 l2 = (*buflen) - struct_len;
1113 if (!baseaddr) baseaddr = p;
1115 StrnCpy(p,lp_servicename(snum),13);
1121 type = STYPE_DISKTREE;
1122 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1123 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1124 SSVAL(p,14,type); /* device type */
1125 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1126 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1131 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1132 SSVALS(p,22,-1); /* max uses */
1133 SSVAL(p,24,1); /* current uses */
1134 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1135 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1136 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1141 memset(p+40,0,SHPWLEN+2);
1153 (*buf) = p + struct_len;
1154 (*buflen) -= struct_len;
1156 (*stringspace) = l2;
1166 static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
1167 int mdrcnt,int mprcnt,
1168 char **rdata,char **rparam,
1169 int *rdata_len,int *rparam_len)
1171 char *str1 = param+2;
1172 char *str2 = skip_string(str1,1);
1173 char *netname = skip_string(str2,1);
1174 char *p = skip_string(netname,1);
1175 int uLevel = SVAL(p,0);
1176 int snum = find_service(netname);
1178 if (snum < 0) return False;
1180 /* check it's a supported varient */
1181 if (!prefix_ok(str1,"zWrLh")) return False;
1182 if (!check_share_info(uLevel,str2)) return False;
1184 *rdata = REALLOC(*rdata,mdrcnt);
1186 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1187 if (*rdata_len < 0) return False;
1190 *rparam = REALLOC(*rparam,*rparam_len);
1191 SSVAL(*rparam,0,NERR_Success);
1192 SSVAL(*rparam,2,0); /* converter word */
1193 SSVAL(*rparam,4,*rdata_len);
1198 /****************************************************************************
1199 view list of shares available
1200 ****************************************************************************/
1201 static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
1202 int mdrcnt,int mprcnt,
1203 char **rdata,char **rparam,
1204 int *rdata_len,int *rparam_len)
1206 char *str1 = param+2;
1207 char *str2 = skip_string(str1,1);
1208 char *p = skip_string(str2,1);
1209 int uLevel = SVAL(p,0);
1210 int buf_len = SVAL(p,2);
1212 int count=lp_numservices();
1213 int total=0,counted=0;
1215 int data_len, fixed_len, string_len;
1218 if (!prefix_ok(str1,"WrLeh")) return False;
1219 if (!check_share_info(uLevel,str2)) return False;
1221 data_len = fixed_len = string_len = 0;
1222 for (i=0;i<count;i++)
1223 if (lp_browseable(i) && lp_snum_ok(i))
1226 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1227 if (data_len <= buf_len)
1231 string_len += s_len;
1234 *rdata_len = fixed_len + string_len;
1235 *rdata = REALLOC(*rdata,*rdata_len);
1236 memset(*rdata,0,*rdata_len);
1238 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1242 for (i = 0; i < count;i++)
1243 if (lp_browseable(i) && lp_snum_ok(i))
1244 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1248 *rparam = REALLOC(*rparam,*rparam_len);
1249 SSVAL(*rparam,0,NERR_Success);
1251 SSVAL(*rparam,4,counted);
1252 SSVAL(*rparam,6,total);
1254 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1255 counted,total,uLevel,
1256 buf_len,*rdata_len,mdrcnt));
1262 /****************************************************************************
1263 get the time of day info
1264 ****************************************************************************/
1265 static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
1266 int mdrcnt,int mprcnt,
1267 char **rdata,char **rparam,
1268 int *rdata_len,int *rparam_len)
1272 *rparam = REALLOC(*rparam,*rparam_len);
1275 *rdata = REALLOC(*rdata,*rdata_len);
1277 SSVAL(*rparam,0,NERR_Success);
1278 SSVAL(*rparam,2,0); /* converter word */
1284 time_t unixdate = time(NULL);
1286 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1287 by NT in a "net time" operation,
1288 it seems to ignore the one below */
1290 /* the client expects to get localtime, not GMT, in this bit
1291 (I think, this needs testing) */
1292 t = LocalTime(&unixdate,GMT_TO_LOCAL);
1294 SIVAL(p,4,0); /* msecs ? */
1295 CVAL(p,8) = t->tm_hour;
1296 CVAL(p,9) = t->tm_min;
1297 CVAL(p,10) = t->tm_sec;
1298 CVAL(p,11) = 0; /* hundredths of seconds */
1299 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1300 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1301 CVAL(p,16) = t->tm_mday;
1302 CVAL(p,17) = t->tm_mon + 1;
1303 SSVAL(p,18,1900+t->tm_year);
1304 CVAL(p,20) = t->tm_wday;
1311 /****************************************************************************
1312 set the user password
1313 ****************************************************************************/
1314 static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
1315 int mdrcnt,int mprcnt,
1316 char **rdata,char **rparam,
1317 int *rdata_len,int *rparam_len)
1319 char *p = skip_string(param+2,2);
1321 fstring pass1,pass2;
1325 p = skip_string(p,1);
1327 StrnCpy(pass1,p,16);
1328 StrnCpy(pass2,p+16,16);
1331 *rparam = REALLOC(*rparam,*rparam_len);
1335 SSVAL(*rparam,0,NERR_Success);
1336 SSVAL(*rparam,2,0); /* converter word */
1338 DEBUG(3,("Set password for <%s>\n",user));
1340 if (!password_ok(user,pass1,strlen(pass1),NULL,False) ||
1341 !chgpasswd(user,pass1,pass2))
1342 SSVAL(*rparam,0,NERR_badpass);
1344 bzero(pass1,sizeof(fstring));
1345 bzero(pass2,sizeof(fstring));
1350 /****************************************************************************
1353 ****************************************************************************/
1354 static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
1355 int mdrcnt,int mprcnt,
1356 char **rdata,char **rparam,
1357 int *rdata_len,int *rparam_len)
1359 int function = SVAL(param,0);
1360 char *str1 = param+2;
1361 char *str2 = skip_string(str1,1);
1362 char *p = skip_string(str2,1);
1363 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1364 by the print queue api */
1365 int snum = (SVAL(p,0)>>8);
1369 /* check it's a supported varient */
1370 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1374 *rparam = REALLOC(*rparam,*rparam_len);
1378 SSVAL(*rparam,0,NERR_Success);
1380 if (snum >= 0 && VALID_SNUM(snum))
1382 print_queue_struct *queue=NULL;
1384 count = get_printqueue(snum,cnum,&queue,NULL);
1386 for (i=0;i<count;i++)
1387 if ((queue[i].job%0xFF) == jobid)
1390 case 81: /* delete */
1391 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1392 del_printqueue(cnum,snum,queue[i].job);
1394 case 82: /* pause */
1395 case 83: /* resume */
1396 DEBUG(3,("%s queue entry %d\n",
1397 (function==82?"pausing":"resuming"),queue[i].job));
1398 status_printjob(cnum,snum,queue[i].job,
1399 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1406 SSVAL(*rparam,0,NERR_JobNotFound);
1408 if (queue) free(queue);
1411 SSVAL(*rparam,2,0); /* converter word */
1416 static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data,
1417 int mdrcnt,int mprcnt,
1418 char **rdata,char **rparam,
1419 int *rdata_len,int *rparam_len)
1421 char *str1 = param+2;
1422 char *str2 = skip_string(str1,1);
1423 char *QueueName = skip_string(str2,1);
1426 /* check it's a supported varient */
1427 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1431 *rparam = REALLOC(*rparam,*rparam_len);
1435 SSVAL(*rparam,0,NERR_Success);
1436 SSVAL(*rparam,2,0); /* converter word */
1438 snum = lp_servicenumber(QueueName);
1439 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1440 int pnum = lp_servicenumber(PRINTERS_NAME);
1442 lp_add_printer(QueueName,pnum);
1443 snum = lp_servicenumber(QueueName);
1447 if (snum >= 0 && VALID_SNUM(snum)) {
1448 print_queue_struct *queue=NULL;
1452 count = get_printqueue(snum,cnum,&queue,NULL);
1453 for (i = 0; i < count; i++)
1454 del_printqueue(cnum,snum,queue[i].job);
1456 if (queue) free(queue);
1459 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1465 /****************************************************************************
1466 set the property of a print job (undocumented?)
1467 ? function = 0xb -> set name of print job
1468 ? function = 0x6 -> move print job up/down
1469 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1470 or <WWsTP> <WB21BB16B10zWWzDDz>
1471 ****************************************************************************/
1472 static int check_printjob_info(struct pack_desc* desc,
1473 int uLevel, char* id)
1475 desc->subformat = NULL;
1477 case 0: desc->format = "W"; break;
1478 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1479 case 2: desc->format = "WWzWWDDzz"; break;
1480 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1481 default: return False;
1483 if (strcmp(desc->format,id) != 0) return False;
1487 static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
1488 int mdrcnt,int mprcnt,
1489 char **rdata,char **rparam,
1490 int *rdata_len,int *rparam_len)
1492 struct pack_desc desc;
1493 char *str1 = param+2;
1494 char *str2 = skip_string(str1,1);
1495 char *p = skip_string(str2,1);
1496 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1497 by the print queue api */
1498 int snum = (SVAL(p,0)>>8);
1499 int uLevel = SVAL(p,2);
1500 int function = SVAL(p,4); /* what is this ?? */
1505 *rparam = REALLOC(*rparam,*rparam_len);
1509 /* check it's a supported varient */
1510 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1514 case 0x6: /* change job place in the queue, data gives the new place */
1515 if (snum >= 0 && VALID_SNUM(snum))
1517 print_queue_struct *queue=NULL;
1521 count = get_printqueue(snum,cnum,&queue,NULL);
1522 for (i=0;i<count;i++) /* find job */
1523 if ((queue[i].job%0xFF) == jobid) break;
1526 desc.errcode=NERR_JobNotFound;
1527 if (queue) free(queue);
1530 desc.errcode=NERR_Success;
1534 int place= SVAL(data,0);
1535 /* we currently have no way of doing this. Can any unix do it? */
1536 if (i < place) /* move down */;
1537 else if (i > place ) /* move up */;
1540 desc.errcode=NERR_notsupported; /* not yet supported */
1541 if (queue) free(queue);
1544 else desc.errcode=NERR_JobNotFound;
1546 case 0xb: /* change print job name, data gives the name */
1547 /* jobid, snum should be zero */
1554 if (issafe(*s)) name[l++] = *s;
1559 DEBUG(3,("Setting print name to %s\n",name));
1561 for (i=0;i<MAX_OPEN_FILES;i++)
1562 if (Files[i].open && Files[i].print_file)
1568 if (!become_user(Files[i].cnum,uid) ||
1569 !become_service(Files[i].cnum,True))
1572 if (sys_rename(Files[i].name,name) == 0)
1573 string_set(&Files[i].name,name);
1577 desc.errcode=NERR_Success;
1580 default: /* not implemented */
1584 SSVALS(*rparam,0,desc.errcode);
1585 SSVAL(*rparam,2,0); /* converter word */
1591 /****************************************************************************
1592 get info about the server
1593 ****************************************************************************/
1594 static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
1595 int mdrcnt,int mprcnt,
1596 char **rdata,char **rparam,
1597 int *rdata_len,int *rparam_len)
1599 char *str1 = param+2;
1600 char *str2 = skip_string(str1,1);
1601 char *p = skip_string(str2,1);
1602 int uLevel = SVAL(p,0);
1606 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1608 /* check it's a supported varient */
1609 if (!prefix_ok(str1,"WrLh")) return False;
1612 if (strcmp(str2,"B16") != 0) return False;
1616 if (strcmp(str2,"B16BBDz") != 0) return False;
1620 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1625 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1630 if (strcmp(str2,"DN") != 0) return False;
1634 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1637 default: return False;
1640 *rdata_len = mdrcnt;
1641 *rdata = REALLOC(*rdata,*rdata_len);
1644 p2 = p + struct_len;
1646 StrnCpy(p,local_machine,16);
1652 struct srv_info_struct *servers=NULL;
1655 uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION|
1656 SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE;
1658 strcpy(comment,lp_serverstring());
1660 if ((count=get_server_info(SV_TYPE_ALL,&servers))>0) {
1661 for (i=0;i<count;i++)
1662 if (strequal(servers[i].name,local_machine)) {
1663 servertype = servers[i].type;
1664 strcpy(comment,servers[i].comment);
1667 if (servers) free(servers);
1669 SCVAL(p,0,2); /* version_major */
1670 SCVAL(p,1,0); /* version_minor */
1671 SIVAL(p,2,servertype);
1672 if (mdrcnt == struct_len) {
1675 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1676 standard_sub(cnum,comment);
1677 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1678 p2 = skip_string(p2,1);
1683 return False; /* not yet implemented */
1686 *rdata_len = PTR_DIFF(p2,*rdata);
1689 *rparam = REALLOC(*rparam,*rparam_len);
1690 SSVAL(*rparam,0,NERR_Success);
1691 SSVAL(*rparam,2,0); /* converter word */
1692 SSVAL(*rparam,4,*rdata_len);
1698 /****************************************************************************
1699 get info about the server
1700 ****************************************************************************/
1701 static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
1702 int mdrcnt,int mprcnt,
1703 char **rdata,char **rparam,
1704 int *rdata_len,int *rparam_len)
1706 char *str1 = param+2;
1707 char *str2 = skip_string(str1,1);
1708 char *p = skip_string(str2,1);
1710 extern pstring sesssetup_user;
1711 int level = SVAL(p,0);
1713 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1716 *rparam = REALLOC(*rparam,*rparam_len);
1718 /* check it's a supported varient */
1719 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1722 *rdata_len = mdrcnt + 1024;
1723 *rdata = REALLOC(*rdata,*rdata_len);
1725 SSVAL(*rparam,0,NERR_Success);
1726 SSVAL(*rparam,2,0); /* converter word */
1731 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1732 strcpy(p2,local_machine);
1733 p2 = skip_string(p2,1);
1736 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1737 strcpy(p2,sesssetup_user);
1738 p2 = skip_string(p2,1);
1741 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1742 strcpy(p2,my_workgroup());
1743 p2 = skip_string(p2,1);
1746 SCVAL(p,0,2); /* major version?? */
1747 SCVAL(p,1,1); /* minor version?? */
1750 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1751 strcpy(p2,my_workgroup()); /* login domain?? */
1752 p2 = skip_string(p2,1);
1755 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1757 p2 = skip_string(p2,1);
1760 *rdata_len = PTR_DIFF(p2,*rdata);
1762 SSVAL(*rparam,4,*rdata_len);
1768 /****************************************************************************
1769 get info about a user
1770 ****************************************************************************/
1772 #define USER_PRIV_GUEST 0
1773 #define USER_PRIV_USER 1
1774 #define USER_PRIV_ADMIN 2
1776 static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
1777 int mdrcnt,int mprcnt,
1778 char **rdata,char **rparam,
1779 int *rdata_len,int *rparam_len)
1781 char *str1 = param+2;
1782 char *str2 = skip_string(str1,1);
1783 char *UserName = skip_string(str2,1);
1784 char *p = skip_string(UserName,1);
1785 int uLevel = SVAL(p,0);
1789 *rparam = REALLOC(*rparam,*rparam_len);
1791 /* check it's a supported varient */
1792 if (strcmp(str1,"zWrLh") != 0) return False;
1794 case 0: p2 = "B21"; break;
1795 case 1: p2 = "B21BB16DWzzWz"; break;
1796 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1797 case 10: p2 = "B21Bzzz"; break;
1798 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1799 default: return False;
1801 if (strcmp(p2,str2) != 0) return False;
1803 *rdata_len = mdrcnt + 1024;
1804 *rdata = REALLOC(*rdata,*rdata_len);
1806 SSVAL(*rparam,0,NERR_Success);
1807 SSVAL(*rparam,2,0); /* converter word */
1818 SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
1819 strcpy(p2,"<Comment>");
1820 p2 = skip_string(p2,1);
1821 SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
1822 strcpy(p2,"<UserComment>");
1823 p2 = skip_string(p2,1);
1824 SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
1825 strcpy(p2,"<FullName>");
1826 p2 = skip_string(p2,1);
1828 if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
1829 SSVAL(p,34,USER_PRIV_USER); /* user privilege */
1830 SIVAL(p,36,0); /* auth flags */
1831 SIVALS(p,40,-1); /* password age */
1832 SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
1833 strcpy(p2,"\\\\%L\\HOMES");
1834 standard_sub_basic(p2);
1835 p2 = skip_string(p2,1);
1836 SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
1838 p2 = skip_string(p2,1);
1839 SIVAL(p,52,0); /* last logon */
1840 SIVAL(p,56,0); /* last logoff */
1841 SSVALS(p,60,-1); /* bad pw counts */
1842 SSVALS(p,62,-1); /* num logons */
1843 SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
1845 p2 = skip_string(p2,1);
1846 SSVAL(p,68,0); /* country code */
1848 SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
1850 p2 = skip_string(p2,1);
1852 SIVALS(p,74,-1); /* max storage */
1853 SSVAL(p,78,168); /* units per week */
1854 SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
1856 SCVAL(p2,21,0); /* fix zero termination */
1857 p2 = skip_string(p2,1);
1859 SSVAL(p,84,0); /* code page */
1861 if (uLevel == 1 || uLevel == 2) {
1862 memset(p+22,' ',16); /* password */
1863 SIVALS(p,38,-1); /* password age */
1864 SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */
1865 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
1866 strcpy(p2,"\\\\%L\\HOMES");
1867 standard_sub_basic(p2);
1868 p2 = skip_string(p2,1);
1869 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
1871 SSVAL(p,52,0); /* flags */
1872 SIVAL(p,54,0); /* script_path */
1874 SIVAL(p,60,0); /* auth_flags */
1875 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
1876 strcpy(p2,"<Full Name>");
1877 p2 = skip_string(p2,1);
1878 SIVAL(p,68,0); /* urs_comment */
1879 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
1881 p2 = skip_string(p2,1);
1882 SIVAL(p,76,0); /* workstations */
1883 SIVAL(p,80,0); /* last_logon */
1884 SIVAL(p,84,0); /* last_logoff */
1885 SIVALS(p,88,-1); /* acct_expires */
1886 SIVALS(p,92,-1); /* max_storage */
1887 SSVAL(p,96,168); /* units_per_week */
1888 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
1891 SSVALS(p,102,-1); /* bad_pw_count */
1892 SSVALS(p,104,-1); /* num_logons */
1893 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
1894 strcpy(p2,"\\\\%L");
1895 standard_sub_basic(p2);
1896 p2 = skip_string(p2,1);
1897 SSVAL(p,110,49); /* country_code */
1898 SSVAL(p,112,860); /* code page */
1903 *rdata_len = PTR_DIFF(p2,*rdata);
1905 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
1911 /*******************************************************************
1912 get groups that a user is a member of
1913 ******************************************************************/
1914 static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
1915 int mdrcnt,int mprcnt,
1916 char **rdata,char **rparam,
1917 int *rdata_len,int *rparam_len)
1919 char *str1 = param+2;
1920 char *str2 = skip_string(str1,1);
1921 char *UserName = skip_string(str2,1);
1922 char *p = skip_string(UserName,1);
1923 int uLevel = SVAL(p,0);
1928 *rparam = REALLOC(*rparam,*rparam_len);
1930 /* check it's a supported varient */
1931 if (strcmp(str1,"zWrLeh") != 0) return False;
1933 case 0: p2 = "B21"; break;
1934 default: return False;
1936 if (strcmp(p2,str2) != 0) return False;
1938 *rdata_len = mdrcnt + 1024;
1939 *rdata = REALLOC(*rdata,*rdata_len);
1941 SSVAL(*rparam,0,NERR_Success);
1942 SSVAL(*rparam,2,0); /* converter word */
1946 /* XXXX we need a real SAM database some day */
1947 strcpy(p,"Users"); p += 21; count++;
1948 strcpy(p,"Domain Users"); p += 21; count++;
1949 strcpy(p,"Guests"); p += 21; count++;
1950 strcpy(p,"Domain Guests"); p += 21; count++;
1952 *rdata_len = PTR_DIFF(p,*rdata);
1954 SSVAL(*rparam,4,count); /* is this right?? */
1955 SSVAL(*rparam,6,count); /* is this right?? */
1961 static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
1962 int mdrcnt,int mprcnt,
1963 char **rdata,char **rparam,
1964 int *rdata_len,int *rparam_len)
1966 char *str1 = param+2;
1967 char *str2 = skip_string(str1,1);
1968 char *p = skip_string(str2,1);
1970 struct pack_desc desc;
1976 bzero(&desc,sizeof(desc));
1978 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
1980 /* check it's a supported varient */
1981 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
1982 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
1983 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
1985 desc.buflen = mdrcnt;
1986 desc.subformat = NULL;
1991 if (init_package(&desc,1,0)) {
1992 PACKI(&desc,"W",0); /* code */
1993 PACKS(&desc,"B21",name); /* eff. name */
1994 PACKS(&desc,"B",""); /* pad */
1996 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
1997 PACKI(&desc,"D",0); /* auth flags XXX */
1998 PACKI(&desc,"W",0); /* num logons */
1999 PACKI(&desc,"W",0); /* bad pw count */
2000 PACKI(&desc,"D",-1); /* last logon */
2001 PACKI(&desc,"D",-1); /* last logoff */
2002 PACKI(&desc,"D",-1); /* logoff time */
2003 PACKI(&desc,"D",-1); /* kickoff time */
2004 PACKI(&desc,"D",0); /* password age */
2005 PACKI(&desc,"D",0); /* password can change */
2006 PACKI(&desc,"D",-1); /* password must change */
2009 strcpy(mypath,"\\\\");
2010 strcat(mypath,local_machine);
2012 PACKS(&desc,"z",mypath); /* computer */
2014 PACKS(&desc,"z",my_workgroup());/* domain */
2015 PACKS(&desc,"z",lp_logon_script()); /* script path */
2016 PACKI(&desc,"D",0); /* reserved */
2019 *rdata_len = desc.usedlen;
2021 *rparam = REALLOC(*rparam,*rparam_len);
2022 SSVALS(*rparam,0,desc.errcode);
2024 SSVAL(*rparam,4,desc.neededlen);
2026 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2031 /****************************************************************************
2032 api_WAccessGetUserPerms
2033 ****************************************************************************/
2034 static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
2035 int mdrcnt,int mprcnt,
2036 char **rdata,char **rparam,
2037 int *rdata_len,int *rparam_len)
2039 char *str1 = param+2;
2040 char *str2 = skip_string(str1,1);
2041 char *user = skip_string(str2,1);
2042 char *resource = skip_string(user,1);
2044 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2046 /* check it's a supported varient */
2047 if (strcmp(str1,"zzh") != 0) return False;
2048 if (strcmp(str2,"") != 0) return False;
2051 *rparam = REALLOC(*rparam,*rparam_len);
2052 SSVALS(*rparam,0,0); /* errorcode */
2053 SSVAL(*rparam,2,0); /* converter word */
2054 SSVAL(*rparam,4,0x7f); /* permission flags */
2059 /****************************************************************************
2060 api_WPrintJobEnumerate
2061 ****************************************************************************/
2062 static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
2063 int mdrcnt,int mprcnt,
2064 char **rdata,char **rparam,
2065 int *rdata_len,int *rparam_len)
2067 char *str1 = param+2;
2068 char *str2 = skip_string(str1,1);
2069 char *p = skip_string(str2,1);
2070 int uJobId = SVAL(p,0);
2076 struct pack_desc desc;
2077 print_queue_struct *queue=NULL;
2078 print_status_struct status;
2083 bzero(&desc,sizeof(desc));
2084 bzero(&status,sizeof(status));
2086 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2088 /* check it's a supported varient */
2089 if (strcmp(str1,"WWrLh") != 0) return False;
2090 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2092 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2093 job = uJobId & 0xFF;
2095 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2097 count = get_printqueue(snum,cnum,&queue,&status);
2098 for (i = 0; i < count; i++) {
2099 if ((queue[i].job % 0xFF) == job) break;
2101 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2103 desc.buflen = mdrcnt;
2105 if (init_package(&desc,1,0)) {
2107 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2108 *rdata_len = desc.usedlen;
2111 desc.errcode = NERR_JobNotFound;
2117 *rparam = REALLOC(*rparam,*rparam_len);
2118 SSVALS(*rparam,0,desc.errcode);
2120 SSVAL(*rparam,4,desc.neededlen);
2122 if (queue) free(queue);
2124 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2128 static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
2129 int mdrcnt,int mprcnt,
2130 char **rdata,char **rparam,
2131 int *rdata_len,int *rparam_len)
2133 char *str1 = param+2;
2134 char *str2 = skip_string(str1,1);
2135 char *p = skip_string(str2,1);
2141 struct pack_desc desc;
2142 print_queue_struct *queue=NULL;
2143 print_status_struct status;
2145 bzero(&desc,sizeof(desc));
2146 bzero(&status,sizeof(status));
2148 p = skip_string(p,1);
2152 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2154 /* check it's a supported varient */
2155 if (strcmp(str1,"zWrLeh") != 0) return False;
2156 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2157 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2159 snum = lp_servicenumber(name);
2160 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2161 int pnum = lp_servicenumber(PRINTERS_NAME);
2163 lp_add_printer(name,pnum);
2164 snum = lp_servicenumber(name);
2168 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2170 count = get_printqueue(snum,cnum,&queue,&status);
2171 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2173 desc.buflen = mdrcnt;
2175 if (init_package(&desc,count,0)) {
2177 for (i = 0; i < count; i++) {
2178 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2179 if (desc.errcode == NERR_Success) succnt = i+1;
2183 *rdata_len = desc.usedlen;
2186 *rparam = REALLOC(*rparam,*rparam_len);
2187 SSVALS(*rparam,0,desc.errcode);
2189 SSVAL(*rparam,4,succnt);
2190 SSVAL(*rparam,6,count);
2192 if (queue) free(queue);
2194 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2198 static int check_printdest_info(struct pack_desc* desc,
2199 int uLevel, char* id)
2201 desc->subformat = NULL;
2203 case 0: desc->format = "B9"; break;
2204 case 1: desc->format = "B9B21WWzW"; break;
2205 case 2: desc->format = "z"; break;
2206 case 3: desc->format = "zzzWWzzzWW"; break;
2207 default: return False;
2209 if (strcmp(desc->format,id) != 0) return False;
2213 static void fill_printdest_info(int cnum, int snum, int uLevel,
2214 struct pack_desc* desc)
2217 strcpy(buf,SERVICE(snum));
2220 PACKS(desc,"B9",buf); /* szName */
2222 PACKS(desc,"B21",""); /* szUserName */
2223 PACKI(desc,"W",0); /* uJobId */
2224 PACKI(desc,"W",0); /* fsStatus */
2225 PACKS(desc,"z",""); /* pszStatus */
2226 PACKI(desc,"W",0); /* time */
2229 if (uLevel == 2 || uLevel == 3) {
2230 PACKS(desc,"z",buf); /* pszPrinterName */
2232 PACKS(desc,"z",""); /* pszUserName */
2233 PACKS(desc,"z",""); /* pszLogAddr */
2234 PACKI(desc,"W",0); /* uJobId */
2235 PACKI(desc,"W",0); /* fsStatus */
2236 PACKS(desc,"z",""); /* pszStatus */
2237 PACKS(desc,"z",""); /* pszComment */
2238 PACKS(desc,"z","NULL"); /* pszDrivers */
2239 PACKI(desc,"W",0); /* time */
2240 PACKI(desc,"W",0); /* pad1 */
2245 static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
2246 int mdrcnt,int mprcnt,
2247 char **rdata,char **rparam,
2248 int *rdata_len,int *rparam_len)
2250 char *str1 = param+2;
2251 char *str2 = skip_string(str1,1);
2252 char *p = skip_string(str2,1);
2253 char* PrinterName = p;
2255 struct pack_desc desc;
2258 bzero(&desc,sizeof(desc));
2260 p = skip_string(p,1);
2264 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2266 /* check it's a supported varient */
2267 if (strcmp(str1,"zWrLh") != 0) return False;
2268 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2270 snum = lp_servicenumber(PrinterName);
2271 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2272 int pnum = lp_servicenumber(PRINTERS_NAME);
2274 lp_add_printer(PrinterName,pnum);
2275 snum = lp_servicenumber(PrinterName);
2281 desc.errcode = NERR_DestNotFound;
2285 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2287 desc.buflen = mdrcnt;
2288 if (init_package(&desc,1,0)) {
2289 fill_printdest_info(cnum,snum,uLevel,&desc);
2291 *rdata_len = desc.usedlen;
2295 *rparam = REALLOC(*rparam,*rparam_len);
2296 SSVALS(*rparam,0,desc.errcode);
2298 SSVAL(*rparam,4,desc.neededlen);
2300 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2304 static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
2305 int mdrcnt,int mprcnt,
2306 char **rdata,char **rparam,
2307 int *rdata_len,int *rparam_len)
2309 char *str1 = param+2;
2310 char *str2 = skip_string(str1,1);
2311 char *p = skip_string(str2,1);
2315 struct pack_desc desc;
2316 int services = lp_numservices();
2318 bzero(&desc,sizeof(desc));
2323 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2325 /* check it's a supported varient */
2326 if (strcmp(str1,"WrLeh") != 0) return False;
2327 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2330 for (i = 0; i < services; i++)
2331 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2334 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2336 desc.buflen = mdrcnt;
2337 if (init_package(&desc,queuecnt,0)) {
2340 for (i = 0; i < services; i++) {
2341 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2342 fill_printdest_info(cnum,i,uLevel,&desc);
2344 if (desc.errcode == NERR_Success) succnt = n;
2349 *rdata_len = desc.usedlen;
2352 *rparam = REALLOC(*rparam,*rparam_len);
2353 SSVALS(*rparam,0,desc.errcode);
2355 SSVAL(*rparam,4,succnt);
2356 SSVAL(*rparam,6,queuecnt);
2358 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2362 static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
2363 int mdrcnt,int mprcnt,
2364 char **rdata,char **rparam,
2365 int *rdata_len,int *rparam_len)
2367 char *str1 = param+2;
2368 char *str2 = skip_string(str1,1);
2369 char *p = skip_string(str2,1);
2372 struct pack_desc desc;
2374 bzero(&desc,sizeof(desc));
2379 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2381 /* check it's a supported varient */
2382 if (strcmp(str1,"WrLeh") != 0) return False;
2383 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2385 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2387 desc.buflen = mdrcnt;
2388 if (init_package(&desc,1,0)) {
2389 PACKS(&desc,"B41","NULL");
2392 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2394 *rdata_len = desc.usedlen;
2397 *rparam = REALLOC(*rparam,*rparam_len);
2398 SSVALS(*rparam,0,desc.errcode);
2400 SSVAL(*rparam,4,succnt);
2403 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2407 static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
2408 int mdrcnt,int mprcnt,
2409 char **rdata,char **rparam,
2410 int *rdata_len,int *rparam_len)
2412 char *str1 = param+2;
2413 char *str2 = skip_string(str1,1);
2414 char *p = skip_string(str2,1);
2417 struct pack_desc desc;
2419 bzero(&desc,sizeof(desc));
2424 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2426 /* check it's a supported varient */
2427 if (strcmp(str1,"WrLeh") != 0) return False;
2428 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2430 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2432 desc.buflen = mdrcnt;
2434 if (init_package(&desc,1,0)) {
2435 PACKS(&desc,"B13","lpd");
2438 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2440 *rdata_len = desc.usedlen;
2443 *rparam = REALLOC(*rparam,*rparam_len);
2444 SSVALS(*rparam,0,desc.errcode);
2446 SSVAL(*rparam,4,succnt);
2449 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2453 static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
2454 int mdrcnt,int mprcnt,
2455 char **rdata,char **rparam,
2456 int *rdata_len,int *rparam_len)
2458 char *str1 = param+2;
2459 char *str2 = skip_string(str1,1);
2460 char *p = skip_string(str2,1);
2463 struct pack_desc desc;
2465 bzero(&desc,sizeof(desc));
2470 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2472 /* check it's a supported varient */
2473 if (strcmp(str1,"WrLeh") != 0) return False;
2474 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2476 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2477 bzero(&desc,sizeof(desc));
2479 desc.buflen = mdrcnt;
2481 if (init_package(&desc,1,0)) {
2482 PACKS(&desc,"B13","lp0");
2485 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2487 *rdata_len = desc.usedlen;
2490 *rparam = REALLOC(*rparam,*rparam_len);
2491 SSVALS(*rparam,0,desc.errcode);
2493 SSVAL(*rparam,4,succnt);
2496 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2500 /****************************************************************************
2501 the buffer was too small
2502 ****************************************************************************/
2503 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
2504 int mdrcnt,int mprcnt,
2505 char **rdata,char **rparam,
2506 int *rdata_len,int *rparam_len)
2508 *rparam_len = MIN(*rparam_len,mprcnt);
2509 *rparam = REALLOC(*rparam,*rparam_len);
2513 SSVAL(*rparam,0,NERR_BufTooSmall);
2515 DEBUG(3,("Supplied buffer too small in API command\n"));
2521 /****************************************************************************
2522 the request is not supported
2523 ****************************************************************************/
2524 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
2525 int mdrcnt,int mprcnt,
2526 char **rdata,char **rparam,
2527 int *rdata_len,int *rparam_len)
2530 *rparam = REALLOC(*rparam,*rparam_len);
2534 SSVAL(*rparam,0,NERR_notsupported);
2535 SSVAL(*rparam,2,0); /* converter word */
2537 DEBUG(3,("Unsupported API command\n"));
2551 } api_commands[] = {
2552 {"RNetShareEnum", 0, api_RNetShareEnum,0},
2553 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
2554 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
2555 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
2556 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
2557 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
2558 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
2559 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
2560 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
2561 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
2562 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
2563 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
2564 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
2565 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
2566 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
2567 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
2568 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
2569 {"NetServerEnum", 104, api_RNetServerEnum,0},
2570 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
2571 {"SetUserPassword", 115, api_SetUserPassword,0},
2572 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
2573 {"PrintJobInfo", 147, api_PrintJobInfo,0},
2574 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
2575 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
2576 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
2577 {NULL, -1, api_Unsupported,0}};
2580 /****************************************************************************
2581 handle remote api calls
2582 ****************************************************************************/
2583 static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
2584 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2586 int api_command = SVAL(params,0);
2588 char *rparam = NULL;
2594 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2595 api_command,params+2,skip_string(params+2,1),
2596 tdscnt,tpscnt,mdrcnt,mprcnt));
2598 for (i=0;api_commands[i].name;i++)
2599 if (api_commands[i].id == api_command && api_commands[i].fn)
2601 DEBUG(3,("Doing %s\n",api_commands[i].name));
2605 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2606 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2608 reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2609 &rdata,&rparam,&rdata_len,&rparam_len);
2612 if (rdata_len > mdrcnt ||
2613 rparam_len > mprcnt)
2615 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2616 &rdata,&rparam,&rdata_len,&rparam_len);
2620 /* if we get False back then it's actually unsupported */
2622 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2623 &rdata,&rparam,&rdata_len,&rparam_len);
2627 /* now send the reply */
2628 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2638 /****************************************************************************
2639 handle named pipe commands
2640 ****************************************************************************/
2641 static int named_pipe(int cnum,int uid, char *outbuf,char *name,
2642 uint16 *setup,char *data,char *params,
2643 int suwcnt,int tdscnt,int tpscnt,
2644 int msrcnt,int mdrcnt,int mprcnt)
2647 if (strequal(name,"LANMAN"))
2648 return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2650 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2651 name,(int)setup[0],(int)setup[1]));
2657 /****************************************************************************
2659 ****************************************************************************/
2660 int reply_trans(char *inbuf,char *outbuf)
2664 char *data=NULL,*params=NULL;
2668 int cnum = SVAL(inbuf,smb_tid);
2669 int uid = SVAL(inbuf,smb_uid);
2671 int tpscnt = SVAL(inbuf,smb_vwv0);
2672 int tdscnt = SVAL(inbuf,smb_vwv1);
2673 int mprcnt = SVAL(inbuf,smb_vwv2);
2674 int mdrcnt = SVAL(inbuf,smb_vwv3);
2675 int msrcnt = CVAL(inbuf,smb_vwv4);
2676 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2677 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2678 int pscnt = SVAL(inbuf,smb_vwv9);
2679 int psoff = SVAL(inbuf,smb_vwv10);
2680 int dscnt = SVAL(inbuf,smb_vwv11);
2681 int dsoff = SVAL(inbuf,smb_vwv12);
2682 int suwcnt = CVAL(inbuf,smb_vwv13);
2684 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2688 data = (char *)malloc(tdscnt);
2689 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2693 params = (char *)malloc(tpscnt);
2694 memcpy(params,smb_base(inbuf)+psoff,pscnt);
2700 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
2701 for (i=0;i<suwcnt;i++)
2702 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
2706 if (pscnt < tpscnt || dscnt < tdscnt)
2708 /* We need to send an interim response then receive the rest
2709 of the parameter/data bytes */
2710 outsize = set_message(outbuf,0,0,True);
2712 send_smb(Client,outbuf);
2715 /* receive the rest of the trans packet */
2716 while (pscnt < tpscnt || dscnt < tdscnt)
2718 int pcnt,poff,dcnt,doff,pdisp,ddisp;
2720 receive_smb(Client,inbuf, 0);
2723 /* Ensure this is still a trans packet (sanity check) */
2724 if(CVAL(inbuf, smb_com) != SMBtrans)
2726 DEBUG(2,("Invalid secondary trans2 packet\n"));
2727 if (params) free(params);
2728 if (data) free(data);
2729 if (setup) free(setup);
2730 return(ERROR(ERRSRV,ERRerror));
2733 tpscnt = SVAL(inbuf,smb_vwv0);
2734 tdscnt = SVAL(inbuf,smb_vwv1);
2736 pcnt = SVAL(inbuf,smb_vwv2);
2737 poff = SVAL(inbuf,smb_vwv3);
2738 pdisp = SVAL(inbuf,smb_vwv4);
2740 dcnt = SVAL(inbuf,smb_vwv5);
2741 doff = SVAL(inbuf,smb_vwv6);
2742 ddisp = SVAL(inbuf,smb_vwv7);
2748 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
2750 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
2754 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
2757 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
2758 outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
2759 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
2762 if (data) free(data);
2763 if (params) free(params);
2764 if (setup) free(setup);
2766 if (close_on_completion)
2767 close_cnum(cnum,uid);
2773 return(ERROR(ERRSRV,ERRnosupport));