2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1995
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles the named pipe and mailslot calls
23 in the SMBtrans protocol
33 extern int DEBUGLEVEL;
35 extern files_struct Files[];
36 extern connection_struct Connections[];
38 extern fstring local_machine;
40 #define NERR_Success 0
41 #define NERR_badpass 86
42 #define NERR_notsupported 50
44 #define NERR_BASE (2100)
45 #define NERR_BufTooSmall (NERR_BASE+23)
46 #define NERR_JobNotFound (NERR_BASE+51)
47 #define NERR_DestNotFound (NERR_BASE+52)
48 #define ERROR_INVALID_LEVEL 124
49 #define ERROR_MORE_DATA 234
51 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
53 #define ACCESS_READ 0x01
54 #define ACCESS_WRITE 0x02
55 #define ACCESS_CREATE 0x04
57 #define SHPWLEN 8 /* share password length */
58 #define NNLEN 12 /* 8.3 net name length */
59 #define SNLEN 15 /* service name length */
60 #define QNLEN 12 /* queue name maximum length */
62 #define MAJOR_VERSION 4
63 #define MINOR_VERSION 0
67 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
68 int mdrcnt,int mprcnt,
69 char **rdata,char **rparam,
70 int *rdata_len,int *rparam_len);
71 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
72 int mdrcnt,int mprcnt,
73 char **rdata,char **rparam,
74 int *rdata_len,int *rparam_len);
77 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
82 if (!src || !dst || !n || !(*dst)) return(0);
84 StrnCpy(buf,src,sizeof(buf)/2);
85 string_sub(buf,"%S",lp_servicename(snum));
86 standard_sub(cnum,buf);
94 static int CopyAndAdvance(char** dst, char* src, int* n)
97 if (!src || !dst || !n || !(*dst)) return(0);
105 static int StrlenExpanded(int cnum, int snum, char* s)
109 StrnCpy(buf,s,sizeof(buf)/2);
110 string_sub(buf,"%S",lp_servicename(snum));
111 standard_sub(cnum,buf);
112 return strlen(buf) + 1;
115 static char* Expand(int cnum, int snum, char* s)
118 if (!s) return(NULL);
119 StrnCpy(buf,s,sizeof(buf)/2);
120 string_sub(buf,"%S",lp_servicename(snum));
121 standard_sub(cnum,buf);
125 /*******************************************************************
126 check a API string for validity when we only need to check the prefix
127 ******************************************************************/
128 static BOOL prefix_ok(char *str,char *prefix)
130 return(strncmp(str,prefix,strlen(prefix)) == 0);
134 /****************************************************************************
136 ****************************************************************************/
137 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
138 int ldata,int lparam,int lsetup)
141 int this_ldata,this_lparam;
142 int tot_data=0,tot_param=0;
145 this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */
146 this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam));
148 align = (this_lparam%4);
150 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
152 memcpy(smb_buf(outbuf),param,this_lparam);
154 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
156 SSVAL(outbuf,smb_vwv0,lparam);
157 SSVAL(outbuf,smb_vwv1,ldata);
158 SSVAL(outbuf,smb_vwv3,this_lparam);
159 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
160 SSVAL(outbuf,smb_vwv5,0);
161 SSVAL(outbuf,smb_vwv6,this_ldata);
162 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
163 SSVAL(outbuf,smb_vwv8,0);
164 SSVAL(outbuf,smb_vwv9,lsetup);
165 for (i=0;i<lsetup;i++)
166 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
169 send_smb(Client,outbuf);
171 tot_data = this_ldata;
172 tot_param = this_lparam;
174 while (tot_data < ldata || tot_param < lparam)
176 this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
177 this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
179 align = (this_lparam%4);
181 set_message(outbuf,10,this_ldata+this_lparam+align,False);
183 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
185 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
187 SSVAL(outbuf,smb_vwv3,this_lparam);
188 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
189 SSVAL(outbuf,smb_vwv5,tot_param);
190 SSVAL(outbuf,smb_vwv6,this_ldata);
191 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
192 SSVAL(outbuf,smb_vwv8,tot_data);
193 SSVAL(outbuf,smb_vwv9,0);
196 send_smb(Client,outbuf);
198 tot_data += this_ldata;
199 tot_param += this_lparam;
204 char* format; /* formatstring for structure */
205 char* subformat; /* subformat for structure */
206 char* base; /* baseaddress of buffer */
207 int buflen; /* remaining size for fixed part; on init: length of base */
208 int subcount; /* count of substructures */
209 char* structbuf; /* pointer into buffer for remaining fixed part */
210 int stringlen; /* remaining size for variable part */
211 char* stringbuf; /* pointer into buffer for remaining variable part */
212 int neededlen; /* total needed size */
213 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
214 char* curpos; /* current position; pointer into format or subformat */
218 static int get_counter(char** p)
221 if (!p || !(*p)) return(1);
222 if (!isdigit(**p)) return 1;
226 n = 10 * n + (i - '0');
233 static int getlen(char* p)
239 case 'W': /* word (2 byte) */
242 case 'N': /* count of substructures (word) at end */
245 case 'D': /* double word (4 byte) */
246 case 'z': /* offset to zero terminated string (4 byte) */
247 case 'l': /* offset to user data (4 byte) */
250 case 'b': /* offset to data (with counter) (4 byte) */
254 case 'B': /* byte (with optional counter) */
255 n += get_counter(&p);
262 static BOOL init_package(struct pack_desc* p, int count, int subcount)
267 if (!p->format || !p->base) return(False);
269 i = count * getlen(p->format);
270 if (p->subformat) i += subcount * getlen(p->subformat);
271 p->structbuf = p->base;
275 p->curpos = p->format;
278 p->errcode = NERR_BufTooSmall;
281 p->errcode = NERR_Success;
284 p->stringbuf = p->base + i;
286 return(p->errcode == NERR_Success);
290 static int package(struct pack_desc* p, ...)
293 static int package(va_alist)
299 int needed=0, stringneeded;
301 int is_string=0, stringused;
308 p = va_arg(args,struct pack_desc *);
313 p->curpos = p->format;
315 p->curpos = p->subformat;
320 str = va_arg(args,char*);
321 if (strncmp(str,p->curpos,strlen(str)) != 0) {
322 DEBUG(2,("type error in package: %s instead of %*s\n",str,
323 strlen(str),p->curpos));
333 if (!p->curpos) return(0);
335 switch( *p->curpos++ ) {
336 case 'W': /* word (2 byte) */
338 temp = va_arg(args,int);
339 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
341 case 'N': /* count of substructures (word) at end */
343 p->subcount = va_arg(args,int);
344 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
346 case 'D': /* double word (4 byte) */
348 temp = va_arg(args,int);
349 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
351 case 'B': /* byte (with optional counter) */
352 needed = get_counter(&p->curpos);
354 char *s = va_arg(args,char*);
355 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
358 case 'z': /* offset to zero terminated string (4 byte) */
359 str = va_arg(args,char*);
360 stringneeded = (str ? strlen(str)+1 : 0);
363 case 'l': /* offset to user data (4 byte) */
364 str = va_arg(args,char*);
365 stringneeded = va_arg(args,int);
368 case 'b': /* offset to data (with counter) (4 byte) */
369 str = va_arg(args,char*);
370 stringneeded = get_counter(&p->curpos);
375 if (stringneeded >= 0) {
377 if (p->buflen >= needed) {
378 stringused = stringneeded;
379 if (stringused > p->stringlen) {
380 stringused = (is_string ? p->stringlen : 0);
381 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
384 SIVAL(p->structbuf,0,0);
386 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
387 memcpy(p->stringbuf,str?str:"",stringused);
388 if (is_string) p->stringbuf[stringused-1] = '\0';
389 p->stringbuf += stringused;
390 p->stringlen -= stringused;
391 p->usedlen += stringused;
394 p->neededlen += stringneeded;
396 p->neededlen += needed;
397 if (p->buflen >= needed) {
398 p->structbuf += needed;
400 p->usedlen += needed;
403 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
409 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
410 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
412 #define PACK(desc,t,v) package(desc,v)
413 #define PACKl(desc,t,v,l) package(desc,v,l)
416 static void PACKI(struct pack_desc* desc,char *t,int v)
421 static void PACKS(struct pack_desc* desc,char *t,char *v)
427 /****************************************************************************
429 ****************************************************************************/
431 static void PackDriverData(struct pack_desc* desc)
433 char drivdata[4+4+32];
434 SIVAL(drivdata,0,sizeof drivdata); /* cb */
435 SIVAL(drivdata,4,1000); /* lVersion */
436 memset(drivdata+8,0,32); /* szDeviceName */
437 strcpy(drivdata+8,"NULL");
438 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
441 static int check_printq_info(struct pack_desc* desc,
442 int uLevel, const char* id1, const char* id2)
444 desc->subformat = NULL;
447 desc->format = "B13";
450 desc->format = "B13BWWWzzzzzWW";
453 desc->format = "B13BWWWzzzzzWN";
454 desc->subformat = "WB21BB16B10zWWzDDz";
457 desc->format = "zWWWWzzzzWWzzl";
460 desc->format = "zWWWWzzzzWNzzl";
461 desc->subformat = "WWzWWDDzz";
466 default: return False;
468 if (strcmp(desc->format,id1) != 0) return False;
469 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
473 static void fill_printjob_info(int cnum, int snum, int uLevel,
474 struct pack_desc* desc,
475 print_queue_struct* queue, int n)
477 time_t t = queue->time;
479 /* the client expects localtime */
482 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
484 PACKS(desc,"B21",queue->user); /* szUserName */
485 PACKS(desc,"B",""); /* pad */
486 PACKS(desc,"B16",""); /* szNotifyName */
487 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
488 PACKS(desc,"z",""); /* pszParms */
489 PACKI(desc,"W",n+1); /* uPosition */
490 PACKI(desc,"W",queue->status); /* fsStatus */
491 PACKS(desc,"z",""); /* pszStatus */
492 PACKI(desc,"D",t); /* ulSubmitted */
493 PACKI(desc,"D",queue->size); /* ulSize */
494 PACKS(desc,"z",queue->file); /* pszComment */
496 if (uLevel == 2 || uLevel == 3) {
497 PACKI(desc,"W",queue->priority); /* uPriority */
498 PACKS(desc,"z",queue->user); /* pszUserName */
499 PACKI(desc,"W",n+1); /* uPosition */
500 PACKI(desc,"W",queue->status); /* fsStatus */
501 PACKI(desc,"D",t); /* ulSubmitted */
502 PACKI(desc,"D",queue->size); /* ulSize */
503 PACKS(desc,"z","Samba"); /* pszComment */
504 PACKS(desc,"z",queue->file); /* pszDocument */
506 PACKS(desc,"z",""); /* pszNotifyName */
507 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
508 PACKS(desc,"z",""); /* pszParms */
509 PACKS(desc,"z",""); /* pszStatus */
510 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
511 PACKS(desc,"z","lpd"); /* pszQProcName */
512 PACKS(desc,"z",""); /* pszQProcParms */
513 PACKS(desc,"z","NULL"); /* pszDriverName */
514 PackDriverData(desc); /* pDriverData */
515 PACKS(desc,"z",""); /* pszPrinterName */
520 static void fill_printq_info(int cnum, int snum, int uLevel,
521 struct pack_desc* desc,
522 int count, print_queue_struct* queue,
523 print_status_struct* status)
526 PACKS(desc,"B13",SERVICE(snum));
528 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
530 if (uLevel == 1 || uLevel == 2) {
531 PACKS(desc,"B",""); /* alignment */
532 PACKI(desc,"W",5); /* priority */
533 PACKI(desc,"W",0); /* start time */
534 PACKI(desc,"W",0); /* until time */
535 PACKS(desc,"z",""); /* pSepFile */
536 PACKS(desc,"z","lpd"); /* pPrProc */
537 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
538 PACKS(desc,"z",""); /* pParms */
540 PACKS(desc,"z","UNKNOWN PRINTER");
541 PACKI(desc,"W",LPSTAT_ERROR);
543 else if (!status || !status->message[0]) {
544 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
545 PACKI(desc,"W",LPSTAT_OK); /* status */
547 PACKS(desc,"z",status->message);
548 PACKI(desc,"W",status->status); /* status */
550 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
552 if (uLevel == 3 || uLevel == 4) {
553 PACKI(desc,"W",5); /* uPriority */
554 PACKI(desc,"W",0); /* uStarttime */
555 PACKI(desc,"W",0); /* uUntiltime */
556 PACKI(desc,"W",5); /* pad1 */
557 PACKS(desc,"z",""); /* pszSepFile */
558 PACKS(desc,"z","WinPrint"); /* pszPrProc */
559 PACKS(desc,"z",""); /* pszParms */
560 if (!status || !status->message[0]) {
561 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
562 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
564 PACKS(desc,"z",status->message); /* pszComment */
565 PACKI(desc,"W",status->status); /* fsStatus */
567 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
568 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
569 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
570 PackDriverData(desc); /* pDriverData */
572 if (uLevel == 2 || uLevel == 4) {
574 for (i=0;i<count;i++)
575 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
578 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
581 static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
582 int mdrcnt,int mprcnt,
583 char **rdata,char **rparam,
584 int *rdata_len,int *rparam_len)
586 char *str1 = param+2;
587 char *str2 = skip_string(str1,1);
588 char *p = skip_string(str2,1);
594 struct pack_desc desc;
595 print_queue_struct *queue=NULL;
596 print_status_struct status;
598 bzero(&status,sizeof(status));
599 bzero(&desc,sizeof(desc));
601 p = skip_string(p,1);
606 /* remove any trailing username */
607 if ((p = strchr(QueueName,'%'))) *p = 0;
609 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
611 /* check it's a supported varient */
612 if (!prefix_ok(str1,"zWrLh")) return False;
613 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
615 snum = lp_servicenumber(QueueName);
616 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
617 int pnum = lp_servicenumber(PRINTERS_NAME);
619 lp_add_printer(QueueName,pnum);
620 snum = lp_servicenumber(QueueName);
624 if (snum < 0 || !VALID_SNUM(snum)) return(False);
626 count = get_printqueue(snum,cnum,&queue,&status);
627 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
629 desc.buflen = mdrcnt;
630 if (init_package(&desc,1,count)) {
631 desc.subcount = count;
632 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
635 *rdata_len = desc.usedlen;
638 *rparam = REALLOC(*rparam,*rparam_len);
639 SSVALS(*rparam,0,desc.errcode);
641 SSVAL(*rparam,4,desc.neededlen);
643 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
645 if (queue) free(queue);
651 /****************************************************************************
652 view list of all print jobs on all queues
653 ****************************************************************************/
654 static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
655 int mdrcnt, int mprcnt,
656 char **rdata, char** rparam,
657 int *rdata_len, int *rparam_len)
659 char *param_format = param+2;
660 char *output_format1 = skip_string(param_format,1);
661 char *p = skip_string(output_format1,1);
662 int uLevel = SVAL(p,0);
663 char *output_format2 = p + 4;
664 int services = lp_numservices();
666 struct pack_desc desc;
667 print_queue_struct **queue = NULL;
668 print_status_struct *status = NULL;
669 int* subcntarr = NULL;
670 int queuecnt, subcnt=0, succnt=0;
672 bzero(&desc,sizeof(desc));
674 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
676 if (!prefix_ok(param_format,"WrLeh")) return False;
677 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
680 for (i = 0; i < services; i++)
681 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
684 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
685 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
686 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
687 memset(status,0,queuecnt*sizeof(print_status_struct));
688 subcntarr = (int*)malloc(queuecnt*sizeof(int));
691 for (i = 0; i < services; i++)
692 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
693 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
694 subcnt += subcntarr[n];
698 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
700 desc.buflen = mdrcnt;
702 if (init_package(&desc,queuecnt,subcnt)) {
705 for (i = 0; i < services; i++)
706 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
707 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
709 if (desc.errcode == NERR_Success) succnt = n;
713 if (subcntarr) free(subcntarr);
715 *rdata_len = desc.usedlen;
717 *rparam = REALLOC(*rparam,*rparam_len);
718 SSVALS(*rparam,0,desc.errcode);
720 SSVAL(*rparam,4,succnt);
721 SSVAL(*rparam,6,queuecnt);
723 for (i = 0; i < queuecnt; i++) {
724 if (queue && queue[i]) free(queue[i]);
727 if (queue) free(queue);
728 if (status) free(status);
733 /****************************************************************************
734 get info level for a server list query
735 ****************************************************************************/
736 static BOOL check_server_info(int uLevel, char* id)
740 if (strcmp(id,"B16") != 0) return False;
743 if (strcmp(id,"B16BBDz") != 0) return False;
751 /* used for server information: client, nameserv and ipc */
752 struct srv_info_struct
757 fstring domain; /* used ONLY in ipc.c NOT namework.c */
758 BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
761 /*******************************************************************
762 filter out unwanted server info
763 ******************************************************************/
764 static BOOL filter_server_info(struct srv_info_struct *server,
766 char *domain, uint32 request)
770 if (strequal(lp_workgroup(), server->domain)) {
775 DEBUG(4,("primary domain:reject %8x %s %s\n",request,server->name,server->domain));
778 else if ((request & SV_TYPE_DOMAIN_ENUM) &&
779 (server->type & SV_TYPE_DOMAIN_ENUM))
781 DEBUG(4,("rej:DOM %8x: %s %s\n",server->type,server->name,server->domain));
789 if (strequal(domain, server->domain))
792 if (request == SV_TYPE_LOCAL_LIST_ONLY &&
793 !(server->type & SV_TYPE_LOCAL_LIST_ONLY))
795 DEBUG(4,("rej:LOC %8x: ok %s %s\n",request,server->name,server->domain));
799 if ((request == (SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM)) &&
800 !(server->type&SV_TYPE_DOMAIN_ENUM))
802 DEBUG(4,("rej:LOCDOM %8x: ok %s %s\n",request,server->name,server->domain));
810 DEBUG(4,("domain:%s %s %s\n",domain,server->name,server->domain));
817 /*******************************************************************
818 get server info lists from the files saved by nmbd. Return the
820 ******************************************************************/
821 static int get_server_info(uint32 servertype,
822 struct srv_info_struct **servers, BOOL domains,
831 strcpy(fname,lp_lockdir());
832 trim_string(fname,NULL,"/");
834 strcat(fname,SERVER_LIST);
836 f = fopen(fname,"r");
839 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
843 /* request for everything is code for request all servers */
844 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
846 DEBUG(4,("Servertype search: %8x domains:%s\n",servertype,BOOLSTR(domains)));
851 struct srv_info_struct *s;
856 fgets(line,sizeof(line)-1,f);
857 if (!*line) continue;
859 if (count == alloced) {
861 (*servers) = (struct srv_info_struct *)
862 Realloc(*servers,sizeof(**servers)*alloced);
863 if (!(*servers)) return(0);
864 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
866 s = &(*servers)[count];
868 if (!next_token(&ptr,s->name , NULL)) continue;
869 if (!next_token(&ptr,stype , NULL)) continue;
870 if (!next_token(&ptr,s->comment, NULL)) continue;
871 if (!next_token(&ptr,s->domain , NULL)) {
872 /* this allows us to cope with an old nmbd */
873 strcpy(s->domain,my_workgroup());
876 if (sscanf(stype,"%X",&s->type) != 1) {
877 DEBUG(4,("r:host file "));
881 /* doesn't match up: don't want it */
882 if (!(servertype & s->type)) {
883 DEBUG(4,("r:serv type "));
887 if ((servertype == ~SV_TYPE_DOMAIN_ENUM) &&
888 (s->type & SV_TYPE_DOMAIN_ENUM))
890 DEBUG(4,("s:all x dom "));
894 if (domains && !(domain && *domain && strequal(domain, s->domain)))
896 if (!(s->type & SV_TYPE_DOMAIN_ENUM))
898 DEBUG(4,("r:dom enum "));
905 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
906 s->name, s->type, s->comment, s->domain));
908 s->type |= SV_TYPE_LOCAL_LIST_ONLY;
909 s->server_added = True;
914 DEBUG(4,("%20s %8x %25s %15s\n",
915 s->name, s->type, s->comment, s->domain));
924 /*******************************************************************
925 fill in a server info structure
926 ******************************************************************/
927 static int fill_srv_info(struct srv_info_struct *service,
928 int uLevel, char **buf, int *buflen,
929 char **stringbuf, int *stringspace, char *baseaddr)
938 case 0: struct_len = 16; break;
939 case 1: struct_len = 26; break;
949 len = strlen(service->comment)+1;
953 if (buflen) *buflen = struct_len;
954 if (stringspace) *stringspace = len;
955 return struct_len + len;
960 if (*buflen < struct_len) return -1;
969 l2 = *buflen - struct_len;
971 if (!baseaddr) baseaddr = p;
976 StrnCpy(p,service->name,15);
980 StrnCpy(p,service->name,15);
981 SIVAL(p,18,service->type);
982 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
983 len += CopyAndAdvance(&p2,service->comment,&l2);
989 *buf = p + struct_len;
990 *buflen -= struct_len;
1003 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1005 return(strcmp(s1->name,s2->name));
1008 /****************************************************************************
1009 view list of servers available (or possibly domains). The info is
1010 extracted from lists saved by nmbd on the local host
1011 ****************************************************************************/
1012 static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
1013 int mdrcnt, int mprcnt, char **rdata,
1014 char **rparam, int *rdata_len, int *rparam_len)
1016 char *str1 = param+2;
1017 char *str2 = skip_string(str1,1);
1018 char *p = skip_string(str2,1);
1019 int uLevel = SVAL(p,0);
1020 int buf_len = SVAL(p,2);
1021 uint32 servertype = IVAL(p,4);
1023 int data_len, fixed_len, string_len;
1025 struct srv_info_struct *servers=NULL;
1026 int counted=0,total=0;
1030 BOOL domain_request;
1031 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
1033 /*if (servertype == SV_TYPE_ALL) servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);*/
1034 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
1036 domain_request = servertype & SV_TYPE_DOMAIN_ENUM;
1041 if (!prefix_ok(str1,"WrLehD")) return False;
1042 if (!check_server_info(uLevel,str2)) return False;
1044 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1045 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1046 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1048 if (strcmp(str1, "WrLehDO") == 0)
1052 else if (strcmp(str1, "WrLehDz") == 0)
1055 StrnCpy(domain, p, sizeof(fstring)-1);
1058 if (lp_browse_list())
1060 total = get_server_info(servertype,&servers,domains,domain);
1063 data_len = fixed_len = string_len = 0;
1065 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1068 char *lastname=NULL;
1070 for (i=0;i<total;i++)
1072 struct srv_info_struct *s = &servers[i];
1073 if (filter_server_info(s,domains,domain,
1074 local_request|domain_request))
1076 if (lastname && strequal(lastname,s->name)) continue;
1078 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1079 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1080 s->name, s->type, s->comment, s->domain));
1082 if (data_len <= buf_len)
1086 string_len += s_len;
1092 *rdata_len = fixed_len + string_len;
1093 *rdata = REALLOC(*rdata,*rdata_len);
1094 bzero(*rdata,*rdata_len);
1096 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1102 char *lastname=NULL;
1103 int count2 = counted;
1104 for (i = 0; i < total && count2;i++)
1106 struct srv_info_struct *s = &servers[i];
1107 if (filter_server_info(s,domains,domain,local_request|domain_request))
1109 if (lastname && strequal(lastname,s->name)) continue;
1111 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1112 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1113 s->name, s->type, s->comment, s->domain));
1120 *rparam = REALLOC(*rparam,*rparam_len);
1121 SSVAL(*rparam,0,NERR_Success);
1123 SSVAL(*rparam,4,counted);
1124 SSVAL(*rparam,6,total);
1126 if (servers) free(servers);
1128 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1129 domain,uLevel,counted,total));
1135 /****************************************************************************
1136 get info about a share
1137 ****************************************************************************/
1138 static BOOL check_share_info(int uLevel, char* id)
1142 if (strcmp(id,"B13") != 0) return False;
1145 if (strcmp(id,"B13BWz") != 0) return False;
1148 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1151 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1153 default: return False;
1158 static int fill_share_info(int cnum, int snum, int uLevel,
1159 char** buf, int* buflen,
1160 char** stringbuf, int* stringspace, char* baseaddr)
1169 case 0: struct_len = 13; break;
1170 case 1: struct_len = 20; break;
1171 case 2: struct_len = 40; break;
1172 case 91: struct_len = 68; break;
1180 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1181 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1182 if (buflen) *buflen = struct_len;
1183 if (stringspace) *stringspace = len;
1184 return struct_len + len;
1189 if ((*buflen) < struct_len) return -1;
1197 p2 = p + struct_len;
1198 l2 = (*buflen) - struct_len;
1200 if (!baseaddr) baseaddr = p;
1202 StrnCpy(p,lp_servicename(snum),13);
1208 type = STYPE_DISKTREE;
1209 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1210 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1211 SSVAL(p,14,type); /* device type */
1212 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1213 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1218 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1219 SSVALS(p,22,-1); /* max uses */
1220 SSVAL(p,24,1); /* current uses */
1221 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1222 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1223 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1228 memset(p+40,0,SHPWLEN+2);
1240 (*buf) = p + struct_len;
1241 (*buflen) -= struct_len;
1243 (*stringspace) = l2;
1253 static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
1254 int mdrcnt,int mprcnt,
1255 char **rdata,char **rparam,
1256 int *rdata_len,int *rparam_len)
1258 char *str1 = param+2;
1259 char *str2 = skip_string(str1,1);
1260 char *netname = skip_string(str2,1);
1261 char *p = skip_string(netname,1);
1262 int uLevel = SVAL(p,0);
1263 int snum = find_service(netname);
1265 if (snum < 0) return False;
1267 /* check it's a supported varient */
1268 if (!prefix_ok(str1,"zWrLh")) return False;
1269 if (!check_share_info(uLevel,str2)) return False;
1271 *rdata = REALLOC(*rdata,mdrcnt);
1273 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1274 if (*rdata_len < 0) return False;
1277 *rparam = REALLOC(*rparam,*rparam_len);
1278 SSVAL(*rparam,0,NERR_Success);
1279 SSVAL(*rparam,2,0); /* converter word */
1280 SSVAL(*rparam,4,*rdata_len);
1285 /****************************************************************************
1286 view list of shares available
1287 ****************************************************************************/
1288 static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
1289 int mdrcnt,int mprcnt,
1290 char **rdata,char **rparam,
1291 int *rdata_len,int *rparam_len)
1293 char *str1 = param+2;
1294 char *str2 = skip_string(str1,1);
1295 char *p = skip_string(str2,1);
1296 int uLevel = SVAL(p,0);
1297 int buf_len = SVAL(p,2);
1299 int count=lp_numservices();
1300 int total=0,counted=0;
1302 int data_len, fixed_len, string_len;
1305 if (!prefix_ok(str1,"WrLeh")) return False;
1306 if (!check_share_info(uLevel,str2)) return False;
1308 data_len = fixed_len = string_len = 0;
1309 for (i=0;i<count;i++)
1310 if (lp_browseable(i) && lp_snum_ok(i))
1313 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1314 if (data_len <= buf_len)
1318 string_len += s_len;
1321 *rdata_len = fixed_len + string_len;
1322 *rdata = REALLOC(*rdata,*rdata_len);
1323 memset(*rdata,0,*rdata_len);
1325 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1329 for (i = 0; i < count;i++)
1330 if (lp_browseable(i) && lp_snum_ok(i))
1331 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1335 *rparam = REALLOC(*rparam,*rparam_len);
1336 SSVAL(*rparam,0,NERR_Success);
1338 SSVAL(*rparam,4,counted);
1339 SSVAL(*rparam,6,total);
1341 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1342 counted,total,uLevel,
1343 buf_len,*rdata_len,mdrcnt));
1349 /****************************************************************************
1350 get the time of day info
1351 ****************************************************************************/
1352 static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
1353 int mdrcnt,int mprcnt,
1354 char **rdata,char **rparam,
1355 int *rdata_len,int *rparam_len)
1359 *rparam = REALLOC(*rparam,*rparam_len);
1362 *rdata = REALLOC(*rdata,*rdata_len);
1364 SSVAL(*rparam,0,NERR_Success);
1365 SSVAL(*rparam,2,0); /* converter word */
1371 time_t unixdate = time(NULL);
1373 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1374 by NT in a "net time" operation,
1375 it seems to ignore the one below */
1377 /* the client expects to get localtime, not GMT, in this bit
1378 (I think, this needs testing) */
1379 t = LocalTime(&unixdate);
1381 SIVAL(p,4,0); /* msecs ? */
1382 CVAL(p,8) = t->tm_hour;
1383 CVAL(p,9) = t->tm_min;
1384 CVAL(p,10) = t->tm_sec;
1385 CVAL(p,11) = 0; /* hundredths of seconds */
1386 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1387 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1388 CVAL(p,16) = t->tm_mday;
1389 CVAL(p,17) = t->tm_mon + 1;
1390 SSVAL(p,18,1900+t->tm_year);
1391 CVAL(p,20) = t->tm_wday;
1398 /****************************************************************************
1399 set the user password
1400 ****************************************************************************/
1401 static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
1402 int mdrcnt,int mprcnt,
1403 char **rdata,char **rparam,
1404 int *rdata_len,int *rparam_len)
1406 char *p = skip_string(param+2,2);
1408 fstring pass1,pass2;
1412 p = skip_string(p,1);
1414 StrnCpy(pass1,p,16);
1415 StrnCpy(pass2,p+16,16);
1418 *rparam = REALLOC(*rparam,*rparam_len);
1422 SSVAL(*rparam,0,NERR_badpass);
1423 SSVAL(*rparam,2,0); /* converter word */
1425 DEBUG(3,("Set password for <%s>\n",user));
1427 if (password_ok(user,pass1,strlen(pass1),NULL,False) &&
1428 chgpasswd(user,pass1,pass2))
1430 SSVAL(*rparam,0,NERR_Success);
1433 bzero(pass1,sizeof(fstring));
1434 bzero(pass2,sizeof(fstring));
1439 /****************************************************************************
1442 ****************************************************************************/
1443 static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
1444 int mdrcnt,int mprcnt,
1445 char **rdata,char **rparam,
1446 int *rdata_len,int *rparam_len)
1448 int function = SVAL(param,0);
1449 char *str1 = param+2;
1450 char *str2 = skip_string(str1,1);
1451 char *p = skip_string(str2,1);
1452 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1453 by the print queue api */
1454 int snum = (SVAL(p,0)>>8);
1458 /* check it's a supported varient */
1459 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1463 *rparam = REALLOC(*rparam,*rparam_len);
1467 SSVAL(*rparam,0,NERR_Success);
1469 if (snum >= 0 && VALID_SNUM(snum))
1471 print_queue_struct *queue=NULL;
1473 count = get_printqueue(snum,cnum,&queue,NULL);
1475 for (i=0;i<count;i++)
1476 if ((queue[i].job%0xFF) == jobid)
1479 case 81: /* delete */
1480 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1481 del_printqueue(cnum,snum,queue[i].job);
1483 case 82: /* pause */
1484 case 83: /* resume */
1485 DEBUG(3,("%s queue entry %d\n",
1486 (function==82?"pausing":"resuming"),queue[i].job));
1487 status_printjob(cnum,snum,queue[i].job,
1488 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1495 SSVAL(*rparam,0,NERR_JobNotFound);
1497 if (queue) free(queue);
1500 SSVAL(*rparam,2,0); /* converter word */
1505 static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data,
1506 int mdrcnt,int mprcnt,
1507 char **rdata,char **rparam,
1508 int *rdata_len,int *rparam_len)
1510 char *str1 = param+2;
1511 char *str2 = skip_string(str1,1);
1512 char *QueueName = skip_string(str2,1);
1515 /* check it's a supported varient */
1516 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1520 *rparam = REALLOC(*rparam,*rparam_len);
1524 SSVAL(*rparam,0,NERR_Success);
1525 SSVAL(*rparam,2,0); /* converter word */
1527 snum = lp_servicenumber(QueueName);
1528 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1529 int pnum = lp_servicenumber(PRINTERS_NAME);
1531 lp_add_printer(QueueName,pnum);
1532 snum = lp_servicenumber(QueueName);
1536 if (snum >= 0 && VALID_SNUM(snum)) {
1537 print_queue_struct *queue=NULL;
1541 count = get_printqueue(snum,cnum,&queue,NULL);
1542 for (i = 0; i < count; i++)
1543 del_printqueue(cnum,snum,queue[i].job);
1545 if (queue) free(queue);
1548 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1554 /****************************************************************************
1555 set the property of a print job (undocumented?)
1556 ? function = 0xb -> set name of print job
1557 ? function = 0x6 -> move print job up/down
1558 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1559 or <WWsTP> <WB21BB16B10zWWzDDz>
1560 ****************************************************************************/
1561 static int check_printjob_info(struct pack_desc* desc,
1562 int uLevel, char* id)
1564 desc->subformat = NULL;
1566 case 0: desc->format = "W"; break;
1567 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1568 case 2: desc->format = "WWzWWDDzz"; break;
1569 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1570 default: return False;
1572 if (strcmp(desc->format,id) != 0) return False;
1576 static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
1577 int mdrcnt,int mprcnt,
1578 char **rdata,char **rparam,
1579 int *rdata_len,int *rparam_len)
1581 struct pack_desc desc;
1582 char *str1 = param+2;
1583 char *str2 = skip_string(str1,1);
1584 char *p = skip_string(str2,1);
1585 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1586 by the print queue api */
1587 int snum = (SVAL(p,0)>>8);
1588 int uLevel = SVAL(p,2);
1589 int function = SVAL(p,4); /* what is this ?? */
1594 *rparam = REALLOC(*rparam,*rparam_len);
1598 /* check it's a supported varient */
1599 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1603 case 0x6: /* change job place in the queue, data gives the new place */
1604 if (snum >= 0 && VALID_SNUM(snum))
1606 print_queue_struct *queue=NULL;
1610 count = get_printqueue(snum,cnum,&queue,NULL);
1611 for (i=0;i<count;i++) /* find job */
1612 if ((queue[i].job%0xFF) == jobid) break;
1615 desc.errcode=NERR_JobNotFound;
1616 if (queue) free(queue);
1619 desc.errcode=NERR_Success;
1623 int place= SVAL(data,0);
1624 /* we currently have no way of doing this. Can any unix do it? */
1625 if (i < place) /* move down */;
1626 else if (i > place ) /* move up */;
1629 desc.errcode=NERR_notsupported; /* not yet supported */
1630 if (queue) free(queue);
1633 else desc.errcode=NERR_JobNotFound;
1635 case 0xb: /* change print job name, data gives the name */
1636 /* jobid, snum should be zero */
1643 if (issafe(*s)) name[l++] = *s;
1648 DEBUG(3,("Setting print name to %s\n",name));
1650 for (i=0;i<MAX_OPEN_FILES;i++)
1651 if (Files[i].open && Files[i].print_file)
1657 if (!become_user(Files[i].cnum,uid) ||
1658 !become_service(Files[i].cnum,True))
1661 if (sys_rename(Files[i].name,name) == 0)
1662 string_set(&Files[i].name,name);
1666 desc.errcode=NERR_Success;
1669 default: /* not implemented */
1673 SSVALS(*rparam,0,desc.errcode);
1674 SSVAL(*rparam,2,0); /* converter word */
1680 /****************************************************************************
1681 get info about the server
1682 ****************************************************************************/
1683 static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
1684 int mdrcnt,int mprcnt,
1685 char **rdata,char **rparam,
1686 int *rdata_len,int *rparam_len)
1688 char *str1 = param+2;
1689 char *str2 = skip_string(str1,1);
1690 char *p = skip_string(str2,1);
1691 int uLevel = SVAL(p,0);
1695 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1697 /* check it's a supported varient */
1698 if (!prefix_ok(str1,"WrLh")) return False;
1701 if (strcmp(str2,"B16") != 0) return False;
1705 if (strcmp(str2,"B16BBDz") != 0) return False;
1709 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1714 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1719 if (strcmp(str2,"DN") != 0) return False;
1723 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1726 default: return False;
1729 *rdata_len = mdrcnt;
1730 *rdata = REALLOC(*rdata,*rdata_len);
1733 p2 = p + struct_len;
1735 StrnCpy(p,local_machine,16);
1741 struct srv_info_struct *servers=NULL;
1744 uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION|
1745 SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE;
1747 strcpy(comment,lp_serverstring());
1749 if ((count=get_server_info(SV_TYPE_ALL,&servers,False,NULL))>0) {
1750 for (i=0;i<count;i++)
1751 if (strequal(servers[i].name,local_machine)) {
1752 servertype = servers[i].type;
1753 strcpy(comment,servers[i].comment);
1756 if (servers) free(servers);
1758 SCVAL(p,0,MAJOR_VERSION);
1759 SCVAL(p,1,MINOR_VERSION);
1760 SIVAL(p,2,servertype);
1762 if (mdrcnt == struct_len) {
1765 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1766 standard_sub(cnum,comment);
1767 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1768 p2 = skip_string(p2,1);
1773 return False; /* not yet implemented */
1776 *rdata_len = PTR_DIFF(p2,*rdata);
1779 *rparam = REALLOC(*rparam,*rparam_len);
1780 SSVAL(*rparam,0,NERR_Success);
1781 SSVAL(*rparam,2,0); /* converter word */
1782 SSVAL(*rparam,4,*rdata_len);
1788 /****************************************************************************
1789 get info about the server
1790 ****************************************************************************/
1791 static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
1792 int mdrcnt,int mprcnt,
1793 char **rdata,char **rparam,
1794 int *rdata_len,int *rparam_len)
1796 char *str1 = param+2;
1797 char *str2 = skip_string(str1,1);
1798 char *p = skip_string(str2,1);
1800 extern pstring sesssetup_user;
1801 int level = SVAL(p,0);
1803 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1806 *rparam = REALLOC(*rparam,*rparam_len);
1808 /* check it's a supported varient */
1809 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1812 *rdata_len = mdrcnt + 1024;
1813 *rdata = REALLOC(*rdata,*rdata_len);
1815 SSVAL(*rparam,0,NERR_Success);
1816 SSVAL(*rparam,2,0); /* converter word */
1821 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1822 strcpy(p2,local_machine);
1823 p2 = skip_string(p2,1);
1826 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1827 strcpy(p2,sesssetup_user);
1828 p2 = skip_string(p2,1);
1831 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1832 strcpy(p2,my_workgroup());
1833 p2 = skip_string(p2,1);
1836 SCVAL(p,0,MAJOR_VERSION);
1837 SCVAL(p,1,MINOR_VERSION);
1840 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1841 strcpy(p2,my_workgroup()); /* login domain?? */
1842 p2 = skip_string(p2,1);
1845 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1847 p2 = skip_string(p2,1);
1850 *rdata_len = PTR_DIFF(p2,*rdata);
1852 SSVAL(*rparam,4,*rdata_len);
1858 /****************************************************************************
1859 get info about a user
1860 ****************************************************************************/
1862 #define USER_PRIV_GUEST 0
1863 #define USER_PRIV_USER 1
1864 #define USER_PRIV_ADMIN 2
1866 static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
1867 int mdrcnt,int mprcnt,
1868 char **rdata,char **rparam,
1869 int *rdata_len,int *rparam_len)
1871 char *str1 = param+2;
1872 char *str2 = skip_string(str1,1);
1873 char *UserName = skip_string(str2,1);
1874 char *p = skip_string(UserName,1);
1875 int uLevel = SVAL(p,0);
1879 *rparam = REALLOC(*rparam,*rparam_len);
1881 /* check it's a supported varient */
1882 if (strcmp(str1,"zWrLh") != 0) return False;
1884 case 0: p2 = "B21"; break;
1885 case 1: p2 = "B21BB16DWzzWz"; break;
1886 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1887 case 10: p2 = "B21Bzzz"; break;
1888 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1889 default: return False;
1891 if (strcmp(p2,str2) != 0) return False;
1893 *rdata_len = mdrcnt + 1024;
1894 *rdata = REALLOC(*rdata,*rdata_len);
1896 SSVAL(*rparam,0,NERR_Success);
1897 SSVAL(*rparam,2,0); /* converter word */
1908 SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
1909 strcpy(p2,"<Comment>");
1910 p2 = skip_string(p2,1);
1911 SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
1912 strcpy(p2,"<UserComment>");
1913 p2 = skip_string(p2,1);
1914 SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
1915 strcpy(p2,"<FullName>");
1916 p2 = skip_string(p2,1);
1918 if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
1920 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
1921 SIVAL(p,36,0); /* auth flags */
1922 SIVALS(p,40,-1); /* password age */
1923 SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
1924 strcpy(p2,"\\\\%L\\HOMES");
1925 standard_sub_basic(p2);
1926 p2 = skip_string(p2,1);
1927 SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
1929 p2 = skip_string(p2,1);
1930 SIVAL(p,52,0); /* last logon */
1931 SIVAL(p,56,0); /* last logoff */
1932 SSVALS(p,60,-1); /* bad pw counts */
1933 SSVALS(p,62,-1); /* num logons */
1934 SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
1936 p2 = skip_string(p2,1);
1937 SSVAL(p,68,0); /* country code */
1939 SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
1941 p2 = skip_string(p2,1);
1943 SIVALS(p,74,-1); /* max storage */
1944 SSVAL(p,78,168); /* units per week */
1945 SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
1947 SCVAL(p2,21,0); /* fix zero termination */
1948 p2 = skip_string(p2,1);
1950 SSVAL(p,84,0); /* code page */
1952 if (uLevel == 1 || uLevel == 2) {
1953 memset(p+22,' ',16); /* password */
1954 SIVALS(p,38,-1); /* password age */
1956 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
1957 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
1958 strcpy(p2,"\\\\%L\\HOMES");
1959 standard_sub_basic(p2);
1960 p2 = skip_string(p2,1);
1961 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
1963 SSVAL(p,52,0); /* flags */
1964 SIVAL(p,54,0); /* script_path */
1966 SIVAL(p,60,0); /* auth_flags */
1967 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
1968 strcpy(p2,"<Full Name>");
1969 p2 = skip_string(p2,1);
1970 SIVAL(p,68,0); /* urs_comment */
1971 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
1973 p2 = skip_string(p2,1);
1974 SIVAL(p,76,0); /* workstations */
1975 SIVAL(p,80,0); /* last_logon */
1976 SIVAL(p,84,0); /* last_logoff */
1977 SIVALS(p,88,-1); /* acct_expires */
1978 SIVALS(p,92,-1); /* max_storage */
1979 SSVAL(p,96,168); /* units_per_week */
1980 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
1983 SSVALS(p,102,-1); /* bad_pw_count */
1984 SSVALS(p,104,-1); /* num_logons */
1985 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
1986 strcpy(p2,"\\\\%L");
1987 standard_sub_basic(p2);
1988 p2 = skip_string(p2,1);
1989 SSVAL(p,110,49); /* country_code */
1990 SSVAL(p,112,860); /* code page */
1995 *rdata_len = PTR_DIFF(p2,*rdata);
1997 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2003 /*******************************************************************
2004 get groups that a user is a member of
2005 ******************************************************************/
2006 static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
2007 int mdrcnt,int mprcnt,
2008 char **rdata,char **rparam,
2009 int *rdata_len,int *rparam_len)
2011 char *str1 = param+2;
2012 char *str2 = skip_string(str1,1);
2013 char *UserName = skip_string(str2,1);
2014 char *p = skip_string(UserName,1);
2015 int uLevel = SVAL(p,0);
2020 *rparam = REALLOC(*rparam,*rparam_len);
2022 /* check it's a supported varient */
2023 if (strcmp(str1,"zWrLeh") != 0) return False;
2025 case 0: p2 = "B21"; break;
2026 default: return False;
2028 if (strcmp(p2,str2) != 0) return False;
2030 *rdata_len = mdrcnt + 1024;
2031 *rdata = REALLOC(*rdata,*rdata_len);
2033 SSVAL(*rparam,0,NERR_Success);
2034 SSVAL(*rparam,2,0); /* converter word */
2038 /* XXXX we need a real SAM database some day */
2039 strcpy(p,"Users"); p += 21; count++;
2040 strcpy(p,"Domain Users"); p += 21; count++;
2041 strcpy(p,"Guests"); p += 21; count++;
2042 strcpy(p,"Domain Guests"); p += 21; count++;
2044 *rdata_len = PTR_DIFF(p,*rdata);
2046 SSVAL(*rparam,4,count); /* is this right?? */
2047 SSVAL(*rparam,6,count); /* is this right?? */
2053 static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
2054 int mdrcnt,int mprcnt,
2055 char **rdata,char **rparam,
2056 int *rdata_len,int *rparam_len)
2058 char *str1 = param+2;
2059 char *str2 = skip_string(str1,1);
2060 char *p = skip_string(str2,1);
2062 struct pack_desc desc;
2068 bzero(&desc,sizeof(desc));
2070 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2072 /* check it's a supported varient */
2073 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2074 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2075 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2077 desc.buflen = mdrcnt;
2078 desc.subformat = NULL;
2083 if (init_package(&desc,1,0)) {
2084 PACKI(&desc,"W",0); /* code */
2085 PACKS(&desc,"B21",name); /* eff. name */
2086 PACKS(&desc,"B",""); /* pad */
2088 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2089 PACKI(&desc,"D",0); /* auth flags XXX */
2090 PACKI(&desc,"W",0); /* num logons */
2091 PACKI(&desc,"W",0); /* bad pw count */
2092 PACKI(&desc,"D",-1); /* last logon */
2093 PACKI(&desc,"D",-1); /* last logoff */
2094 PACKI(&desc,"D",-1); /* logoff time */
2095 PACKI(&desc,"D",-1); /* kickoff time */
2096 PACKI(&desc,"D",0); /* password age */
2097 PACKI(&desc,"D",0); /* password can change */
2098 PACKI(&desc,"D",-1); /* password must change */
2101 strcpy(mypath,"\\\\");
2102 strcat(mypath,local_machine);
2104 PACKS(&desc,"z",mypath); /* computer */
2106 PACKS(&desc,"z",my_workgroup());/* domain */
2107 PACKS(&desc,"z",lp_logon_script()); /* script path */
2108 PACKI(&desc,"D",0); /* reserved */
2111 *rdata_len = desc.usedlen;
2113 *rparam = REALLOC(*rparam,*rparam_len);
2114 SSVALS(*rparam,0,desc.errcode);
2116 SSVAL(*rparam,4,desc.neededlen);
2118 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2123 /****************************************************************************
2124 api_WAccessGetUserPerms
2125 ****************************************************************************/
2126 static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
2127 int mdrcnt,int mprcnt,
2128 char **rdata,char **rparam,
2129 int *rdata_len,int *rparam_len)
2131 char *str1 = param+2;
2132 char *str2 = skip_string(str1,1);
2133 char *user = skip_string(str2,1);
2134 char *resource = skip_string(user,1);
2136 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2138 /* check it's a supported varient */
2139 if (strcmp(str1,"zzh") != 0) return False;
2140 if (strcmp(str2,"") != 0) return False;
2143 *rparam = REALLOC(*rparam,*rparam_len);
2144 SSVALS(*rparam,0,0); /* errorcode */
2145 SSVAL(*rparam,2,0); /* converter word */
2146 SSVAL(*rparam,4,0x7f); /* permission flags */
2151 /****************************************************************************
2152 api_WPrintJobEnumerate
2153 ****************************************************************************/
2154 static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
2155 int mdrcnt,int mprcnt,
2156 char **rdata,char **rparam,
2157 int *rdata_len,int *rparam_len)
2159 char *str1 = param+2;
2160 char *str2 = skip_string(str1,1);
2161 char *p = skip_string(str2,1);
2162 int uJobId = SVAL(p,0);
2168 struct pack_desc desc;
2169 print_queue_struct *queue=NULL;
2170 print_status_struct status;
2175 bzero(&desc,sizeof(desc));
2176 bzero(&status,sizeof(status));
2178 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2180 /* check it's a supported varient */
2181 if (strcmp(str1,"WWrLh") != 0) return False;
2182 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2184 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2185 job = uJobId & 0xFF;
2187 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2189 count = get_printqueue(snum,cnum,&queue,&status);
2190 for (i = 0; i < count; i++) {
2191 if ((queue[i].job % 0xFF) == job) break;
2193 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2195 desc.buflen = mdrcnt;
2197 if (init_package(&desc,1,0)) {
2199 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2200 *rdata_len = desc.usedlen;
2203 desc.errcode = NERR_JobNotFound;
2209 *rparam = REALLOC(*rparam,*rparam_len);
2210 SSVALS(*rparam,0,desc.errcode);
2212 SSVAL(*rparam,4,desc.neededlen);
2214 if (queue) free(queue);
2216 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2220 static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
2221 int mdrcnt,int mprcnt,
2222 char **rdata,char **rparam,
2223 int *rdata_len,int *rparam_len)
2225 char *str1 = param+2;
2226 char *str2 = skip_string(str1,1);
2227 char *p = skip_string(str2,1);
2233 struct pack_desc desc;
2234 print_queue_struct *queue=NULL;
2235 print_status_struct status;
2237 bzero(&desc,sizeof(desc));
2238 bzero(&status,sizeof(status));
2240 p = skip_string(p,1);
2244 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2246 /* check it's a supported varient */
2247 if (strcmp(str1,"zWrLeh") != 0) return False;
2248 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2249 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2251 snum = lp_servicenumber(name);
2252 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2253 int pnum = lp_servicenumber(PRINTERS_NAME);
2255 lp_add_printer(name,pnum);
2256 snum = lp_servicenumber(name);
2260 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2262 count = get_printqueue(snum,cnum,&queue,&status);
2263 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2265 desc.buflen = mdrcnt;
2267 if (init_package(&desc,count,0)) {
2269 for (i = 0; i < count; i++) {
2270 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2271 if (desc.errcode == NERR_Success) succnt = i+1;
2275 *rdata_len = desc.usedlen;
2278 *rparam = REALLOC(*rparam,*rparam_len);
2279 SSVALS(*rparam,0,desc.errcode);
2281 SSVAL(*rparam,4,succnt);
2282 SSVAL(*rparam,6,count);
2284 if (queue) free(queue);
2286 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2290 static int check_printdest_info(struct pack_desc* desc,
2291 int uLevel, char* id)
2293 desc->subformat = NULL;
2295 case 0: desc->format = "B9"; break;
2296 case 1: desc->format = "B9B21WWzW"; break;
2297 case 2: desc->format = "z"; break;
2298 case 3: desc->format = "zzzWWzzzWW"; break;
2299 default: return False;
2301 if (strcmp(desc->format,id) != 0) return False;
2305 static void fill_printdest_info(int cnum, int snum, int uLevel,
2306 struct pack_desc* desc)
2309 strcpy(buf,SERVICE(snum));
2312 PACKS(desc,"B9",buf); /* szName */
2314 PACKS(desc,"B21",""); /* szUserName */
2315 PACKI(desc,"W",0); /* uJobId */
2316 PACKI(desc,"W",0); /* fsStatus */
2317 PACKS(desc,"z",""); /* pszStatus */
2318 PACKI(desc,"W",0); /* time */
2321 if (uLevel == 2 || uLevel == 3) {
2322 PACKS(desc,"z",buf); /* pszPrinterName */
2324 PACKS(desc,"z",""); /* pszUserName */
2325 PACKS(desc,"z",""); /* pszLogAddr */
2326 PACKI(desc,"W",0); /* uJobId */
2327 PACKI(desc,"W",0); /* fsStatus */
2328 PACKS(desc,"z",""); /* pszStatus */
2329 PACKS(desc,"z",""); /* pszComment */
2330 PACKS(desc,"z","NULL"); /* pszDrivers */
2331 PACKI(desc,"W",0); /* time */
2332 PACKI(desc,"W",0); /* pad1 */
2337 static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
2338 int mdrcnt,int mprcnt,
2339 char **rdata,char **rparam,
2340 int *rdata_len,int *rparam_len)
2342 char *str1 = param+2;
2343 char *str2 = skip_string(str1,1);
2344 char *p = skip_string(str2,1);
2345 char* PrinterName = p;
2347 struct pack_desc desc;
2350 bzero(&desc,sizeof(desc));
2352 p = skip_string(p,1);
2356 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2358 /* check it's a supported varient */
2359 if (strcmp(str1,"zWrLh") != 0) return False;
2360 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2362 snum = lp_servicenumber(PrinterName);
2363 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2364 int pnum = lp_servicenumber(PRINTERS_NAME);
2366 lp_add_printer(PrinterName,pnum);
2367 snum = lp_servicenumber(PrinterName);
2373 desc.errcode = NERR_DestNotFound;
2377 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2379 desc.buflen = mdrcnt;
2380 if (init_package(&desc,1,0)) {
2381 fill_printdest_info(cnum,snum,uLevel,&desc);
2383 *rdata_len = desc.usedlen;
2387 *rparam = REALLOC(*rparam,*rparam_len);
2388 SSVALS(*rparam,0,desc.errcode);
2390 SSVAL(*rparam,4,desc.neededlen);
2392 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2396 static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
2397 int mdrcnt,int mprcnt,
2398 char **rdata,char **rparam,
2399 int *rdata_len,int *rparam_len)
2401 char *str1 = param+2;
2402 char *str2 = skip_string(str1,1);
2403 char *p = skip_string(str2,1);
2407 struct pack_desc desc;
2408 int services = lp_numservices();
2410 bzero(&desc,sizeof(desc));
2415 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2417 /* check it's a supported varient */
2418 if (strcmp(str1,"WrLeh") != 0) return False;
2419 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2422 for (i = 0; i < services; i++)
2423 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2426 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2428 desc.buflen = mdrcnt;
2429 if (init_package(&desc,queuecnt,0)) {
2432 for (i = 0; i < services; i++) {
2433 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2434 fill_printdest_info(cnum,i,uLevel,&desc);
2436 if (desc.errcode == NERR_Success) succnt = n;
2441 *rdata_len = desc.usedlen;
2444 *rparam = REALLOC(*rparam,*rparam_len);
2445 SSVALS(*rparam,0,desc.errcode);
2447 SSVAL(*rparam,4,succnt);
2448 SSVAL(*rparam,6,queuecnt);
2450 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2454 static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
2455 int mdrcnt,int mprcnt,
2456 char **rdata,char **rparam,
2457 int *rdata_len,int *rparam_len)
2459 char *str1 = param+2;
2460 char *str2 = skip_string(str1,1);
2461 char *p = skip_string(str2,1);
2464 struct pack_desc desc;
2466 bzero(&desc,sizeof(desc));
2471 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2473 /* check it's a supported varient */
2474 if (strcmp(str1,"WrLeh") != 0) return False;
2475 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2477 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2479 desc.buflen = mdrcnt;
2480 if (init_package(&desc,1,0)) {
2481 PACKS(&desc,"B41","NULL");
2484 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2486 *rdata_len = desc.usedlen;
2489 *rparam = REALLOC(*rparam,*rparam_len);
2490 SSVALS(*rparam,0,desc.errcode);
2492 SSVAL(*rparam,4,succnt);
2495 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2499 static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
2500 int mdrcnt,int mprcnt,
2501 char **rdata,char **rparam,
2502 int *rdata_len,int *rparam_len)
2504 char *str1 = param+2;
2505 char *str2 = skip_string(str1,1);
2506 char *p = skip_string(str2,1);
2509 struct pack_desc desc;
2511 bzero(&desc,sizeof(desc));
2516 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2518 /* check it's a supported varient */
2519 if (strcmp(str1,"WrLeh") != 0) return False;
2520 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2522 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2524 desc.buflen = mdrcnt;
2526 if (init_package(&desc,1,0)) {
2527 PACKS(&desc,"B13","lpd");
2530 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2532 *rdata_len = desc.usedlen;
2535 *rparam = REALLOC(*rparam,*rparam_len);
2536 SSVALS(*rparam,0,desc.errcode);
2538 SSVAL(*rparam,4,succnt);
2541 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2545 static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
2546 int mdrcnt,int mprcnt,
2547 char **rdata,char **rparam,
2548 int *rdata_len,int *rparam_len)
2550 char *str1 = param+2;
2551 char *str2 = skip_string(str1,1);
2552 char *p = skip_string(str2,1);
2555 struct pack_desc desc;
2557 bzero(&desc,sizeof(desc));
2562 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2564 /* check it's a supported varient */
2565 if (strcmp(str1,"WrLeh") != 0) return False;
2566 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2568 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2569 bzero(&desc,sizeof(desc));
2571 desc.buflen = mdrcnt;
2573 if (init_package(&desc,1,0)) {
2574 PACKS(&desc,"B13","lp0");
2577 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2579 *rdata_len = desc.usedlen;
2582 *rparam = REALLOC(*rparam,*rparam_len);
2583 SSVALS(*rparam,0,desc.errcode);
2585 SSVAL(*rparam,4,succnt);
2588 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2599 } api_fd_commands [] =
2601 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2602 { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP },
2603 { NULL, NULL, -1, api_Unsupported }
2606 /****************************************************************************
2607 handle remote api calls delivered to a named pipe already opened.
2608 ****************************************************************************/
2609 static int api_fd_reply(int cnum,int uid,char *outbuf,
2610 uint16 *setup,char *data,char *params,
2611 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2614 char *rparam = NULL;
2622 /* First find out the name of this file. */
2625 DEBUG(0,("Unexpected named pipe transaction.\n"));
2629 /* Get the file handle and hence the file name. */
2631 subcommand = setup[0];
2633 DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2634 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2635 tdscnt,tpscnt,mdrcnt,mprcnt));
2637 for (i=0;api_fd_commands[i].name;i++)
2638 if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2639 api_fd_commands[i].subcommand == subcommand &&
2640 api_fd_commands[i].fn)
2642 DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2646 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2647 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2649 reply = api_fd_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2650 &rdata,&rparam,&rdata_len,&rparam_len);
2652 if (rdata_len > mdrcnt ||
2653 rparam_len > mprcnt)
2655 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2656 &rdata,&rparam,&rdata_len,&rparam_len);
2660 /* if we get False back then it's actually unsupported */
2662 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2663 &rdata,&rparam,&rdata_len,&rparam_len);
2665 /* now send the reply */
2666 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2678 /****************************************************************************
2679 the buffer was too small
2680 ****************************************************************************/
2681 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
2682 int mdrcnt,int mprcnt,
2683 char **rdata,char **rparam,
2684 int *rdata_len,int *rparam_len)
2686 *rparam_len = MIN(*rparam_len,mprcnt);
2687 *rparam = REALLOC(*rparam,*rparam_len);
2691 SSVAL(*rparam,0,NERR_BufTooSmall);
2693 DEBUG(3,("Supplied buffer too small in API command\n"));
2699 /****************************************************************************
2700 the request is not supported
2701 ****************************************************************************/
2702 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
2703 int mdrcnt,int mprcnt,
2704 char **rdata,char **rparam,
2705 int *rdata_len,int *rparam_len)
2708 *rparam = REALLOC(*rparam,*rparam_len);
2712 SSVAL(*rparam,0,NERR_notsupported);
2713 SSVAL(*rparam,2,0); /* converter word */
2715 DEBUG(3,("Unsupported API command\n"));
2729 } api_commands[] = {
2730 {"RNetShareEnum", 0, api_RNetShareEnum,0},
2731 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
2732 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
2733 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
2734 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
2735 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
2736 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
2737 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
2738 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
2739 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
2740 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
2741 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
2742 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
2743 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
2744 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
2745 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
2746 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
2747 {"NetServerEnum", 104, api_RNetServerEnum,0},
2748 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
2749 {"SetUserPassword", 115, api_SetUserPassword,0},
2750 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
2751 {"PrintJobInfo", 147, api_PrintJobInfo,0},
2752 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
2753 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
2754 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
2755 {NULL, -1, api_Unsupported,0}};
2758 /****************************************************************************
2759 handle remote api calls
2760 ****************************************************************************/
2761 static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
2762 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2764 int api_command = SVAL(params,0);
2766 char *rparam = NULL;
2772 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2773 api_command,params+2,skip_string(params+2,1),
2774 tdscnt,tpscnt,mdrcnt,mprcnt));
2776 for (i=0;api_commands[i].name;i++)
2777 if (api_commands[i].id == api_command && api_commands[i].fn)
2779 DEBUG(3,("Doing %s\n",api_commands[i].name));
2783 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2784 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2786 reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2787 &rdata,&rparam,&rdata_len,&rparam_len);
2790 if (rdata_len > mdrcnt ||
2791 rparam_len > mprcnt)
2793 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2794 &rdata,&rparam,&rdata_len,&rparam_len);
2798 /* if we get False back then it's actually unsupported */
2800 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2801 &rdata,&rparam,&rdata_len,&rparam_len);
2805 /* now send the reply */
2806 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2816 /****************************************************************************
2817 handle named pipe commands
2818 ****************************************************************************/
2819 static int named_pipe(int cnum,int uid, char *outbuf,char *name,
2820 uint16 *setup,char *data,char *params,
2821 int suwcnt,int tdscnt,int tpscnt,
2822 int msrcnt,int mdrcnt,int mprcnt)
2825 if (strequal(name,"LANMAN"))
2826 return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2828 if (strlen(name) < 1)
2829 return(api_fd_reply(cnum,uid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
2832 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2833 name,(int)setup[0],(int)setup[1]));
2839 /****************************************************************************
2841 ****************************************************************************/
2842 int reply_trans(char *inbuf,char *outbuf)
2846 char *data=NULL,*params=NULL;
2850 int cnum = SVAL(inbuf,smb_tid);
2851 int uid = SVAL(inbuf,smb_uid);
2853 int tpscnt = SVAL(inbuf,smb_vwv0);
2854 int tdscnt = SVAL(inbuf,smb_vwv1);
2855 int mprcnt = SVAL(inbuf,smb_vwv2);
2856 int mdrcnt = SVAL(inbuf,smb_vwv3);
2857 int msrcnt = CVAL(inbuf,smb_vwv4);
2858 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2859 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2860 int pscnt = SVAL(inbuf,smb_vwv9);
2861 int psoff = SVAL(inbuf,smb_vwv10);
2862 int dscnt = SVAL(inbuf,smb_vwv11);
2863 int dsoff = SVAL(inbuf,smb_vwv12);
2864 int suwcnt = CVAL(inbuf,smb_vwv13);
2866 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2870 data = (char *)malloc(tdscnt);
2871 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2875 params = (char *)malloc(tpscnt);
2876 memcpy(params,smb_base(inbuf)+psoff,pscnt);
2882 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
2883 for (i=0;i<suwcnt;i++)
2884 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
2888 if (pscnt < tpscnt || dscnt < tdscnt)
2890 /* We need to send an interim response then receive the rest
2891 of the parameter/data bytes */
2892 outsize = set_message(outbuf,0,0,True);
2894 send_smb(Client,outbuf);
2897 /* receive the rest of the trans packet */
2898 while (pscnt < tpscnt || dscnt < tdscnt)
2900 int pcnt,poff,dcnt,doff,pdisp,ddisp;
2902 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) ||
2903 CVAL(inbuf, smb_com) != SMBtrans)
2905 DEBUG(2,("Invalid secondary trans2 packet\n"));
2906 if (params) free(params);
2907 if (data) free(data);
2908 if (setup) free(setup);
2909 return(ERROR(ERRSRV,ERRerror));
2914 tpscnt = SVAL(inbuf,smb_vwv0);
2915 tdscnt = SVAL(inbuf,smb_vwv1);
2917 pcnt = SVAL(inbuf,smb_vwv2);
2918 poff = SVAL(inbuf,smb_vwv3);
2919 pdisp = SVAL(inbuf,smb_vwv4);
2921 dcnt = SVAL(inbuf,smb_vwv5);
2922 doff = SVAL(inbuf,smb_vwv6);
2923 ddisp = SVAL(inbuf,smb_vwv7);
2929 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
2931 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
2935 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
2938 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
2939 outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
2940 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
2943 if (data) free(data);
2944 if (params) free(params);
2945 if (setup) free(setup);
2947 if (close_on_completion)
2948 close_cnum(cnum,uid);
2954 return(ERROR(ERRSRV,ERRnosupport));