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 2
63 #define MINOR_VERSION 0
67 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
72 if (!src || !dst || !n || !(*dst)) return(0);
74 StrnCpy(buf,src,sizeof(buf)/2);
75 string_sub(buf,"%S",lp_servicename(snum));
76 standard_sub(cnum,buf);
84 static int CopyAndAdvance(char** dst, char* src, int* n)
87 if (!src || !dst || !n || !(*dst)) return(0);
95 static int StrlenExpanded(int cnum, int snum, char* s)
99 StrnCpy(buf,s,sizeof(buf)/2);
100 string_sub(buf,"%S",lp_servicename(snum));
101 standard_sub(cnum,buf);
102 return strlen(buf) + 1;
105 static char* Expand(int cnum, int snum, char* s)
108 if (!s) return(NULL);
109 StrnCpy(buf,s,sizeof(buf)/2);
110 string_sub(buf,"%S",lp_servicename(snum));
111 standard_sub(cnum,buf);
115 /*******************************************************************
116 check a API string for validity when we only need to check the prefix
117 ******************************************************************/
118 static BOOL prefix_ok(char *str,char *prefix)
120 return(strncmp(str,prefix,strlen(prefix)) == 0);
124 /****************************************************************************
126 ****************************************************************************/
127 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
128 int ldata,int lparam,int lsetup)
131 int this_ldata,this_lparam;
132 int tot_data=0,tot_param=0;
135 this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */
136 this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam));
138 align = (this_lparam%4);
140 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
142 memcpy(smb_buf(outbuf),param,this_lparam);
144 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
146 SSVAL(outbuf,smb_vwv0,lparam);
147 SSVAL(outbuf,smb_vwv1,ldata);
148 SSVAL(outbuf,smb_vwv3,this_lparam);
149 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
150 SSVAL(outbuf,smb_vwv5,0);
151 SSVAL(outbuf,smb_vwv6,this_ldata);
152 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
153 SSVAL(outbuf,smb_vwv8,0);
154 SSVAL(outbuf,smb_vwv9,lsetup);
155 for (i=0;i<lsetup;i++)
156 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
159 send_smb(Client,outbuf);
161 tot_data = this_ldata;
162 tot_param = this_lparam;
164 while (tot_data < ldata || tot_param < lparam)
166 this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
167 this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
169 align = (this_lparam%4);
171 set_message(outbuf,10,this_ldata+this_lparam+align,False);
173 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
175 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
177 SSVAL(outbuf,smb_vwv3,this_lparam);
178 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
179 SSVAL(outbuf,smb_vwv5,tot_param);
180 SSVAL(outbuf,smb_vwv6,this_ldata);
181 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
182 SSVAL(outbuf,smb_vwv8,tot_data);
183 SSVAL(outbuf,smb_vwv9,0);
186 send_smb(Client,outbuf);
188 tot_data += this_ldata;
189 tot_param += this_lparam;
194 char* format; /* formatstring for structure */
195 char* subformat; /* subformat for structure */
196 char* base; /* baseaddress of buffer */
197 int buflen; /* remaining size for fixed part; on init: length of base */
198 int subcount; /* count of substructures */
199 char* structbuf; /* pointer into buffer for remaining fixed part */
200 int stringlen; /* remaining size for variable part */
201 char* stringbuf; /* pointer into buffer for remaining variable part */
202 int neededlen; /* total needed size */
203 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
204 char* curpos; /* current position; pointer into format or subformat */
208 static int get_counter(char** p)
211 if (!p || !(*p)) return(1);
212 if (!isdigit(**p)) return 1;
216 n = 10 * n + (i - '0');
223 static int getlen(char* p)
229 case 'W': /* word (2 byte) */
232 case 'N': /* count of substructures (word) at end */
235 case 'D': /* double word (4 byte) */
236 case 'z': /* offset to zero terminated string (4 byte) */
237 case 'l': /* offset to user data (4 byte) */
240 case 'b': /* offset to data (with counter) (4 byte) */
244 case 'B': /* byte (with optional counter) */
245 n += get_counter(&p);
252 static BOOL init_package(struct pack_desc* p, int count, int subcount)
257 if (!p->format || !p->base) return(False);
259 i = count * getlen(p->format);
260 if (p->subformat) i += subcount * getlen(p->subformat);
261 p->structbuf = p->base;
265 p->curpos = p->format;
268 p->errcode = NERR_BufTooSmall;
271 p->errcode = NERR_Success;
274 p->stringbuf = p->base + i;
276 return(p->errcode == NERR_Success);
280 static int package(struct pack_desc* p, ...)
283 static int package(va_alist)
289 int needed=0, stringneeded;
291 int is_string=0, stringused;
298 p = va_arg(args,struct pack_desc *);
303 p->curpos = p->format;
305 p->curpos = p->subformat;
310 str = va_arg(args,char*);
311 if (strncmp(str,p->curpos,strlen(str)) != 0) {
312 DEBUG(2,("type error in package: %s instead of %*s\n",str,
313 strlen(str),p->curpos));
323 if (!p->curpos) return(0);
325 switch( *p->curpos++ ) {
326 case 'W': /* word (2 byte) */
328 temp = va_arg(args,int);
329 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
331 case 'N': /* count of substructures (word) at end */
333 p->subcount = va_arg(args,int);
334 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
336 case 'D': /* double word (4 byte) */
338 temp = va_arg(args,int);
339 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
341 case 'B': /* byte (with optional counter) */
342 needed = get_counter(&p->curpos);
344 char *s = va_arg(args,char*);
345 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
348 case 'z': /* offset to zero terminated string (4 byte) */
349 str = va_arg(args,char*);
350 stringneeded = (str ? strlen(str)+1 : 0);
353 case 'l': /* offset to user data (4 byte) */
354 str = va_arg(args,char*);
355 stringneeded = va_arg(args,int);
358 case 'b': /* offset to data (with counter) (4 byte) */
359 str = va_arg(args,char*);
360 stringneeded = get_counter(&p->curpos);
365 if (stringneeded >= 0) {
367 if (p->buflen >= needed) {
368 stringused = stringneeded;
369 if (stringused > p->stringlen) {
370 stringused = (is_string ? p->stringlen : 0);
371 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
374 SIVAL(p->structbuf,0,0);
376 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
377 memcpy(p->stringbuf,str?str:"",stringused);
378 if (is_string) p->stringbuf[stringused-1] = '\0';
379 p->stringbuf += stringused;
380 p->stringlen -= stringused;
381 p->usedlen += stringused;
384 p->neededlen += stringneeded;
386 p->neededlen += needed;
387 if (p->buflen >= needed) {
388 p->structbuf += needed;
390 p->usedlen += needed;
393 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
399 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
400 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
402 #define PACK(desc,t,v) package(desc,v)
403 #define PACKl(desc,t,v,l) package(desc,v,l)
406 static void PACKI(struct pack_desc* desc,char *t,int v)
411 static void PACKS(struct pack_desc* desc,char *t,char *v)
417 /****************************************************************************
419 ****************************************************************************/
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","WinPrint"); /* 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",lp_printerdriver(snum)); /* 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 /* remove any trailing username */
597 if ((p = strchr(QueueName,'%'))) *p = 0;
599 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
601 /* check it's a supported varient */
602 if (!prefix_ok(str1,"zWrLh")) return False;
603 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
605 snum = lp_servicenumber(QueueName);
606 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
607 int pnum = lp_servicenumber(PRINTERS_NAME);
609 lp_add_printer(QueueName,pnum);
610 snum = lp_servicenumber(QueueName);
614 if (snum < 0 || !VALID_SNUM(snum)) return(False);
616 count = get_printqueue(snum,cnum,&queue,&status);
617 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
619 desc.buflen = mdrcnt;
620 if (init_package(&desc,1,count)) {
621 desc.subcount = count;
622 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
625 *rdata_len = desc.usedlen;
628 *rparam = REALLOC(*rparam,*rparam_len);
629 SSVALS(*rparam,0,desc.errcode);
631 SSVAL(*rparam,4,desc.neededlen);
633 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
635 if (queue) free(queue);
641 /****************************************************************************
642 view list of all print jobs on all queues
643 ****************************************************************************/
644 static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
645 int mdrcnt, int mprcnt,
646 char **rdata, char** rparam,
647 int *rdata_len, int *rparam_len)
649 char *param_format = param+2;
650 char *output_format1 = skip_string(param_format,1);
651 char *p = skip_string(output_format1,1);
652 int uLevel = SVAL(p,0);
653 char *output_format2 = p + 4;
654 int services = lp_numservices();
656 struct pack_desc desc;
657 print_queue_struct **queue = NULL;
658 print_status_struct *status = NULL;
659 int* subcntarr = NULL;
660 int queuecnt, subcnt=0, succnt=0;
662 bzero(&desc,sizeof(desc));
664 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
666 if (!prefix_ok(param_format,"WrLeh")) return False;
667 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
670 for (i = 0; i < services; i++)
671 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
674 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
675 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
676 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
677 memset(status,0,queuecnt*sizeof(print_status_struct));
678 subcntarr = (int*)malloc(queuecnt*sizeof(int));
681 for (i = 0; i < services; i++)
682 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
683 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
684 subcnt += subcntarr[n];
688 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
690 desc.buflen = mdrcnt;
692 if (init_package(&desc,queuecnt,subcnt)) {
695 for (i = 0; i < services; i++)
696 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
697 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
699 if (desc.errcode == NERR_Success) succnt = n;
703 if (subcntarr) free(subcntarr);
705 *rdata_len = desc.usedlen;
707 *rparam = REALLOC(*rparam,*rparam_len);
708 SSVALS(*rparam,0,desc.errcode);
710 SSVAL(*rparam,4,succnt);
711 SSVAL(*rparam,6,queuecnt);
713 for (i = 0; i < queuecnt; i++) {
714 if (queue && queue[i]) free(queue[i]);
717 if (queue) free(queue);
718 if (status) free(status);
723 /****************************************************************************
724 get info level for a server list query
725 ****************************************************************************/
726 static BOOL check_server_info(int uLevel, char* id)
730 if (strcmp(id,"B16") != 0) return False;
733 if (strcmp(id,"B16BBDz") != 0) return False;
741 /* used for server information: client, nameserv and ipc */
742 struct srv_info_struct
747 fstring domain; /* used ONLY in ipc.c NOT namework.c */
748 BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
751 /*******************************************************************
752 filter out unwanted server info
753 ******************************************************************/
754 static BOOL filter_server_info(struct srv_info_struct *server,
756 char *domain, uint32 request)
760 if (strequal(lp_workgroup(), server->domain)) {
765 DEBUG(4,("primary domain:reject %8x %s %s\n",request,server->name,server->domain));
768 else if ((request & SV_TYPE_DOMAIN_ENUM) &&
769 (server->type & SV_TYPE_DOMAIN_ENUM))
771 DEBUG(4,("rej:DOM %8x: %s %s\n",server->type,server->name,server->domain));
779 if (strequal(domain, server->domain))
782 if (request == SV_TYPE_LOCAL_LIST_ONLY &&
783 !(server->type & SV_TYPE_LOCAL_LIST_ONLY))
785 DEBUG(4,("rej:LOC %8x: ok %s %s\n",request,server->name,server->domain));
789 if ((request == (SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM)) &&
790 !(server->type&SV_TYPE_DOMAIN_ENUM))
792 DEBUG(4,("rej:LOCDOM %8x: ok %s %s\n",request,server->name,server->domain));
800 DEBUG(4,("domain:%s %s %s\n",domain,server->name,server->domain));
807 /*******************************************************************
808 get server info lists from the files saved by nmbd. Return the
810 ******************************************************************/
811 static int get_server_info(uint32 servertype,
812 struct srv_info_struct **servers, BOOL domains,
821 strcpy(fname,lp_lockdir());
822 trim_string(fname,NULL,"/");
824 strcat(fname,SERVER_LIST);
826 f = fopen(fname,"r");
829 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
833 /* request for everything is code for request all servers */
834 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
836 DEBUG(4,("Servertype search: %8x domains:%s\n",servertype,BOOLSTR(domains)));
841 struct srv_info_struct *s;
846 fgets(line,sizeof(line)-1,f);
847 if (!*line) continue;
849 if (count == alloced) {
851 (*servers) = (struct srv_info_struct *)
852 Realloc(*servers,sizeof(**servers)*alloced);
853 if (!(*servers)) return(0);
854 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
856 s = &(*servers)[count];
858 if (!next_token(&ptr,s->name , NULL)) continue;
859 if (!next_token(&ptr,stype , NULL)) continue;
860 if (!next_token(&ptr,s->comment, NULL)) continue;
861 if (!next_token(&ptr,s->domain , NULL)) {
862 /* this allows us to cope with an old nmbd */
863 strcpy(s->domain,my_workgroup());
866 if (sscanf(stype,"%X",&s->type) != 1) {
867 DEBUG(4,("r:host file "));
871 /* doesn't match up: don't want it */
872 if (!(servertype & s->type)) {
873 DEBUG(4,("r:serv type "));
877 if ((servertype == ~SV_TYPE_DOMAIN_ENUM) &&
878 (s->type & SV_TYPE_DOMAIN_ENUM))
880 DEBUG(4,("s:all x dom "));
884 if (domains && !(domain && *domain && strequal(domain, s->domain)))
886 if (!(s->type & SV_TYPE_DOMAIN_ENUM))
888 DEBUG(4,("r:dom enum "));
895 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
896 s->name, s->type, s->comment, s->domain));
898 s->type |= SV_TYPE_LOCAL_LIST_ONLY;
899 s->server_added = True;
904 DEBUG(4,("%20s %8x %25s %15s\n",
905 s->name, s->type, s->comment, s->domain));
914 /*******************************************************************
915 fill in a server info structure
916 ******************************************************************/
917 static int fill_srv_info(struct srv_info_struct *service,
918 int uLevel, char **buf, int *buflen,
919 char **stringbuf, int *stringspace, char *baseaddr)
928 case 0: struct_len = 16; break;
929 case 1: struct_len = 26; break;
939 len = strlen(service->comment)+1;
943 if (buflen) *buflen = struct_len;
944 if (stringspace) *stringspace = len;
945 return struct_len + len;
950 if (*buflen < struct_len) return -1;
959 l2 = *buflen - struct_len;
961 if (!baseaddr) baseaddr = p;
966 StrnCpy(p,service->name,15);
970 StrnCpy(p,service->name,15);
971 SIVAL(p,18,service->type);
972 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
973 len += CopyAndAdvance(&p2,service->comment,&l2);
979 *buf = p + struct_len;
980 *buflen -= struct_len;
993 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
995 return(strcmp(s1->name,s2->name));
998 /****************************************************************************
999 view list of servers available (or possibly domains). The info is
1000 extracted from lists saved by nmbd on the local host
1001 ****************************************************************************/
1002 static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
1003 int mdrcnt, int mprcnt, char **rdata,
1004 char **rparam, int *rdata_len, int *rparam_len)
1006 char *str1 = param+2;
1007 char *str2 = skip_string(str1,1);
1008 char *p = skip_string(str2,1);
1009 int uLevel = SVAL(p,0);
1010 int buf_len = SVAL(p,2);
1011 uint32 servertype = IVAL(p,4);
1013 int data_len, fixed_len, string_len;
1015 struct srv_info_struct *servers=NULL;
1016 int counted=0,total=0;
1020 BOOL domain_request;
1021 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
1023 /*if (servertype == SV_TYPE_ALL) servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);*/
1024 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
1026 domain_request = servertype & SV_TYPE_DOMAIN_ENUM;
1031 if (!prefix_ok(str1,"WrLehD")) return False;
1032 if (!check_server_info(uLevel,str2)) return False;
1034 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1035 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1036 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1038 if (strcmp(str1, "WrLehDO") == 0)
1042 else if (strcmp(str1, "WrLehDz") == 0)
1045 StrnCpy(domain, p, sizeof(fstring)-1);
1048 if (lp_browse_list())
1050 total = get_server_info(servertype,&servers,domains,domain);
1053 data_len = fixed_len = string_len = 0;
1055 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1058 char *lastname=NULL;
1060 for (i=0;i<total;i++)
1062 struct srv_info_struct *s = &servers[i];
1063 if (filter_server_info(s,domains,domain,
1064 local_request|domain_request))
1066 if (lastname && strequal(lastname,s->name)) continue;
1068 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1069 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1070 s->name, s->type, s->comment, s->domain));
1072 if (data_len <= buf_len)
1076 string_len += s_len;
1082 *rdata_len = fixed_len + string_len;
1083 *rdata = REALLOC(*rdata,*rdata_len);
1084 bzero(*rdata,*rdata_len);
1086 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1092 char *lastname=NULL;
1093 int count2 = counted;
1094 for (i = 0; i < total && count2;i++)
1096 struct srv_info_struct *s = &servers[i];
1097 if (filter_server_info(s,domains,domain,local_request|domain_request))
1099 if (lastname && strequal(lastname,s->name)) continue;
1101 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1102 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1103 s->name, s->type, s->comment, s->domain));
1110 *rparam = REALLOC(*rparam,*rparam_len);
1111 SSVAL(*rparam,0,NERR_Success);
1113 SSVAL(*rparam,4,counted);
1114 SSVAL(*rparam,6,total);
1116 if (servers) free(servers);
1118 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1119 domain,uLevel,counted,total));
1125 /****************************************************************************
1126 get info about a share
1127 ****************************************************************************/
1128 static BOOL check_share_info(int uLevel, char* id)
1132 if (strcmp(id,"B13") != 0) return False;
1135 if (strcmp(id,"B13BWz") != 0) return False;
1138 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1141 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1143 default: return False;
1148 static int fill_share_info(int cnum, int snum, int uLevel,
1149 char** buf, int* buflen,
1150 char** stringbuf, int* stringspace, char* baseaddr)
1159 case 0: struct_len = 13; break;
1160 case 1: struct_len = 20; break;
1161 case 2: struct_len = 40; break;
1162 case 91: struct_len = 68; break;
1170 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1171 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1172 if (buflen) *buflen = struct_len;
1173 if (stringspace) *stringspace = len;
1174 return struct_len + len;
1179 if ((*buflen) < struct_len) return -1;
1187 p2 = p + struct_len;
1188 l2 = (*buflen) - struct_len;
1190 if (!baseaddr) baseaddr = p;
1192 StrnCpy(p,lp_servicename(snum),13);
1198 type = STYPE_DISKTREE;
1199 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1200 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1201 SSVAL(p,14,type); /* device type */
1202 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1203 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1208 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1209 SSVALS(p,22,-1); /* max uses */
1210 SSVAL(p,24,1); /* current uses */
1211 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1212 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1213 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1218 memset(p+40,0,SHPWLEN+2);
1230 (*buf) = p + struct_len;
1231 (*buflen) -= struct_len;
1233 (*stringspace) = l2;
1243 static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
1244 int mdrcnt,int mprcnt,
1245 char **rdata,char **rparam,
1246 int *rdata_len,int *rparam_len)
1248 char *str1 = param+2;
1249 char *str2 = skip_string(str1,1);
1250 char *netname = skip_string(str2,1);
1251 char *p = skip_string(netname,1);
1252 int uLevel = SVAL(p,0);
1253 int snum = find_service(netname);
1255 if (snum < 0) return False;
1257 /* check it's a supported varient */
1258 if (!prefix_ok(str1,"zWrLh")) return False;
1259 if (!check_share_info(uLevel,str2)) return False;
1261 *rdata = REALLOC(*rdata,mdrcnt);
1263 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1264 if (*rdata_len < 0) return False;
1267 *rparam = REALLOC(*rparam,*rparam_len);
1268 SSVAL(*rparam,0,NERR_Success);
1269 SSVAL(*rparam,2,0); /* converter word */
1270 SSVAL(*rparam,4,*rdata_len);
1275 /****************************************************************************
1276 view list of shares available
1277 ****************************************************************************/
1278 static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
1279 int mdrcnt,int mprcnt,
1280 char **rdata,char **rparam,
1281 int *rdata_len,int *rparam_len)
1283 char *str1 = param+2;
1284 char *str2 = skip_string(str1,1);
1285 char *p = skip_string(str2,1);
1286 int uLevel = SVAL(p,0);
1287 int buf_len = SVAL(p,2);
1289 int count=lp_numservices();
1290 int total=0,counted=0;
1292 int data_len, fixed_len, string_len;
1295 if (!prefix_ok(str1,"WrLeh")) return False;
1296 if (!check_share_info(uLevel,str2)) return False;
1298 data_len = fixed_len = string_len = 0;
1299 for (i=0;i<count;i++)
1300 if (lp_browseable(i) && lp_snum_ok(i))
1303 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1304 if (data_len <= buf_len)
1308 string_len += s_len;
1311 *rdata_len = fixed_len + string_len;
1312 *rdata = REALLOC(*rdata,*rdata_len);
1313 memset(*rdata,0,*rdata_len);
1315 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1319 for (i = 0; i < count;i++)
1320 if (lp_browseable(i) && lp_snum_ok(i))
1321 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1325 *rparam = REALLOC(*rparam,*rparam_len);
1326 SSVAL(*rparam,0,NERR_Success);
1328 SSVAL(*rparam,4,counted);
1329 SSVAL(*rparam,6,total);
1331 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1332 counted,total,uLevel,
1333 buf_len,*rdata_len,mdrcnt));
1339 /****************************************************************************
1340 get the time of day info
1341 ****************************************************************************/
1342 static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
1343 int mdrcnt,int mprcnt,
1344 char **rdata,char **rparam,
1345 int *rdata_len,int *rparam_len)
1349 *rparam = REALLOC(*rparam,*rparam_len);
1352 *rdata = REALLOC(*rdata,*rdata_len);
1354 SSVAL(*rparam,0,NERR_Success);
1355 SSVAL(*rparam,2,0); /* converter word */
1361 time_t unixdate = time(NULL);
1363 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1364 by NT in a "net time" operation,
1365 it seems to ignore the one below */
1367 /* the client expects to get localtime, not GMT, in this bit
1368 (I think, this needs testing) */
1369 t = LocalTime(&unixdate);
1371 SIVAL(p,4,0); /* msecs ? */
1372 CVAL(p,8) = t->tm_hour;
1373 CVAL(p,9) = t->tm_min;
1374 CVAL(p,10) = t->tm_sec;
1375 CVAL(p,11) = 0; /* hundredths of seconds */
1376 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1377 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1378 CVAL(p,16) = t->tm_mday;
1379 CVAL(p,17) = t->tm_mon + 1;
1380 SSVAL(p,18,1900+t->tm_year);
1381 CVAL(p,20) = t->tm_wday;
1388 /****************************************************************************
1389 set the user password
1390 ****************************************************************************/
1391 static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
1392 int mdrcnt,int mprcnt,
1393 char **rdata,char **rparam,
1394 int *rdata_len,int *rparam_len)
1396 char *p = skip_string(param+2,2);
1398 fstring pass1,pass2;
1402 p = skip_string(p,1);
1404 StrnCpy(pass1,p,16);
1405 StrnCpy(pass2,p+16,16);
1408 *rparam = REALLOC(*rparam,*rparam_len);
1412 SSVAL(*rparam,0,NERR_badpass);
1413 SSVAL(*rparam,2,0); /* converter word */
1415 DEBUG(3,("Set password for <%s>\n",user));
1417 if (password_ok(user,pass1,strlen(pass1),NULL,False) &&
1418 chgpasswd(user,pass1,pass2))
1420 SSVAL(*rparam,0,NERR_Success);
1423 bzero(pass1,sizeof(fstring));
1424 bzero(pass2,sizeof(fstring));
1429 /****************************************************************************
1432 ****************************************************************************/
1433 static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
1434 int mdrcnt,int mprcnt,
1435 char **rdata,char **rparam,
1436 int *rdata_len,int *rparam_len)
1438 int function = SVAL(param,0);
1439 char *str1 = param+2;
1440 char *str2 = skip_string(str1,1);
1441 char *p = skip_string(str2,1);
1442 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1443 by the print queue api */
1444 int snum = (SVAL(p,0)>>8);
1448 /* check it's a supported varient */
1449 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1453 *rparam = REALLOC(*rparam,*rparam_len);
1457 SSVAL(*rparam,0,NERR_Success);
1459 if (snum >= 0 && VALID_SNUM(snum))
1461 print_queue_struct *queue=NULL;
1463 count = get_printqueue(snum,cnum,&queue,NULL);
1465 for (i=0;i<count;i++)
1466 if ((queue[i].job%0xFF) == jobid)
1469 case 81: /* delete */
1470 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1471 del_printqueue(cnum,snum,queue[i].job);
1473 case 82: /* pause */
1474 case 83: /* resume */
1475 DEBUG(3,("%s queue entry %d\n",
1476 (function==82?"pausing":"resuming"),queue[i].job));
1477 status_printjob(cnum,snum,queue[i].job,
1478 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1485 SSVAL(*rparam,0,NERR_JobNotFound);
1487 if (queue) free(queue);
1490 SSVAL(*rparam,2,0); /* converter word */
1495 static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data,
1496 int mdrcnt,int mprcnt,
1497 char **rdata,char **rparam,
1498 int *rdata_len,int *rparam_len)
1500 char *str1 = param+2;
1501 char *str2 = skip_string(str1,1);
1502 char *QueueName = skip_string(str2,1);
1505 /* check it's a supported varient */
1506 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1510 *rparam = REALLOC(*rparam,*rparam_len);
1514 SSVAL(*rparam,0,NERR_Success);
1515 SSVAL(*rparam,2,0); /* converter word */
1517 snum = lp_servicenumber(QueueName);
1518 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1519 int pnum = lp_servicenumber(PRINTERS_NAME);
1521 lp_add_printer(QueueName,pnum);
1522 snum = lp_servicenumber(QueueName);
1526 if (snum >= 0 && VALID_SNUM(snum)) {
1527 print_queue_struct *queue=NULL;
1531 count = get_printqueue(snum,cnum,&queue,NULL);
1532 for (i = 0; i < count; i++)
1533 del_printqueue(cnum,snum,queue[i].job);
1535 if (queue) free(queue);
1538 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1544 /****************************************************************************
1545 set the property of a print job (undocumented?)
1546 ? function = 0xb -> set name of print job
1547 ? function = 0x6 -> move print job up/down
1548 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1549 or <WWsTP> <WB21BB16B10zWWzDDz>
1550 ****************************************************************************/
1551 static int check_printjob_info(struct pack_desc* desc,
1552 int uLevel, char* id)
1554 desc->subformat = NULL;
1556 case 0: desc->format = "W"; break;
1557 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1558 case 2: desc->format = "WWzWWDDzz"; break;
1559 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1560 default: return False;
1562 if (strcmp(desc->format,id) != 0) return False;
1566 static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
1567 int mdrcnt,int mprcnt,
1568 char **rdata,char **rparam,
1569 int *rdata_len,int *rparam_len)
1571 struct pack_desc desc;
1572 char *str1 = param+2;
1573 char *str2 = skip_string(str1,1);
1574 char *p = skip_string(str2,1);
1575 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1576 by the print queue api */
1577 int snum = (SVAL(p,0)>>8);
1578 int uLevel = SVAL(p,2);
1579 int function = SVAL(p,4); /* what is this ?? */
1584 *rparam = REALLOC(*rparam,*rparam_len);
1588 /* check it's a supported varient */
1589 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1593 case 0x6: /* change job place in the queue, data gives the new place */
1594 if (snum >= 0 && VALID_SNUM(snum))
1596 print_queue_struct *queue=NULL;
1600 count = get_printqueue(snum,cnum,&queue,NULL);
1601 for (i=0;i<count;i++) /* find job */
1602 if ((queue[i].job%0xFF) == jobid) break;
1605 desc.errcode=NERR_JobNotFound;
1606 if (queue) free(queue);
1609 desc.errcode=NERR_Success;
1613 int place= SVAL(data,0);
1614 /* we currently have no way of doing this. Can any unix do it? */
1615 if (i < place) /* move down */;
1616 else if (i > place ) /* move up */;
1619 desc.errcode=NERR_notsupported; /* not yet supported */
1620 if (queue) free(queue);
1623 else desc.errcode=NERR_JobNotFound;
1625 case 0xb: /* change print job name, data gives the name */
1626 /* jobid, snum should be zero */
1633 if (issafe(*s)) name[l++] = *s;
1638 DEBUG(3,("Setting print name to %s\n",name));
1640 for (i=0;i<MAX_OPEN_FILES;i++)
1641 if (Files[i].open && Files[i].print_file)
1647 if (!become_user(Files[i].cnum,uid) ||
1648 !become_service(Files[i].cnum,True))
1651 if (sys_rename(Files[i].name,name) == 0)
1652 string_set(&Files[i].name,name);
1656 desc.errcode=NERR_Success;
1659 default: /* not implemented */
1663 SSVALS(*rparam,0,desc.errcode);
1664 SSVAL(*rparam,2,0); /* converter word */
1670 /****************************************************************************
1671 get info about the server
1672 ****************************************************************************/
1673 static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
1674 int mdrcnt,int mprcnt,
1675 char **rdata,char **rparam,
1676 int *rdata_len,int *rparam_len)
1678 char *str1 = param+2;
1679 char *str2 = skip_string(str1,1);
1680 char *p = skip_string(str2,1);
1681 int uLevel = SVAL(p,0);
1685 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1687 /* check it's a supported varient */
1688 if (!prefix_ok(str1,"WrLh")) return False;
1691 if (strcmp(str2,"B16") != 0) return False;
1695 if (strcmp(str2,"B16BBDz") != 0) return False;
1699 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1704 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1709 if (strcmp(str2,"DN") != 0) return False;
1713 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1716 default: return False;
1719 *rdata_len = mdrcnt;
1720 *rdata = REALLOC(*rdata,*rdata_len);
1723 p2 = p + struct_len;
1725 StrnCpy(p,local_machine,16);
1731 struct srv_info_struct *servers=NULL;
1734 uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION|
1735 SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE;
1737 strcpy(comment,lp_serverstring());
1739 if ((count=get_server_info(SV_TYPE_ALL,&servers,False,NULL))>0) {
1740 for (i=0;i<count;i++)
1741 if (strequal(servers[i].name,local_machine)) {
1742 servertype = servers[i].type;
1743 strcpy(comment,servers[i].comment);
1746 if (servers) free(servers);
1748 SCVAL(p,0,MAJOR_VERSION);
1749 SCVAL(p,1,MINOR_VERSION);
1750 SIVAL(p,2,servertype);
1752 if (mdrcnt == struct_len) {
1755 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1756 standard_sub(cnum,comment);
1757 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1758 p2 = skip_string(p2,1);
1763 return False; /* not yet implemented */
1766 *rdata_len = PTR_DIFF(p2,*rdata);
1769 *rparam = REALLOC(*rparam,*rparam_len);
1770 SSVAL(*rparam,0,NERR_Success);
1771 SSVAL(*rparam,2,0); /* converter word */
1772 SSVAL(*rparam,4,*rdata_len);
1778 /****************************************************************************
1779 get info about the server
1780 ****************************************************************************/
1781 static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
1782 int mdrcnt,int mprcnt,
1783 char **rdata,char **rparam,
1784 int *rdata_len,int *rparam_len)
1786 char *str1 = param+2;
1787 char *str2 = skip_string(str1,1);
1788 char *p = skip_string(str2,1);
1790 extern pstring sesssetup_user;
1791 int level = SVAL(p,0);
1793 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1796 *rparam = REALLOC(*rparam,*rparam_len);
1798 /* check it's a supported varient */
1799 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1802 *rdata_len = mdrcnt + 1024;
1803 *rdata = REALLOC(*rdata,*rdata_len);
1805 SSVAL(*rparam,0,NERR_Success);
1806 SSVAL(*rparam,2,0); /* converter word */
1811 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1812 strcpy(p2,local_machine);
1813 p2 = skip_string(p2,1);
1816 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1817 strcpy(p2,sesssetup_user);
1818 p2 = skip_string(p2,1);
1821 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1822 strcpy(p2,my_workgroup());
1823 p2 = skip_string(p2,1);
1826 SCVAL(p,0,MAJOR_VERSION);
1827 SCVAL(p,1,MINOR_VERSION);
1830 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1831 strcpy(p2,my_workgroup()); /* login domain?? */
1832 p2 = skip_string(p2,1);
1835 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1837 p2 = skip_string(p2,1);
1840 *rdata_len = PTR_DIFF(p2,*rdata);
1842 SSVAL(*rparam,4,*rdata_len);
1848 /****************************************************************************
1849 get info about a user
1850 ****************************************************************************/
1852 #define USER_PRIV_GUEST 0
1853 #define USER_PRIV_USER 1
1854 #define USER_PRIV_ADMIN 2
1856 static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
1857 int mdrcnt,int mprcnt,
1858 char **rdata,char **rparam,
1859 int *rdata_len,int *rparam_len)
1861 char *str1 = param+2;
1862 char *str2 = skip_string(str1,1);
1863 char *UserName = skip_string(str2,1);
1864 char *p = skip_string(UserName,1);
1865 int uLevel = SVAL(p,0);
1869 *rparam = REALLOC(*rparam,*rparam_len);
1871 /* check it's a supported varient */
1872 if (strcmp(str1,"zWrLh") != 0) return False;
1874 case 0: p2 = "B21"; break;
1875 case 1: p2 = "B21BB16DWzzWz"; break;
1876 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1877 case 10: p2 = "B21Bzzz"; break;
1878 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1879 default: return False;
1881 if (strcmp(p2,str2) != 0) return False;
1883 *rdata_len = mdrcnt + 1024;
1884 *rdata = REALLOC(*rdata,*rdata_len);
1886 SSVAL(*rparam,0,NERR_Success);
1887 SSVAL(*rparam,2,0); /* converter word */
1898 SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
1899 strcpy(p2,"<Comment>");
1900 p2 = skip_string(p2,1);
1901 SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
1902 strcpy(p2,"<UserComment>");
1903 p2 = skip_string(p2,1);
1904 SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
1905 strcpy(p2,"<FullName>");
1906 p2 = skip_string(p2,1);
1908 if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
1909 SSVAL(p,34,USER_PRIV_USER); /* user privilege */
1910 SIVAL(p,36,0); /* auth flags */
1911 SIVALS(p,40,-1); /* password age */
1912 SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
1913 strcpy(p2,"\\\\%L\\HOMES");
1914 standard_sub_basic(p2);
1915 p2 = skip_string(p2,1);
1916 SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
1918 p2 = skip_string(p2,1);
1919 SIVAL(p,52,0); /* last logon */
1920 SIVAL(p,56,0); /* last logoff */
1921 SSVALS(p,60,-1); /* bad pw counts */
1922 SSVALS(p,62,-1); /* num logons */
1923 SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
1925 p2 = skip_string(p2,1);
1926 SSVAL(p,68,0); /* country code */
1928 SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
1930 p2 = skip_string(p2,1);
1932 SIVALS(p,74,-1); /* max storage */
1933 SSVAL(p,78,168); /* units per week */
1934 SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
1936 SCVAL(p2,21,0); /* fix zero termination */
1937 p2 = skip_string(p2,1);
1939 SSVAL(p,84,0); /* code page */
1941 if (uLevel == 1 || uLevel == 2) {
1942 memset(p+22,' ',16); /* password */
1943 SIVALS(p,38,-1); /* password age */
1944 SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */
1945 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
1946 strcpy(p2,"\\\\%L\\HOMES");
1947 standard_sub_basic(p2);
1948 p2 = skip_string(p2,1);
1949 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
1951 SSVAL(p,52,0); /* flags */
1952 SIVAL(p,54,0); /* script_path */
1954 SIVAL(p,60,0); /* auth_flags */
1955 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
1956 strcpy(p2,"<Full Name>");
1957 p2 = skip_string(p2,1);
1958 SIVAL(p,68,0); /* urs_comment */
1959 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
1961 p2 = skip_string(p2,1);
1962 SIVAL(p,76,0); /* workstations */
1963 SIVAL(p,80,0); /* last_logon */
1964 SIVAL(p,84,0); /* last_logoff */
1965 SIVALS(p,88,-1); /* acct_expires */
1966 SIVALS(p,92,-1); /* max_storage */
1967 SSVAL(p,96,168); /* units_per_week */
1968 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
1971 SSVALS(p,102,-1); /* bad_pw_count */
1972 SSVALS(p,104,-1); /* num_logons */
1973 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
1974 strcpy(p2,"\\\\%L");
1975 standard_sub_basic(p2);
1976 p2 = skip_string(p2,1);
1977 SSVAL(p,110,49); /* country_code */
1978 SSVAL(p,112,860); /* code page */
1983 *rdata_len = PTR_DIFF(p2,*rdata);
1985 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
1991 /*******************************************************************
1992 get groups that a user is a member of
1993 ******************************************************************/
1994 static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
1995 int mdrcnt,int mprcnt,
1996 char **rdata,char **rparam,
1997 int *rdata_len,int *rparam_len)
1999 char *str1 = param+2;
2000 char *str2 = skip_string(str1,1);
2001 char *UserName = skip_string(str2,1);
2002 char *p = skip_string(UserName,1);
2003 int uLevel = SVAL(p,0);
2008 *rparam = REALLOC(*rparam,*rparam_len);
2010 /* check it's a supported varient */
2011 if (strcmp(str1,"zWrLeh") != 0) return False;
2013 case 0: p2 = "B21"; break;
2014 default: return False;
2016 if (strcmp(p2,str2) != 0) return False;
2018 *rdata_len = mdrcnt + 1024;
2019 *rdata = REALLOC(*rdata,*rdata_len);
2021 SSVAL(*rparam,0,NERR_Success);
2022 SSVAL(*rparam,2,0); /* converter word */
2026 /* XXXX we need a real SAM database some day */
2027 strcpy(p,"Users"); p += 21; count++;
2028 strcpy(p,"Domain Users"); p += 21; count++;
2029 strcpy(p,"Guests"); p += 21; count++;
2030 strcpy(p,"Domain Guests"); p += 21; count++;
2032 *rdata_len = PTR_DIFF(p,*rdata);
2034 SSVAL(*rparam,4,count); /* is this right?? */
2035 SSVAL(*rparam,6,count); /* is this right?? */
2041 static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
2042 int mdrcnt,int mprcnt,
2043 char **rdata,char **rparam,
2044 int *rdata_len,int *rparam_len)
2046 char *str1 = param+2;
2047 char *str2 = skip_string(str1,1);
2048 char *p = skip_string(str2,1);
2050 struct pack_desc desc;
2056 bzero(&desc,sizeof(desc));
2058 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2060 /* check it's a supported varient */
2061 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2062 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2063 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2065 desc.buflen = mdrcnt;
2066 desc.subformat = NULL;
2071 if (init_package(&desc,1,0)) {
2072 PACKI(&desc,"W",0); /* code */
2073 PACKS(&desc,"B21",name); /* eff. name */
2074 PACKS(&desc,"B",""); /* pad */
2076 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2077 PACKI(&desc,"D",0); /* auth flags XXX */
2078 PACKI(&desc,"W",0); /* num logons */
2079 PACKI(&desc,"W",0); /* bad pw count */
2080 PACKI(&desc,"D",-1); /* last logon */
2081 PACKI(&desc,"D",-1); /* last logoff */
2082 PACKI(&desc,"D",-1); /* logoff time */
2083 PACKI(&desc,"D",-1); /* kickoff time */
2084 PACKI(&desc,"D",0); /* password age */
2085 PACKI(&desc,"D",0); /* password can change */
2086 PACKI(&desc,"D",-1); /* password must change */
2089 strcpy(mypath,"\\\\");
2090 strcat(mypath,local_machine);
2092 PACKS(&desc,"z",mypath); /* computer */
2094 PACKS(&desc,"z",my_workgroup());/* domain */
2095 PACKS(&desc,"z",lp_logon_script()); /* script path */
2096 PACKI(&desc,"D",0); /* reserved */
2099 *rdata_len = desc.usedlen;
2101 *rparam = REALLOC(*rparam,*rparam_len);
2102 SSVALS(*rparam,0,desc.errcode);
2104 SSVAL(*rparam,4,desc.neededlen);
2106 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2111 /****************************************************************************
2112 api_WAccessGetUserPerms
2113 ****************************************************************************/
2114 static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
2115 int mdrcnt,int mprcnt,
2116 char **rdata,char **rparam,
2117 int *rdata_len,int *rparam_len)
2119 char *str1 = param+2;
2120 char *str2 = skip_string(str1,1);
2121 char *user = skip_string(str2,1);
2122 char *resource = skip_string(user,1);
2124 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2126 /* check it's a supported varient */
2127 if (strcmp(str1,"zzh") != 0) return False;
2128 if (strcmp(str2,"") != 0) return False;
2131 *rparam = REALLOC(*rparam,*rparam_len);
2132 SSVALS(*rparam,0,0); /* errorcode */
2133 SSVAL(*rparam,2,0); /* converter word */
2134 SSVAL(*rparam,4,0x7f); /* permission flags */
2139 /****************************************************************************
2140 api_WPrintJobEnumerate
2141 ****************************************************************************/
2142 static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
2143 int mdrcnt,int mprcnt,
2144 char **rdata,char **rparam,
2145 int *rdata_len,int *rparam_len)
2147 char *str1 = param+2;
2148 char *str2 = skip_string(str1,1);
2149 char *p = skip_string(str2,1);
2150 int uJobId = SVAL(p,0);
2156 struct pack_desc desc;
2157 print_queue_struct *queue=NULL;
2158 print_status_struct status;
2163 bzero(&desc,sizeof(desc));
2164 bzero(&status,sizeof(status));
2166 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2168 /* check it's a supported varient */
2169 if (strcmp(str1,"WWrLh") != 0) return False;
2170 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2172 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2173 job = uJobId & 0xFF;
2175 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2177 count = get_printqueue(snum,cnum,&queue,&status);
2178 for (i = 0; i < count; i++) {
2179 if ((queue[i].job % 0xFF) == job) break;
2181 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2183 desc.buflen = mdrcnt;
2185 if (init_package(&desc,1,0)) {
2187 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2188 *rdata_len = desc.usedlen;
2191 desc.errcode = NERR_JobNotFound;
2197 *rparam = REALLOC(*rparam,*rparam_len);
2198 SSVALS(*rparam,0,desc.errcode);
2200 SSVAL(*rparam,4,desc.neededlen);
2202 if (queue) free(queue);
2204 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2208 static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
2209 int mdrcnt,int mprcnt,
2210 char **rdata,char **rparam,
2211 int *rdata_len,int *rparam_len)
2213 char *str1 = param+2;
2214 char *str2 = skip_string(str1,1);
2215 char *p = skip_string(str2,1);
2221 struct pack_desc desc;
2222 print_queue_struct *queue=NULL;
2223 print_status_struct status;
2225 bzero(&desc,sizeof(desc));
2226 bzero(&status,sizeof(status));
2228 p = skip_string(p,1);
2232 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2234 /* check it's a supported varient */
2235 if (strcmp(str1,"zWrLeh") != 0) return False;
2236 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2237 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2239 snum = lp_servicenumber(name);
2240 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2241 int pnum = lp_servicenumber(PRINTERS_NAME);
2243 lp_add_printer(name,pnum);
2244 snum = lp_servicenumber(name);
2248 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2250 count = get_printqueue(snum,cnum,&queue,&status);
2251 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2253 desc.buflen = mdrcnt;
2255 if (init_package(&desc,count,0)) {
2257 for (i = 0; i < count; i++) {
2258 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2259 if (desc.errcode == NERR_Success) succnt = i+1;
2263 *rdata_len = desc.usedlen;
2266 *rparam = REALLOC(*rparam,*rparam_len);
2267 SSVALS(*rparam,0,desc.errcode);
2269 SSVAL(*rparam,4,succnt);
2270 SSVAL(*rparam,6,count);
2272 if (queue) free(queue);
2274 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2278 static int check_printdest_info(struct pack_desc* desc,
2279 int uLevel, char* id)
2281 desc->subformat = NULL;
2283 case 0: desc->format = "B9"; break;
2284 case 1: desc->format = "B9B21WWzW"; break;
2285 case 2: desc->format = "z"; break;
2286 case 3: desc->format = "zzzWWzzzWW"; break;
2287 default: return False;
2289 if (strcmp(desc->format,id) != 0) return False;
2293 static void fill_printdest_info(int cnum, int snum, int uLevel,
2294 struct pack_desc* desc)
2297 strcpy(buf,SERVICE(snum));
2300 PACKS(desc,"B9",buf); /* szName */
2302 PACKS(desc,"B21",""); /* szUserName */
2303 PACKI(desc,"W",0); /* uJobId */
2304 PACKI(desc,"W",0); /* fsStatus */
2305 PACKS(desc,"z",""); /* pszStatus */
2306 PACKI(desc,"W",0); /* time */
2309 if (uLevel == 2 || uLevel == 3) {
2310 PACKS(desc,"z",buf); /* pszPrinterName */
2312 PACKS(desc,"z",""); /* pszUserName */
2313 PACKS(desc,"z",""); /* pszLogAddr */
2314 PACKI(desc,"W",0); /* uJobId */
2315 PACKI(desc,"W",0); /* fsStatus */
2316 PACKS(desc,"z",""); /* pszStatus */
2317 PACKS(desc,"z",""); /* pszComment */
2318 PACKS(desc,"z","NULL"); /* pszDrivers */
2319 PACKI(desc,"W",0); /* time */
2320 PACKI(desc,"W",0); /* pad1 */
2325 static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
2326 int mdrcnt,int mprcnt,
2327 char **rdata,char **rparam,
2328 int *rdata_len,int *rparam_len)
2330 char *str1 = param+2;
2331 char *str2 = skip_string(str1,1);
2332 char *p = skip_string(str2,1);
2333 char* PrinterName = p;
2335 struct pack_desc desc;
2338 bzero(&desc,sizeof(desc));
2340 p = skip_string(p,1);
2344 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2346 /* check it's a supported varient */
2347 if (strcmp(str1,"zWrLh") != 0) return False;
2348 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2350 snum = lp_servicenumber(PrinterName);
2351 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2352 int pnum = lp_servicenumber(PRINTERS_NAME);
2354 lp_add_printer(PrinterName,pnum);
2355 snum = lp_servicenumber(PrinterName);
2361 desc.errcode = NERR_DestNotFound;
2365 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2367 desc.buflen = mdrcnt;
2368 if (init_package(&desc,1,0)) {
2369 fill_printdest_info(cnum,snum,uLevel,&desc);
2371 *rdata_len = desc.usedlen;
2375 *rparam = REALLOC(*rparam,*rparam_len);
2376 SSVALS(*rparam,0,desc.errcode);
2378 SSVAL(*rparam,4,desc.neededlen);
2380 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2384 static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
2385 int mdrcnt,int mprcnt,
2386 char **rdata,char **rparam,
2387 int *rdata_len,int *rparam_len)
2389 char *str1 = param+2;
2390 char *str2 = skip_string(str1,1);
2391 char *p = skip_string(str2,1);
2395 struct pack_desc desc;
2396 int services = lp_numservices();
2398 bzero(&desc,sizeof(desc));
2403 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2405 /* check it's a supported varient */
2406 if (strcmp(str1,"WrLeh") != 0) return False;
2407 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2410 for (i = 0; i < services; i++)
2411 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2414 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2416 desc.buflen = mdrcnt;
2417 if (init_package(&desc,queuecnt,0)) {
2420 for (i = 0; i < services; i++) {
2421 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2422 fill_printdest_info(cnum,i,uLevel,&desc);
2424 if (desc.errcode == NERR_Success) succnt = n;
2429 *rdata_len = desc.usedlen;
2432 *rparam = REALLOC(*rparam,*rparam_len);
2433 SSVALS(*rparam,0,desc.errcode);
2435 SSVAL(*rparam,4,succnt);
2436 SSVAL(*rparam,6,queuecnt);
2438 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2442 static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
2443 int mdrcnt,int mprcnt,
2444 char **rdata,char **rparam,
2445 int *rdata_len,int *rparam_len)
2447 char *str1 = param+2;
2448 char *str2 = skip_string(str1,1);
2449 char *p = skip_string(str2,1);
2452 struct pack_desc desc;
2454 bzero(&desc,sizeof(desc));
2459 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2461 /* check it's a supported varient */
2462 if (strcmp(str1,"WrLeh") != 0) return False;
2463 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2465 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2467 desc.buflen = mdrcnt;
2468 if (init_package(&desc,1,0)) {
2469 PACKS(&desc,"B41","NULL");
2472 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2474 *rdata_len = desc.usedlen;
2477 *rparam = REALLOC(*rparam,*rparam_len);
2478 SSVALS(*rparam,0,desc.errcode);
2480 SSVAL(*rparam,4,succnt);
2483 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2487 static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
2488 int mdrcnt,int mprcnt,
2489 char **rdata,char **rparam,
2490 int *rdata_len,int *rparam_len)
2492 char *str1 = param+2;
2493 char *str2 = skip_string(str1,1);
2494 char *p = skip_string(str2,1);
2497 struct pack_desc desc;
2499 bzero(&desc,sizeof(desc));
2504 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2506 /* check it's a supported varient */
2507 if (strcmp(str1,"WrLeh") != 0) return False;
2508 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2510 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2512 desc.buflen = mdrcnt;
2514 if (init_package(&desc,1,0)) {
2515 PACKS(&desc,"B13","lpd");
2518 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2520 *rdata_len = desc.usedlen;
2523 *rparam = REALLOC(*rparam,*rparam_len);
2524 SSVALS(*rparam,0,desc.errcode);
2526 SSVAL(*rparam,4,succnt);
2529 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2533 static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
2534 int mdrcnt,int mprcnt,
2535 char **rdata,char **rparam,
2536 int *rdata_len,int *rparam_len)
2538 char *str1 = param+2;
2539 char *str2 = skip_string(str1,1);
2540 char *p = skip_string(str2,1);
2543 struct pack_desc desc;
2545 bzero(&desc,sizeof(desc));
2550 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2552 /* check it's a supported varient */
2553 if (strcmp(str1,"WrLeh") != 0) return False;
2554 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2556 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2557 bzero(&desc,sizeof(desc));
2559 desc.buflen = mdrcnt;
2561 if (init_package(&desc,1,0)) {
2562 PACKS(&desc,"B13","lp0");
2565 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2567 *rdata_len = desc.usedlen;
2570 *rparam = REALLOC(*rparam,*rparam_len);
2571 SSVALS(*rparam,0,desc.errcode);
2573 SSVAL(*rparam,4,succnt);
2576 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2580 /****************************************************************************
2581 the buffer was too small
2582 ****************************************************************************/
2583 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
2584 int mdrcnt,int mprcnt,
2585 char **rdata,char **rparam,
2586 int *rdata_len,int *rparam_len)
2588 *rparam_len = MIN(*rparam_len,mprcnt);
2589 *rparam = REALLOC(*rparam,*rparam_len);
2593 SSVAL(*rparam,0,NERR_BufTooSmall);
2595 DEBUG(3,("Supplied buffer too small in API command\n"));
2601 /****************************************************************************
2602 the request is not supported
2603 ****************************************************************************/
2604 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
2605 int mdrcnt,int mprcnt,
2606 char **rdata,char **rparam,
2607 int *rdata_len,int *rparam_len)
2610 *rparam = REALLOC(*rparam,*rparam_len);
2614 SSVAL(*rparam,0,NERR_notsupported);
2615 SSVAL(*rparam,2,0); /* converter word */
2617 DEBUG(3,("Unsupported API command\n"));
2631 } api_commands[] = {
2632 {"RNetShareEnum", 0, api_RNetShareEnum,0},
2633 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
2634 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
2635 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
2636 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
2637 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
2638 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
2639 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
2640 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
2641 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
2642 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
2643 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
2644 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
2645 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
2646 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
2647 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
2648 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
2649 {"NetServerEnum", 104, api_RNetServerEnum,0},
2650 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
2651 {"SetUserPassword", 115, api_SetUserPassword,0},
2652 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
2653 {"PrintJobInfo", 147, api_PrintJobInfo,0},
2654 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
2655 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
2656 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
2657 {NULL, -1, api_Unsupported,0}};
2660 /****************************************************************************
2661 handle remote api calls
2662 ****************************************************************************/
2663 static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
2664 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2666 int api_command = SVAL(params,0);
2668 char *rparam = NULL;
2674 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2675 api_command,params+2,skip_string(params+2,1),
2676 tdscnt,tpscnt,mdrcnt,mprcnt));
2678 for (i=0;api_commands[i].name;i++)
2679 if (api_commands[i].id == api_command && api_commands[i].fn)
2681 DEBUG(3,("Doing %s\n",api_commands[i].name));
2685 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2686 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2688 reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2689 &rdata,&rparam,&rdata_len,&rparam_len);
2692 if (rdata_len > mdrcnt ||
2693 rparam_len > mprcnt)
2695 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2696 &rdata,&rparam,&rdata_len,&rparam_len);
2700 /* if we get False back then it's actually unsupported */
2702 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2703 &rdata,&rparam,&rdata_len,&rparam_len);
2707 /* now send the reply */
2708 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2718 /****************************************************************************
2719 handle named pipe commands
2720 ****************************************************************************/
2721 static int named_pipe(int cnum,int uid, char *outbuf,char *name,
2722 uint16 *setup,char *data,char *params,
2723 int suwcnt,int tdscnt,int tpscnt,
2724 int msrcnt,int mdrcnt,int mprcnt)
2727 if (strequal(name,"LANMAN"))
2728 return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2730 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2731 name,(int)setup[0],(int)setup[1]));
2737 /****************************************************************************
2739 ****************************************************************************/
2740 int reply_trans(char *inbuf,char *outbuf)
2744 char *data=NULL,*params=NULL;
2748 int cnum = SVAL(inbuf,smb_tid);
2749 int uid = SVAL(inbuf,smb_uid);
2751 int tpscnt = SVAL(inbuf,smb_vwv0);
2752 int tdscnt = SVAL(inbuf,smb_vwv1);
2753 int mprcnt = SVAL(inbuf,smb_vwv2);
2754 int mdrcnt = SVAL(inbuf,smb_vwv3);
2755 int msrcnt = CVAL(inbuf,smb_vwv4);
2756 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2757 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2758 int pscnt = SVAL(inbuf,smb_vwv9);
2759 int psoff = SVAL(inbuf,smb_vwv10);
2760 int dscnt = SVAL(inbuf,smb_vwv11);
2761 int dsoff = SVAL(inbuf,smb_vwv12);
2762 int suwcnt = CVAL(inbuf,smb_vwv13);
2764 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2768 data = (char *)malloc(tdscnt);
2769 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2773 params = (char *)malloc(tpscnt);
2774 memcpy(params,smb_base(inbuf)+psoff,pscnt);
2780 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
2781 for (i=0;i<suwcnt;i++)
2782 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
2786 if (pscnt < tpscnt || dscnt < tdscnt)
2788 /* We need to send an interim response then receive the rest
2789 of the parameter/data bytes */
2790 outsize = set_message(outbuf,0,0,True);
2792 send_smb(Client,outbuf);
2795 /* receive the rest of the trans packet */
2796 while (pscnt < tpscnt || dscnt < tdscnt)
2798 int pcnt,poff,dcnt,doff,pdisp,ddisp;
2800 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) ||
2801 CVAL(inbuf, smb_com) != SMBtrans)
2803 DEBUG(2,("Invalid secondary trans2 packet\n"));
2804 if (params) free(params);
2805 if (data) free(data);
2806 if (setup) free(setup);
2807 return(ERROR(ERRSRV,ERRerror));
2812 tpscnt = SVAL(inbuf,smb_vwv0);
2813 tdscnt = SVAL(inbuf,smb_vwv1);
2815 pcnt = SVAL(inbuf,smb_vwv2);
2816 poff = SVAL(inbuf,smb_vwv3);
2817 pdisp = SVAL(inbuf,smb_vwv4);
2819 dcnt = SVAL(inbuf,smb_vwv5);
2820 doff = SVAL(inbuf,smb_vwv6);
2821 ddisp = SVAL(inbuf,smb_vwv7);
2827 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
2829 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
2833 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
2836 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
2837 outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
2838 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
2841 if (data) free(data);
2842 if (params) free(params);
2843 if (setup) free(setup);
2845 if (close_on_completion)
2846 close_cnum(cnum,uid);
2852 return(ERROR(ERRSRV,ERRnosupport));