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 */
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",t); /* 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",t); /* 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,
755 char *domain, uint32 request)
759 if (strequal(lp_workgroup(), server->domain)) {
764 DEBUG(4,("primary domain:reject %8x %s %s\n",request,server->name,server->domain));
767 else if ((request & SV_TYPE_DOMAIN_ENUM) &&
768 (server->type & SV_TYPE_DOMAIN_ENUM))
770 DEBUG(4,("rej:DOM %8x: %s %s\n",server->type,server->name,server->domain));
778 if (strequal(domain, server->domain))
781 if (request == SV_TYPE_LOCAL_LIST_ONLY &&
782 !(server->type & SV_TYPE_LOCAL_LIST_ONLY))
784 DEBUG(4,("rej:LOC %8x: ok %s %s\n",request,server->name,server->domain));
788 if ((request == (SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM)) &&
789 !(server->type&SV_TYPE_DOMAIN_ENUM))
791 DEBUG(4,("rej:LOCDOM %8x: ok %s %s\n",request,server->name,server->domain));
799 DEBUG(4,("domain:%s %s %s\n",domain,server->name,server->domain));
806 /*******************************************************************
807 get server info lists from the files saved by nmbd. Return the
809 ******************************************************************/
810 static int get_server_info(uint32 servertype,
811 struct srv_info_struct **servers, BOOL domains,
820 strcpy(fname,lp_lockdir());
821 trim_string(fname,NULL,"/");
823 strcat(fname,SERVER_LIST);
825 f = fopen(fname,"r");
828 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
832 /* request for everything is code for request all servers */
833 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
835 DEBUG(4,("Servertype search: %8x domains:%s\n",servertype,BOOLSTR(domains)));
840 struct srv_info_struct *s;
845 fgets(line,sizeof(line)-1,f);
846 if (!*line) continue;
848 if (count == alloced) {
850 (*servers) = (struct srv_info_struct *)
851 Realloc(*servers,sizeof(**servers)*alloced);
852 if (!(*servers)) return(0);
853 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
855 s = &(*servers)[count];
857 if (!next_token(&ptr,s->name , NULL)) continue;
858 if (!next_token(&ptr,stype , NULL)) continue;
859 if (!next_token(&ptr,s->comment, NULL)) continue;
860 if (!next_token(&ptr,s->domain , NULL)) {
861 /* this allows us to cope with an old nmbd */
862 strcpy(s->domain,my_workgroup());
865 if (sscanf(stype,"%X",&s->type) != 1) {
866 DEBUG(4,("r:host file "));
870 /* doesn't match up: don't want it */
871 if (!(servertype & s->type)) {
872 DEBUG(4,("r:serv type "));
876 if ((servertype == ~SV_TYPE_DOMAIN_ENUM) &&
877 (s->type & SV_TYPE_DOMAIN_ENUM))
879 DEBUG(4,("s:all x dom "));
883 if (domains && !(domain && *domain && strequal(domain, s->domain)))
885 if (!(s->type & SV_TYPE_DOMAIN_ENUM))
887 DEBUG(4,("r:dom enum "));
894 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
895 s->name, s->type, s->comment, s->domain));
897 s->type |= SV_TYPE_LOCAL_LIST_ONLY;
898 s->server_added = True;
903 DEBUG(4,("%20s %8x %25s %15s\n",
904 s->name, s->type, s->comment, s->domain));
913 /*******************************************************************
914 fill in a server info structure
915 ******************************************************************/
916 static int fill_srv_info(struct srv_info_struct *service,
917 int uLevel, char **buf, int *buflen,
918 char **stringbuf, int *stringspace, char *baseaddr)
927 case 0: struct_len = 16; break;
928 case 1: struct_len = 26; break;
938 len = strlen(service->comment)+1;
942 if (buflen) *buflen = struct_len;
943 if (stringspace) *stringspace = len;
944 return struct_len + len;
949 if (*buflen < struct_len) return -1;
958 l2 = *buflen - struct_len;
960 if (!baseaddr) baseaddr = p;
965 StrnCpy(p,service->name,15);
969 StrnCpy(p,service->name,15);
970 SIVAL(p,18,service->type);
971 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
972 len += CopyAndAdvance(&p2,service->comment,&l2);
978 *buf = p + struct_len;
979 *buflen -= struct_len;
992 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
994 return(strcmp(s1->name,s2->name));
997 /****************************************************************************
998 view list of servers available (or possibly domains). The info is
999 extracted from lists saved by nmbd on the local host
1000 ****************************************************************************/
1001 static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
1002 int mdrcnt, int mprcnt, char **rdata,
1003 char **rparam, int *rdata_len, int *rparam_len)
1005 char *str1 = param+2;
1006 char *str2 = skip_string(str1,1);
1007 char *p = skip_string(str2,1);
1008 int uLevel = SVAL(p,0);
1009 int buf_len = SVAL(p,2);
1010 uint32 servertype = IVAL(p,4);
1012 int data_len, fixed_len, string_len;
1014 struct srv_info_struct *servers=NULL;
1015 int counted=0,total=0;
1019 BOOL domain_request;
1020 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
1022 /*if (servertype == SV_TYPE_ALL) servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);*/
1023 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
1025 domain_request = servertype & SV_TYPE_DOMAIN_ENUM;
1030 if (!prefix_ok(str1,"WrLehD")) return False;
1031 if (!check_server_info(uLevel,str2)) return False;
1033 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1034 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1035 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1037 if (strcmp(str1, "WrLehDO") == 0)
1041 else if (strcmp(str1, "WrLehDz") == 0)
1044 StrnCpy(domain, p, sizeof(fstring)-1);
1047 if (lp_browse_list())
1049 total = get_server_info(servertype,&servers,domains,domain);
1052 data_len = fixed_len = string_len = 0;
1054 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1057 char *lastname=NULL;
1059 for (i=0;i<total;i++)
1061 struct srv_info_struct *s = &servers[i];
1062 if (filter_server_info(s,domains,domain,
1063 local_request|domain_request))
1065 if (lastname && strequal(lastname,s->name)) continue;
1067 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1068 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1069 s->name, s->type, s->comment, s->domain));
1071 if (data_len <= buf_len)
1075 string_len += s_len;
1081 *rdata_len = fixed_len + string_len;
1082 *rdata = REALLOC(*rdata,*rdata_len);
1083 bzero(*rdata,*rdata_len);
1085 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1091 char *lastname=NULL;
1092 int count2 = counted;
1093 for (i = 0; i < total && count2;i++)
1095 struct srv_info_struct *s = &servers[i];
1096 if (filter_server_info(s,domains,domain,local_request|domain_request))
1098 if (lastname && strequal(lastname,s->name)) continue;
1100 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1101 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1102 s->name, s->type, s->comment, s->domain));
1109 *rparam = REALLOC(*rparam,*rparam_len);
1110 SSVAL(*rparam,0,NERR_Success);
1112 SSVAL(*rparam,4,counted);
1113 SSVAL(*rparam,6,total);
1115 if (servers) free(servers);
1117 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1118 domain,uLevel,counted,total));
1124 /****************************************************************************
1125 get info about a share
1126 ****************************************************************************/
1127 static BOOL check_share_info(int uLevel, char* id)
1131 if (strcmp(id,"B13") != 0) return False;
1134 if (strcmp(id,"B13BWz") != 0) return False;
1137 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1140 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1142 default: return False;
1147 static int fill_share_info(int cnum, int snum, int uLevel,
1148 char** buf, int* buflen,
1149 char** stringbuf, int* stringspace, char* baseaddr)
1158 case 0: struct_len = 13; break;
1159 case 1: struct_len = 20; break;
1160 case 2: struct_len = 40; break;
1161 case 91: struct_len = 68; break;
1169 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1170 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1171 if (buflen) *buflen = struct_len;
1172 if (stringspace) *stringspace = len;
1173 return struct_len + len;
1178 if ((*buflen) < struct_len) return -1;
1186 p2 = p + struct_len;
1187 l2 = (*buflen) - struct_len;
1189 if (!baseaddr) baseaddr = p;
1191 StrnCpy(p,lp_servicename(snum),13);
1197 type = STYPE_DISKTREE;
1198 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1199 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1200 SSVAL(p,14,type); /* device type */
1201 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1202 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1207 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1208 SSVALS(p,22,-1); /* max uses */
1209 SSVAL(p,24,1); /* current uses */
1210 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1211 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1212 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1217 memset(p+40,0,SHPWLEN+2);
1229 (*buf) = p + struct_len;
1230 (*buflen) -= struct_len;
1232 (*stringspace) = l2;
1242 static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
1243 int mdrcnt,int mprcnt,
1244 char **rdata,char **rparam,
1245 int *rdata_len,int *rparam_len)
1247 char *str1 = param+2;
1248 char *str2 = skip_string(str1,1);
1249 char *netname = skip_string(str2,1);
1250 char *p = skip_string(netname,1);
1251 int uLevel = SVAL(p,0);
1252 int snum = find_service(netname);
1254 if (snum < 0) return False;
1256 /* check it's a supported varient */
1257 if (!prefix_ok(str1,"zWrLh")) return False;
1258 if (!check_share_info(uLevel,str2)) return False;
1260 *rdata = REALLOC(*rdata,mdrcnt);
1262 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1263 if (*rdata_len < 0) return False;
1266 *rparam = REALLOC(*rparam,*rparam_len);
1267 SSVAL(*rparam,0,NERR_Success);
1268 SSVAL(*rparam,2,0); /* converter word */
1269 SSVAL(*rparam,4,*rdata_len);
1274 /****************************************************************************
1275 view list of shares available
1276 ****************************************************************************/
1277 static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
1278 int mdrcnt,int mprcnt,
1279 char **rdata,char **rparam,
1280 int *rdata_len,int *rparam_len)
1282 char *str1 = param+2;
1283 char *str2 = skip_string(str1,1);
1284 char *p = skip_string(str2,1);
1285 int uLevel = SVAL(p,0);
1286 int buf_len = SVAL(p,2);
1288 int count=lp_numservices();
1289 int total=0,counted=0;
1291 int data_len, fixed_len, string_len;
1294 if (!prefix_ok(str1,"WrLeh")) return False;
1295 if (!check_share_info(uLevel,str2)) return False;
1297 data_len = fixed_len = string_len = 0;
1298 for (i=0;i<count;i++)
1299 if (lp_browseable(i) && lp_snum_ok(i))
1302 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1303 if (data_len <= buf_len)
1307 string_len += s_len;
1310 *rdata_len = fixed_len + string_len;
1311 *rdata = REALLOC(*rdata,*rdata_len);
1312 memset(*rdata,0,*rdata_len);
1314 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1318 for (i = 0; i < count;i++)
1319 if (lp_browseable(i) && lp_snum_ok(i))
1320 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1324 *rparam = REALLOC(*rparam,*rparam_len);
1325 SSVAL(*rparam,0,NERR_Success);
1327 SSVAL(*rparam,4,counted);
1328 SSVAL(*rparam,6,total);
1330 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1331 counted,total,uLevel,
1332 buf_len,*rdata_len,mdrcnt));
1338 /****************************************************************************
1339 get the time of day info
1340 ****************************************************************************/
1341 static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
1342 int mdrcnt,int mprcnt,
1343 char **rdata,char **rparam,
1344 int *rdata_len,int *rparam_len)
1348 *rparam = REALLOC(*rparam,*rparam_len);
1351 *rdata = REALLOC(*rdata,*rdata_len);
1353 SSVAL(*rparam,0,NERR_Success);
1354 SSVAL(*rparam,2,0); /* converter word */
1360 time_t unixdate = time(NULL);
1362 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1363 by NT in a "net time" operation,
1364 it seems to ignore the one below */
1366 /* the client expects to get localtime, not GMT, in this bit
1367 (I think, this needs testing) */
1368 t = LocalTime(&unixdate);
1370 SIVAL(p,4,0); /* msecs ? */
1371 CVAL(p,8) = t->tm_hour;
1372 CVAL(p,9) = t->tm_min;
1373 CVAL(p,10) = t->tm_sec;
1374 CVAL(p,11) = 0; /* hundredths of seconds */
1375 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1376 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1377 CVAL(p,16) = t->tm_mday;
1378 CVAL(p,17) = t->tm_mon + 1;
1379 SSVAL(p,18,1900+t->tm_year);
1380 CVAL(p,20) = t->tm_wday;
1387 /****************************************************************************
1388 set the user password
1389 ****************************************************************************/
1390 static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
1391 int mdrcnt,int mprcnt,
1392 char **rdata,char **rparam,
1393 int *rdata_len,int *rparam_len)
1395 char *p = skip_string(param+2,2);
1397 fstring pass1,pass2;
1401 p = skip_string(p,1);
1403 StrnCpy(pass1,p,16);
1404 StrnCpy(pass2,p+16,16);
1407 *rparam = REALLOC(*rparam,*rparam_len);
1411 SSVAL(*rparam,0,NERR_Success);
1412 SSVAL(*rparam,2,0); /* converter word */
1414 DEBUG(3,("Set password for <%s>\n",user));
1416 if (!password_ok(user,pass1,strlen(pass1),NULL,False) ||
1417 !chgpasswd(user,pass1,pass2))
1418 SSVAL(*rparam,0,NERR_badpass);
1420 bzero(pass1,sizeof(fstring));
1421 bzero(pass2,sizeof(fstring));
1426 /****************************************************************************
1429 ****************************************************************************/
1430 static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
1431 int mdrcnt,int mprcnt,
1432 char **rdata,char **rparam,
1433 int *rdata_len,int *rparam_len)
1435 int function = SVAL(param,0);
1436 char *str1 = param+2;
1437 char *str2 = skip_string(str1,1);
1438 char *p = skip_string(str2,1);
1439 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1440 by the print queue api */
1441 int snum = (SVAL(p,0)>>8);
1445 /* check it's a supported varient */
1446 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1450 *rparam = REALLOC(*rparam,*rparam_len);
1454 SSVAL(*rparam,0,NERR_Success);
1456 if (snum >= 0 && VALID_SNUM(snum))
1458 print_queue_struct *queue=NULL;
1460 count = get_printqueue(snum,cnum,&queue,NULL);
1462 for (i=0;i<count;i++)
1463 if ((queue[i].job%0xFF) == jobid)
1466 case 81: /* delete */
1467 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1468 del_printqueue(cnum,snum,queue[i].job);
1470 case 82: /* pause */
1471 case 83: /* resume */
1472 DEBUG(3,("%s queue entry %d\n",
1473 (function==82?"pausing":"resuming"),queue[i].job));
1474 status_printjob(cnum,snum,queue[i].job,
1475 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1482 SSVAL(*rparam,0,NERR_JobNotFound);
1484 if (queue) free(queue);
1487 SSVAL(*rparam,2,0); /* converter word */
1492 static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data,
1493 int mdrcnt,int mprcnt,
1494 char **rdata,char **rparam,
1495 int *rdata_len,int *rparam_len)
1497 char *str1 = param+2;
1498 char *str2 = skip_string(str1,1);
1499 char *QueueName = skip_string(str2,1);
1502 /* check it's a supported varient */
1503 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1507 *rparam = REALLOC(*rparam,*rparam_len);
1511 SSVAL(*rparam,0,NERR_Success);
1512 SSVAL(*rparam,2,0); /* converter word */
1514 snum = lp_servicenumber(QueueName);
1515 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1516 int pnum = lp_servicenumber(PRINTERS_NAME);
1518 lp_add_printer(QueueName,pnum);
1519 snum = lp_servicenumber(QueueName);
1523 if (snum >= 0 && VALID_SNUM(snum)) {
1524 print_queue_struct *queue=NULL;
1528 count = get_printqueue(snum,cnum,&queue,NULL);
1529 for (i = 0; i < count; i++)
1530 del_printqueue(cnum,snum,queue[i].job);
1532 if (queue) free(queue);
1535 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1541 /****************************************************************************
1542 set the property of a print job (undocumented?)
1543 ? function = 0xb -> set name of print job
1544 ? function = 0x6 -> move print job up/down
1545 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1546 or <WWsTP> <WB21BB16B10zWWzDDz>
1547 ****************************************************************************/
1548 static int check_printjob_info(struct pack_desc* desc,
1549 int uLevel, char* id)
1551 desc->subformat = NULL;
1553 case 0: desc->format = "W"; break;
1554 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1555 case 2: desc->format = "WWzWWDDzz"; break;
1556 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1557 default: return False;
1559 if (strcmp(desc->format,id) != 0) return False;
1563 static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
1564 int mdrcnt,int mprcnt,
1565 char **rdata,char **rparam,
1566 int *rdata_len,int *rparam_len)
1568 struct pack_desc desc;
1569 char *str1 = param+2;
1570 char *str2 = skip_string(str1,1);
1571 char *p = skip_string(str2,1);
1572 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1573 by the print queue api */
1574 int snum = (SVAL(p,0)>>8);
1575 int uLevel = SVAL(p,2);
1576 int function = SVAL(p,4); /* what is this ?? */
1581 *rparam = REALLOC(*rparam,*rparam_len);
1585 /* check it's a supported varient */
1586 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1590 case 0x6: /* change job place in the queue, data gives the new place */
1591 if (snum >= 0 && VALID_SNUM(snum))
1593 print_queue_struct *queue=NULL;
1597 count = get_printqueue(snum,cnum,&queue,NULL);
1598 for (i=0;i<count;i++) /* find job */
1599 if ((queue[i].job%0xFF) == jobid) break;
1602 desc.errcode=NERR_JobNotFound;
1603 if (queue) free(queue);
1606 desc.errcode=NERR_Success;
1610 int place= SVAL(data,0);
1611 /* we currently have no way of doing this. Can any unix do it? */
1612 if (i < place) /* move down */;
1613 else if (i > place ) /* move up */;
1616 desc.errcode=NERR_notsupported; /* not yet supported */
1617 if (queue) free(queue);
1620 else desc.errcode=NERR_JobNotFound;
1622 case 0xb: /* change print job name, data gives the name */
1623 /* jobid, snum should be zero */
1630 if (issafe(*s)) name[l++] = *s;
1635 DEBUG(3,("Setting print name to %s\n",name));
1637 for (i=0;i<MAX_OPEN_FILES;i++)
1638 if (Files[i].open && Files[i].print_file)
1644 if (!become_user(Files[i].cnum,uid) ||
1645 !become_service(Files[i].cnum,True))
1648 if (sys_rename(Files[i].name,name) == 0)
1649 string_set(&Files[i].name,name);
1653 desc.errcode=NERR_Success;
1656 default: /* not implemented */
1660 SSVALS(*rparam,0,desc.errcode);
1661 SSVAL(*rparam,2,0); /* converter word */
1667 /****************************************************************************
1668 get info about the server
1669 ****************************************************************************/
1670 static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
1671 int mdrcnt,int mprcnt,
1672 char **rdata,char **rparam,
1673 int *rdata_len,int *rparam_len)
1675 char *str1 = param+2;
1676 char *str2 = skip_string(str1,1);
1677 char *p = skip_string(str2,1);
1678 int uLevel = SVAL(p,0);
1682 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1684 /* check it's a supported varient */
1685 if (!prefix_ok(str1,"WrLh")) return False;
1688 if (strcmp(str2,"B16") != 0) return False;
1692 if (strcmp(str2,"B16BBDz") != 0) return False;
1696 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1701 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1706 if (strcmp(str2,"DN") != 0) return False;
1710 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1713 default: return False;
1716 *rdata_len = mdrcnt;
1717 *rdata = REALLOC(*rdata,*rdata_len);
1720 p2 = p + struct_len;
1722 StrnCpy(p,local_machine,16);
1728 struct srv_info_struct *servers=NULL;
1731 uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION|
1732 SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE;
1734 strcpy(comment,lp_serverstring());
1736 if ((count=get_server_info(SV_TYPE_ALL,&servers,False,NULL))>0) {
1737 for (i=0;i<count;i++)
1738 if (strequal(servers[i].name,local_machine)) {
1739 servertype = servers[i].type;
1740 strcpy(comment,servers[i].comment);
1743 if (servers) free(servers);
1745 SCVAL(p,0,2); /* version_major */
1746 SCVAL(p,1,0); /* version_minor */
1747 SIVAL(p,2,servertype);
1748 if (mdrcnt == struct_len) {
1751 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1752 standard_sub(cnum,comment);
1753 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1754 p2 = skip_string(p2,1);
1759 return False; /* not yet implemented */
1762 *rdata_len = PTR_DIFF(p2,*rdata);
1765 *rparam = REALLOC(*rparam,*rparam_len);
1766 SSVAL(*rparam,0,NERR_Success);
1767 SSVAL(*rparam,2,0); /* converter word */
1768 SSVAL(*rparam,4,*rdata_len);
1774 /****************************************************************************
1775 get info about the server
1776 ****************************************************************************/
1777 static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
1778 int mdrcnt,int mprcnt,
1779 char **rdata,char **rparam,
1780 int *rdata_len,int *rparam_len)
1782 char *str1 = param+2;
1783 char *str2 = skip_string(str1,1);
1784 char *p = skip_string(str2,1);
1786 extern pstring sesssetup_user;
1787 int level = SVAL(p,0);
1789 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1792 *rparam = REALLOC(*rparam,*rparam_len);
1794 /* check it's a supported varient */
1795 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1798 *rdata_len = mdrcnt + 1024;
1799 *rdata = REALLOC(*rdata,*rdata_len);
1801 SSVAL(*rparam,0,NERR_Success);
1802 SSVAL(*rparam,2,0); /* converter word */
1807 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1808 strcpy(p2,local_machine);
1809 p2 = skip_string(p2,1);
1812 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1813 strcpy(p2,sesssetup_user);
1814 p2 = skip_string(p2,1);
1817 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1818 strcpy(p2,my_workgroup());
1819 p2 = skip_string(p2,1);
1822 SCVAL(p,0,2); /* major version?? */
1823 SCVAL(p,1,1); /* minor version?? */
1826 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1827 strcpy(p2,my_workgroup()); /* login domain?? */
1828 p2 = skip_string(p2,1);
1831 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1833 p2 = skip_string(p2,1);
1836 *rdata_len = PTR_DIFF(p2,*rdata);
1838 SSVAL(*rparam,4,*rdata_len);
1844 /****************************************************************************
1845 get info about a user
1846 ****************************************************************************/
1848 #define USER_PRIV_GUEST 0
1849 #define USER_PRIV_USER 1
1850 #define USER_PRIV_ADMIN 2
1852 static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
1853 int mdrcnt,int mprcnt,
1854 char **rdata,char **rparam,
1855 int *rdata_len,int *rparam_len)
1857 char *str1 = param+2;
1858 char *str2 = skip_string(str1,1);
1859 char *UserName = skip_string(str2,1);
1860 char *p = skip_string(UserName,1);
1861 int uLevel = SVAL(p,0);
1865 *rparam = REALLOC(*rparam,*rparam_len);
1867 /* check it's a supported varient */
1868 if (strcmp(str1,"zWrLh") != 0) return False;
1870 case 0: p2 = "B21"; break;
1871 case 1: p2 = "B21BB16DWzzWz"; break;
1872 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1873 case 10: p2 = "B21Bzzz"; break;
1874 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1875 default: return False;
1877 if (strcmp(p2,str2) != 0) return False;
1879 *rdata_len = mdrcnt + 1024;
1880 *rdata = REALLOC(*rdata,*rdata_len);
1882 SSVAL(*rparam,0,NERR_Success);
1883 SSVAL(*rparam,2,0); /* converter word */
1894 SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
1895 strcpy(p2,"<Comment>");
1896 p2 = skip_string(p2,1);
1897 SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
1898 strcpy(p2,"<UserComment>");
1899 p2 = skip_string(p2,1);
1900 SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
1901 strcpy(p2,"<FullName>");
1902 p2 = skip_string(p2,1);
1904 if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
1905 SSVAL(p,34,USER_PRIV_USER); /* user privilege */
1906 SIVAL(p,36,0); /* auth flags */
1907 SIVALS(p,40,-1); /* password age */
1908 SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
1909 strcpy(p2,"\\\\%L\\HOMES");
1910 standard_sub_basic(p2);
1911 p2 = skip_string(p2,1);
1912 SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
1914 p2 = skip_string(p2,1);
1915 SIVAL(p,52,0); /* last logon */
1916 SIVAL(p,56,0); /* last logoff */
1917 SSVALS(p,60,-1); /* bad pw counts */
1918 SSVALS(p,62,-1); /* num logons */
1919 SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
1921 p2 = skip_string(p2,1);
1922 SSVAL(p,68,0); /* country code */
1924 SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
1926 p2 = skip_string(p2,1);
1928 SIVALS(p,74,-1); /* max storage */
1929 SSVAL(p,78,168); /* units per week */
1930 SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
1932 SCVAL(p2,21,0); /* fix zero termination */
1933 p2 = skip_string(p2,1);
1935 SSVAL(p,84,0); /* code page */
1937 if (uLevel == 1 || uLevel == 2) {
1938 memset(p+22,' ',16); /* password */
1939 SIVALS(p,38,-1); /* password age */
1940 SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */
1941 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
1942 strcpy(p2,"\\\\%L\\HOMES");
1943 standard_sub_basic(p2);
1944 p2 = skip_string(p2,1);
1945 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
1947 SSVAL(p,52,0); /* flags */
1948 SIVAL(p,54,0); /* script_path */
1950 SIVAL(p,60,0); /* auth_flags */
1951 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
1952 strcpy(p2,"<Full Name>");
1953 p2 = skip_string(p2,1);
1954 SIVAL(p,68,0); /* urs_comment */
1955 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
1957 p2 = skip_string(p2,1);
1958 SIVAL(p,76,0); /* workstations */
1959 SIVAL(p,80,0); /* last_logon */
1960 SIVAL(p,84,0); /* last_logoff */
1961 SIVALS(p,88,-1); /* acct_expires */
1962 SIVALS(p,92,-1); /* max_storage */
1963 SSVAL(p,96,168); /* units_per_week */
1964 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
1967 SSVALS(p,102,-1); /* bad_pw_count */
1968 SSVALS(p,104,-1); /* num_logons */
1969 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
1970 strcpy(p2,"\\\\%L");
1971 standard_sub_basic(p2);
1972 p2 = skip_string(p2,1);
1973 SSVAL(p,110,49); /* country_code */
1974 SSVAL(p,112,860); /* code page */
1979 *rdata_len = PTR_DIFF(p2,*rdata);
1981 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
1987 /*******************************************************************
1988 get groups that a user is a member of
1989 ******************************************************************/
1990 static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
1991 int mdrcnt,int mprcnt,
1992 char **rdata,char **rparam,
1993 int *rdata_len,int *rparam_len)
1995 char *str1 = param+2;
1996 char *str2 = skip_string(str1,1);
1997 char *UserName = skip_string(str2,1);
1998 char *p = skip_string(UserName,1);
1999 int uLevel = SVAL(p,0);
2004 *rparam = REALLOC(*rparam,*rparam_len);
2006 /* check it's a supported varient */
2007 if (strcmp(str1,"zWrLeh") != 0) return False;
2009 case 0: p2 = "B21"; break;
2010 default: return False;
2012 if (strcmp(p2,str2) != 0) return False;
2014 *rdata_len = mdrcnt + 1024;
2015 *rdata = REALLOC(*rdata,*rdata_len);
2017 SSVAL(*rparam,0,NERR_Success);
2018 SSVAL(*rparam,2,0); /* converter word */
2022 /* XXXX we need a real SAM database some day */
2023 strcpy(p,"Users"); p += 21; count++;
2024 strcpy(p,"Domain Users"); p += 21; count++;
2025 strcpy(p,"Guests"); p += 21; count++;
2026 strcpy(p,"Domain Guests"); p += 21; count++;
2028 *rdata_len = PTR_DIFF(p,*rdata);
2030 SSVAL(*rparam,4,count); /* is this right?? */
2031 SSVAL(*rparam,6,count); /* is this right?? */
2037 static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
2038 int mdrcnt,int mprcnt,
2039 char **rdata,char **rparam,
2040 int *rdata_len,int *rparam_len)
2042 char *str1 = param+2;
2043 char *str2 = skip_string(str1,1);
2044 char *p = skip_string(str2,1);
2046 struct pack_desc desc;
2052 bzero(&desc,sizeof(desc));
2054 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2056 /* check it's a supported varient */
2057 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2058 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2059 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2061 desc.buflen = mdrcnt;
2062 desc.subformat = NULL;
2067 if (init_package(&desc,1,0)) {
2068 PACKI(&desc,"W",0); /* code */
2069 PACKS(&desc,"B21",name); /* eff. name */
2070 PACKS(&desc,"B",""); /* pad */
2072 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2073 PACKI(&desc,"D",0); /* auth flags XXX */
2074 PACKI(&desc,"W",0); /* num logons */
2075 PACKI(&desc,"W",0); /* bad pw count */
2076 PACKI(&desc,"D",-1); /* last logon */
2077 PACKI(&desc,"D",-1); /* last logoff */
2078 PACKI(&desc,"D",-1); /* logoff time */
2079 PACKI(&desc,"D",-1); /* kickoff time */
2080 PACKI(&desc,"D",0); /* password age */
2081 PACKI(&desc,"D",0); /* password can change */
2082 PACKI(&desc,"D",-1); /* password must change */
2085 strcpy(mypath,"\\\\");
2086 strcat(mypath,local_machine);
2088 PACKS(&desc,"z",mypath); /* computer */
2090 PACKS(&desc,"z",my_workgroup());/* domain */
2091 PACKS(&desc,"z",lp_logon_script()); /* script path */
2092 PACKI(&desc,"D",0); /* reserved */
2095 *rdata_len = desc.usedlen;
2097 *rparam = REALLOC(*rparam,*rparam_len);
2098 SSVALS(*rparam,0,desc.errcode);
2100 SSVAL(*rparam,4,desc.neededlen);
2102 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2107 /****************************************************************************
2108 api_WAccessGetUserPerms
2109 ****************************************************************************/
2110 static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
2111 int mdrcnt,int mprcnt,
2112 char **rdata,char **rparam,
2113 int *rdata_len,int *rparam_len)
2115 char *str1 = param+2;
2116 char *str2 = skip_string(str1,1);
2117 char *user = skip_string(str2,1);
2118 char *resource = skip_string(user,1);
2120 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2122 /* check it's a supported varient */
2123 if (strcmp(str1,"zzh") != 0) return False;
2124 if (strcmp(str2,"") != 0) return False;
2127 *rparam = REALLOC(*rparam,*rparam_len);
2128 SSVALS(*rparam,0,0); /* errorcode */
2129 SSVAL(*rparam,2,0); /* converter word */
2130 SSVAL(*rparam,4,0x7f); /* permission flags */
2135 /****************************************************************************
2136 api_WPrintJobEnumerate
2137 ****************************************************************************/
2138 static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
2139 int mdrcnt,int mprcnt,
2140 char **rdata,char **rparam,
2141 int *rdata_len,int *rparam_len)
2143 char *str1 = param+2;
2144 char *str2 = skip_string(str1,1);
2145 char *p = skip_string(str2,1);
2146 int uJobId = SVAL(p,0);
2152 struct pack_desc desc;
2153 print_queue_struct *queue=NULL;
2154 print_status_struct status;
2159 bzero(&desc,sizeof(desc));
2160 bzero(&status,sizeof(status));
2162 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2164 /* check it's a supported varient */
2165 if (strcmp(str1,"WWrLh") != 0) return False;
2166 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2168 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2169 job = uJobId & 0xFF;
2171 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2173 count = get_printqueue(snum,cnum,&queue,&status);
2174 for (i = 0; i < count; i++) {
2175 if ((queue[i].job % 0xFF) == job) break;
2177 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2179 desc.buflen = mdrcnt;
2181 if (init_package(&desc,1,0)) {
2183 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2184 *rdata_len = desc.usedlen;
2187 desc.errcode = NERR_JobNotFound;
2193 *rparam = REALLOC(*rparam,*rparam_len);
2194 SSVALS(*rparam,0,desc.errcode);
2196 SSVAL(*rparam,4,desc.neededlen);
2198 if (queue) free(queue);
2200 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2204 static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
2205 int mdrcnt,int mprcnt,
2206 char **rdata,char **rparam,
2207 int *rdata_len,int *rparam_len)
2209 char *str1 = param+2;
2210 char *str2 = skip_string(str1,1);
2211 char *p = skip_string(str2,1);
2217 struct pack_desc desc;
2218 print_queue_struct *queue=NULL;
2219 print_status_struct status;
2221 bzero(&desc,sizeof(desc));
2222 bzero(&status,sizeof(status));
2224 p = skip_string(p,1);
2228 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2230 /* check it's a supported varient */
2231 if (strcmp(str1,"zWrLeh") != 0) return False;
2232 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2233 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2235 snum = lp_servicenumber(name);
2236 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2237 int pnum = lp_servicenumber(PRINTERS_NAME);
2239 lp_add_printer(name,pnum);
2240 snum = lp_servicenumber(name);
2244 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2246 count = get_printqueue(snum,cnum,&queue,&status);
2247 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2249 desc.buflen = mdrcnt;
2251 if (init_package(&desc,count,0)) {
2253 for (i = 0; i < count; i++) {
2254 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2255 if (desc.errcode == NERR_Success) succnt = i+1;
2259 *rdata_len = desc.usedlen;
2262 *rparam = REALLOC(*rparam,*rparam_len);
2263 SSVALS(*rparam,0,desc.errcode);
2265 SSVAL(*rparam,4,succnt);
2266 SSVAL(*rparam,6,count);
2268 if (queue) free(queue);
2270 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2274 static int check_printdest_info(struct pack_desc* desc,
2275 int uLevel, char* id)
2277 desc->subformat = NULL;
2279 case 0: desc->format = "B9"; break;
2280 case 1: desc->format = "B9B21WWzW"; break;
2281 case 2: desc->format = "z"; break;
2282 case 3: desc->format = "zzzWWzzzWW"; break;
2283 default: return False;
2285 if (strcmp(desc->format,id) != 0) return False;
2289 static void fill_printdest_info(int cnum, int snum, int uLevel,
2290 struct pack_desc* desc)
2293 strcpy(buf,SERVICE(snum));
2296 PACKS(desc,"B9",buf); /* szName */
2298 PACKS(desc,"B21",""); /* szUserName */
2299 PACKI(desc,"W",0); /* uJobId */
2300 PACKI(desc,"W",0); /* fsStatus */
2301 PACKS(desc,"z",""); /* pszStatus */
2302 PACKI(desc,"W",0); /* time */
2305 if (uLevel == 2 || uLevel == 3) {
2306 PACKS(desc,"z",buf); /* pszPrinterName */
2308 PACKS(desc,"z",""); /* pszUserName */
2309 PACKS(desc,"z",""); /* pszLogAddr */
2310 PACKI(desc,"W",0); /* uJobId */
2311 PACKI(desc,"W",0); /* fsStatus */
2312 PACKS(desc,"z",""); /* pszStatus */
2313 PACKS(desc,"z",""); /* pszComment */
2314 PACKS(desc,"z","NULL"); /* pszDrivers */
2315 PACKI(desc,"W",0); /* time */
2316 PACKI(desc,"W",0); /* pad1 */
2321 static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
2322 int mdrcnt,int mprcnt,
2323 char **rdata,char **rparam,
2324 int *rdata_len,int *rparam_len)
2326 char *str1 = param+2;
2327 char *str2 = skip_string(str1,1);
2328 char *p = skip_string(str2,1);
2329 char* PrinterName = p;
2331 struct pack_desc desc;
2334 bzero(&desc,sizeof(desc));
2336 p = skip_string(p,1);
2340 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2342 /* check it's a supported varient */
2343 if (strcmp(str1,"zWrLh") != 0) return False;
2344 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2346 snum = lp_servicenumber(PrinterName);
2347 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2348 int pnum = lp_servicenumber(PRINTERS_NAME);
2350 lp_add_printer(PrinterName,pnum);
2351 snum = lp_servicenumber(PrinterName);
2357 desc.errcode = NERR_DestNotFound;
2361 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2363 desc.buflen = mdrcnt;
2364 if (init_package(&desc,1,0)) {
2365 fill_printdest_info(cnum,snum,uLevel,&desc);
2367 *rdata_len = desc.usedlen;
2371 *rparam = REALLOC(*rparam,*rparam_len);
2372 SSVALS(*rparam,0,desc.errcode);
2374 SSVAL(*rparam,4,desc.neededlen);
2376 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2380 static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
2381 int mdrcnt,int mprcnt,
2382 char **rdata,char **rparam,
2383 int *rdata_len,int *rparam_len)
2385 char *str1 = param+2;
2386 char *str2 = skip_string(str1,1);
2387 char *p = skip_string(str2,1);
2391 struct pack_desc desc;
2392 int services = lp_numservices();
2394 bzero(&desc,sizeof(desc));
2399 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2401 /* check it's a supported varient */
2402 if (strcmp(str1,"WrLeh") != 0) return False;
2403 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2406 for (i = 0; i < services; i++)
2407 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2410 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2412 desc.buflen = mdrcnt;
2413 if (init_package(&desc,queuecnt,0)) {
2416 for (i = 0; i < services; i++) {
2417 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2418 fill_printdest_info(cnum,i,uLevel,&desc);
2420 if (desc.errcode == NERR_Success) succnt = n;
2425 *rdata_len = desc.usedlen;
2428 *rparam = REALLOC(*rparam,*rparam_len);
2429 SSVALS(*rparam,0,desc.errcode);
2431 SSVAL(*rparam,4,succnt);
2432 SSVAL(*rparam,6,queuecnt);
2434 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2438 static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
2439 int mdrcnt,int mprcnt,
2440 char **rdata,char **rparam,
2441 int *rdata_len,int *rparam_len)
2443 char *str1 = param+2;
2444 char *str2 = skip_string(str1,1);
2445 char *p = skip_string(str2,1);
2448 struct pack_desc desc;
2450 bzero(&desc,sizeof(desc));
2455 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2457 /* check it's a supported varient */
2458 if (strcmp(str1,"WrLeh") != 0) return False;
2459 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2461 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2463 desc.buflen = mdrcnt;
2464 if (init_package(&desc,1,0)) {
2465 PACKS(&desc,"B41","NULL");
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,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2483 static BOOL api_WPrintQProcEnum(int cnum,int uid, 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,("WPrintQProcEnum 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,"B13") != 0) return False;
2506 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2508 desc.buflen = mdrcnt;
2510 if (init_package(&desc,1,0)) {
2511 PACKS(&desc,"B13","lpd");
2514 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2516 *rdata_len = desc.usedlen;
2519 *rparam = REALLOC(*rparam,*rparam_len);
2520 SSVALS(*rparam,0,desc.errcode);
2522 SSVAL(*rparam,4,succnt);
2525 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2529 static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
2530 int mdrcnt,int mprcnt,
2531 char **rdata,char **rparam,
2532 int *rdata_len,int *rparam_len)
2534 char *str1 = param+2;
2535 char *str2 = skip_string(str1,1);
2536 char *p = skip_string(str2,1);
2539 struct pack_desc desc;
2541 bzero(&desc,sizeof(desc));
2546 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2548 /* check it's a supported varient */
2549 if (strcmp(str1,"WrLeh") != 0) return False;
2550 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2552 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2553 bzero(&desc,sizeof(desc));
2555 desc.buflen = mdrcnt;
2557 if (init_package(&desc,1,0)) {
2558 PACKS(&desc,"B13","lp0");
2561 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2563 *rdata_len = desc.usedlen;
2566 *rparam = REALLOC(*rparam,*rparam_len);
2567 SSVALS(*rparam,0,desc.errcode);
2569 SSVAL(*rparam,4,succnt);
2572 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2576 /****************************************************************************
2577 the buffer was too small
2578 ****************************************************************************/
2579 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
2580 int mdrcnt,int mprcnt,
2581 char **rdata,char **rparam,
2582 int *rdata_len,int *rparam_len)
2584 *rparam_len = MIN(*rparam_len,mprcnt);
2585 *rparam = REALLOC(*rparam,*rparam_len);
2589 SSVAL(*rparam,0,NERR_BufTooSmall);
2591 DEBUG(3,("Supplied buffer too small in API command\n"));
2597 /****************************************************************************
2598 the request is not supported
2599 ****************************************************************************/
2600 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
2601 int mdrcnt,int mprcnt,
2602 char **rdata,char **rparam,
2603 int *rdata_len,int *rparam_len)
2606 *rparam = REALLOC(*rparam,*rparam_len);
2610 SSVAL(*rparam,0,NERR_notsupported);
2611 SSVAL(*rparam,2,0); /* converter word */
2613 DEBUG(3,("Unsupported API command\n"));
2627 } api_commands[] = {
2628 {"RNetShareEnum", 0, api_RNetShareEnum,0},
2629 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
2630 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
2631 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
2632 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
2633 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
2634 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
2635 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
2636 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
2637 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
2638 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
2639 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
2640 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
2641 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
2642 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
2643 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
2644 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
2645 {"NetServerEnum", 104, api_RNetServerEnum,0},
2646 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
2647 {"SetUserPassword", 115, api_SetUserPassword,0},
2648 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
2649 {"PrintJobInfo", 147, api_PrintJobInfo,0},
2650 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
2651 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
2652 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
2653 {NULL, -1, api_Unsupported,0}};
2656 /****************************************************************************
2657 handle remote api calls
2658 ****************************************************************************/
2659 static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
2660 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2662 int api_command = SVAL(params,0);
2664 char *rparam = NULL;
2670 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2671 api_command,params+2,skip_string(params+2,1),
2672 tdscnt,tpscnt,mdrcnt,mprcnt));
2674 for (i=0;api_commands[i].name;i++)
2675 if (api_commands[i].id == api_command && api_commands[i].fn)
2677 DEBUG(3,("Doing %s\n",api_commands[i].name));
2681 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2682 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2684 reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2685 &rdata,&rparam,&rdata_len,&rparam_len);
2688 if (rdata_len > mdrcnt ||
2689 rparam_len > mprcnt)
2691 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2692 &rdata,&rparam,&rdata_len,&rparam_len);
2696 /* if we get False back then it's actually unsupported */
2698 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2699 &rdata,&rparam,&rdata_len,&rparam_len);
2703 /* now send the reply */
2704 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2714 /****************************************************************************
2715 handle named pipe commands
2716 ****************************************************************************/
2717 static int named_pipe(int cnum,int uid, char *outbuf,char *name,
2718 uint16 *setup,char *data,char *params,
2719 int suwcnt,int tdscnt,int tpscnt,
2720 int msrcnt,int mdrcnt,int mprcnt)
2723 if (strequal(name,"LANMAN"))
2724 return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2726 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2727 name,(int)setup[0],(int)setup[1]));
2733 /****************************************************************************
2735 ****************************************************************************/
2736 int reply_trans(char *inbuf,char *outbuf)
2740 char *data=NULL,*params=NULL;
2744 int cnum = SVAL(inbuf,smb_tid);
2745 int uid = SVAL(inbuf,smb_uid);
2747 int tpscnt = SVAL(inbuf,smb_vwv0);
2748 int tdscnt = SVAL(inbuf,smb_vwv1);
2749 int mprcnt = SVAL(inbuf,smb_vwv2);
2750 int mdrcnt = SVAL(inbuf,smb_vwv3);
2751 int msrcnt = CVAL(inbuf,smb_vwv4);
2752 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2753 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2754 int pscnt = SVAL(inbuf,smb_vwv9);
2755 int psoff = SVAL(inbuf,smb_vwv10);
2756 int dscnt = SVAL(inbuf,smb_vwv11);
2757 int dsoff = SVAL(inbuf,smb_vwv12);
2758 int suwcnt = CVAL(inbuf,smb_vwv13);
2760 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2764 data = (char *)malloc(tdscnt);
2765 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2769 params = (char *)malloc(tpscnt);
2770 memcpy(params,smb_base(inbuf)+psoff,pscnt);
2776 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
2777 for (i=0;i<suwcnt;i++)
2778 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
2782 if (pscnt < tpscnt || dscnt < tdscnt)
2784 /* We need to send an interim response then receive the rest
2785 of the parameter/data bytes */
2786 outsize = set_message(outbuf,0,0,True);
2788 send_smb(Client,outbuf);
2791 /* receive the rest of the trans packet */
2792 while (pscnt < tpscnt || dscnt < tdscnt)
2794 int pcnt,poff,dcnt,doff,pdisp,ddisp;
2796 receive_smb(Client,inbuf, 0);
2799 /* Ensure this is still a trans packet (sanity check) */
2800 if(CVAL(inbuf, smb_com) != SMBtrans)
2802 DEBUG(2,("Invalid secondary trans2 packet\n"));
2803 if (params) free(params);
2804 if (data) free(data);
2805 if (setup) free(setup);
2806 return(ERROR(ERRSRV,ERRerror));
2809 tpscnt = SVAL(inbuf,smb_vwv0);
2810 tdscnt = SVAL(inbuf,smb_vwv1);
2812 pcnt = SVAL(inbuf,smb_vwv2);
2813 poff = SVAL(inbuf,smb_vwv3);
2814 pdisp = SVAL(inbuf,smb_vwv4);
2816 dcnt = SVAL(inbuf,smb_vwv5);
2817 doff = SVAL(inbuf,smb_vwv6);
2818 ddisp = SVAL(inbuf,smb_vwv7);
2824 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
2826 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
2830 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
2833 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
2834 outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
2835 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
2838 if (data) free(data);
2839 if (params) free(params);
2840 if (setup) free(setup);
2842 if (close_on_completion)
2843 close_cnum(cnum,uid);
2849 return(ERROR(ERRSRV,ERRnosupport));