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 */
64 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
69 if (!src || !dst || !n || !(*dst)) return(0);
71 StrnCpy(buf,src,sizeof(buf)/2);
72 string_sub(buf,"%S",lp_servicename(snum));
73 standard_sub(cnum,buf);
81 static int CopyAndAdvance(char** dst, char* src, int* n)
84 if (!src || !dst || !n || !(*dst)) return(0);
92 static int StrlenExpanded(int cnum, int snum, char* s)
96 StrnCpy(buf,s,sizeof(buf)/2);
97 string_sub(buf,"%S",lp_servicename(snum));
98 standard_sub(cnum,buf);
99 return strlen(buf) + 1;
102 static char* Expand(int cnum, int snum, char* s)
105 if (!s) return(NULL);
106 StrnCpy(buf,s,sizeof(buf)/2);
107 string_sub(buf,"%S",lp_servicename(snum));
108 standard_sub(cnum,buf);
112 /*******************************************************************
113 check a API string for validity when we only need to check the prefix
114 ******************************************************************/
115 static BOOL prefix_ok(char *str,char *prefix)
117 return(strncmp(str,prefix,strlen(prefix)) == 0);
121 /****************************************************************************
123 ****************************************************************************/
124 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
125 int ldata,int lparam,int lsetup)
128 int this_ldata,this_lparam;
129 int tot_data=0,tot_param=0;
132 this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */
133 this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam));
135 align = (this_lparam%4);
137 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
139 memcpy(smb_buf(outbuf),param,this_lparam);
141 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
143 SSVAL(outbuf,smb_vwv0,lparam);
144 SSVAL(outbuf,smb_vwv1,ldata);
145 SSVAL(outbuf,smb_vwv3,this_lparam);
146 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
147 SSVAL(outbuf,smb_vwv5,0);
148 SSVAL(outbuf,smb_vwv6,this_ldata);
149 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
150 SSVAL(outbuf,smb_vwv8,0);
151 SSVAL(outbuf,smb_vwv9,lsetup);
152 for (i=0;i<lsetup;i++)
153 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
156 send_smb(Client,outbuf);
158 tot_data = this_ldata;
159 tot_param = this_lparam;
161 while (tot_data < ldata || tot_param < lparam)
163 this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
164 this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
166 align = (this_lparam%4);
168 set_message(outbuf,10,this_ldata+this_lparam+align,False);
170 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
172 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
174 SSVAL(outbuf,smb_vwv3,this_lparam);
175 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
176 SSVAL(outbuf,smb_vwv5,tot_param);
177 SSVAL(outbuf,smb_vwv6,this_ldata);
178 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
179 SSVAL(outbuf,smb_vwv8,tot_data);
180 SSVAL(outbuf,smb_vwv9,0);
183 send_smb(Client,outbuf);
185 tot_data += this_ldata;
186 tot_param += this_lparam;
192 /****************************************************************************
194 ****************************************************************************/
197 char* format; /* formatstring for structure */
198 char* subformat; /* subformat for structure */
199 char* base; /* baseaddress of buffer */
200 int buflen; /* remaining size for fixed part; on init: length of base */
201 int subcount; /* count of substructures */
202 char* structbuf; /* pointer into buffer for remaining fixed part */
203 int stringlen; /* remaining size for variable part */
204 char* stringbuf; /* pointer into buffer for remaining variable part */
205 int neededlen; /* total needed size */
206 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
207 char* curpos; /* current position; pointer into format or subformat */
211 static int get_counter(char** p)
214 if (!p || !(*p)) return(1);
215 if (!isdigit(**p)) return 1;
219 n = 10 * n + (i - '0');
226 static int getlen(char* p)
232 case 'W': /* word (2 byte) */
235 case 'N': /* count of substructures (word) at end */
238 case 'D': /* double word (4 byte) */
239 case 'z': /* offset to zero terminated string (4 byte) */
240 case 'l': /* offset to user data (4 byte) */
243 case 'b': /* offset to data (with counter) (4 byte) */
247 case 'B': /* byte (with optional counter) */
248 n += get_counter(&p);
255 static BOOL init_package(struct pack_desc* p, int count, int subcount)
260 if (!p->format || !p->base) return(False);
262 i = count * getlen(p->format);
263 if (p->subformat) i += subcount * getlen(p->subformat);
264 p->structbuf = p->base;
268 p->curpos = p->format;
271 p->errcode = NERR_BufTooSmall;
274 p->errcode = NERR_Success;
277 p->stringbuf = p->base + i;
279 return(p->errcode == NERR_Success);
283 static int package(struct pack_desc* p, ...)
286 static int package(va_alist)
292 int needed=0, stringneeded;
294 int is_string=0, stringused;
301 p = va_arg(args,struct pack_desc *);
306 p->curpos = p->format;
308 p->curpos = p->subformat;
313 str = va_arg(args,char*);
314 if (strncmp(str,p->curpos,strlen(str)) != 0) {
315 DEBUG(2,("type error in package: %s instead of %*s\n",str,
316 strlen(str),p->curpos));
326 if (!p->curpos) return(0);
328 switch( *p->curpos++ ) {
329 case 'W': /* word (2 byte) */
331 temp = va_arg(args,int);
332 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
334 case 'N': /* count of substructures (word) at end */
336 p->subcount = va_arg(args,int);
337 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
339 case 'D': /* double word (4 byte) */
341 temp = va_arg(args,int);
342 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
344 case 'B': /* byte (with optional counter) */
345 needed = get_counter(&p->curpos);
347 char *s = va_arg(args,char*);
348 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
351 case 'z': /* offset to zero terminated string (4 byte) */
352 str = va_arg(args,char*);
353 stringneeded = (str ? strlen(str)+1 : 0);
356 case 'l': /* offset to user data (4 byte) */
357 str = va_arg(args,char*);
358 stringneeded = va_arg(args,int);
361 case 'b': /* offset to data (with counter) (4 byte) */
362 str = va_arg(args,char*);
363 stringneeded = get_counter(&p->curpos);
368 if (stringneeded >= 0) {
370 if (p->buflen >= needed) {
371 stringused = stringneeded;
372 if (stringused > p->stringlen) {
373 stringused = (is_string ? p->stringlen : 0);
374 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
377 SIVAL(p->structbuf,0,0);
379 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
380 memcpy(p->stringbuf,str?str:"",stringused);
381 if (is_string) p->stringbuf[stringused-1] = '\0';
382 p->stringbuf += stringused;
383 p->stringlen -= stringused;
384 p->usedlen += stringused;
387 p->neededlen += stringneeded;
389 p->neededlen += needed;
390 if (p->buflen >= needed) {
391 p->structbuf += needed;
393 p->usedlen += needed;
396 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
402 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
403 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
405 #define PACK(desc,t,v) package(desc,v)
406 #define PACKl(desc,t,v,l) package(desc,v,l)
409 static void PACKI(struct pack_desc* desc,char *t,int v)
414 static void PACKS(struct pack_desc* desc,char *t,char *v)
419 static void PackDriverData(struct pack_desc* desc)
421 char drivdata[4+4+32];
422 SIVAL(drivdata,0,sizeof drivdata); /* cb */
423 SIVAL(drivdata,4,1000); /* lVersion */
424 memset(drivdata+8,0,32); /* szDeviceName */
425 strcpy(drivdata+8,"NULL");
426 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
429 static int check_printq_info(struct pack_desc* desc,
430 int uLevel, const char* id1, const char* id2)
432 desc->subformat = NULL;
435 desc->format = "B13";
438 desc->format = "B13BWWWzzzzzWW";
441 desc->format = "B13BWWWzzzzzWN";
442 desc->subformat = "WB21BB16B10zWWzDDz";
445 desc->format = "zWWWWzzzzWWzzl";
448 desc->format = "zWWWWzzzzWNzzl";
449 desc->subformat = "WWzWWDDzz";
454 default: return False;
456 if (strcmp(desc->format,id1) != 0) return False;
457 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
461 static void fill_printjob_info(int cnum, int snum, int uLevel,
462 struct pack_desc* desc,
463 print_queue_struct* queue, int n)
465 time_t t = queue->time;
467 /* the client expects localtime */
470 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
472 PACKS(desc,"B21",queue->user); /* szUserName */
473 PACKS(desc,"B",""); /* pad */
474 PACKS(desc,"B16",""); /* szNotifyName */
475 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
476 PACKS(desc,"z",""); /* pszParms */
477 PACKI(desc,"W",n+1); /* uPosition */
478 PACKI(desc,"W",queue->status); /* fsStatus */
479 PACKS(desc,"z",""); /* pszStatus */
480 PACKI(desc,"D",t); /* ulSubmitted */
481 PACKI(desc,"D",queue->size); /* ulSize */
482 PACKS(desc,"z",queue->file); /* pszComment */
484 if (uLevel == 2 || uLevel == 3) {
485 PACKI(desc,"W",queue->priority); /* uPriority */
486 PACKS(desc,"z",queue->user); /* pszUserName */
487 PACKI(desc,"W",n+1); /* uPosition */
488 PACKI(desc,"W",queue->status); /* fsStatus */
489 PACKI(desc,"D",t); /* ulSubmitted */
490 PACKI(desc,"D",queue->size); /* ulSize */
491 PACKS(desc,"z","Samba"); /* pszComment */
492 PACKS(desc,"z",queue->file); /* pszDocument */
494 PACKS(desc,"z",""); /* pszNotifyName */
495 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
496 PACKS(desc,"z",""); /* pszParms */
497 PACKS(desc,"z",""); /* pszStatus */
498 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
499 PACKS(desc,"z","lpd"); /* pszQProcName */
500 PACKS(desc,"z",""); /* pszQProcParms */
501 PACKS(desc,"z","NULL"); /* pszDriverName */
502 PackDriverData(desc); /* pDriverData */
503 PACKS(desc,"z",""); /* pszPrinterName */
508 static void fill_printq_info(int cnum, int snum, int uLevel,
509 struct pack_desc* desc,
510 int count, print_queue_struct* queue,
511 print_status_struct* status)
514 PACKS(desc,"B13",SERVICE(snum));
516 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
518 if (uLevel == 1 || uLevel == 2) {
519 PACKS(desc,"B",""); /* alignment */
520 PACKI(desc,"W",5); /* priority */
521 PACKI(desc,"W",0); /* start time */
522 PACKI(desc,"W",0); /* until time */
523 PACKS(desc,"z",""); /* pSepFile */
524 PACKS(desc,"z","lpd"); /* pPrProc */
525 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
526 PACKS(desc,"z",""); /* pParms */
528 PACKS(desc,"z","UNKNOWN PRINTER");
529 PACKI(desc,"W",LPSTAT_ERROR);
531 else if (!status || !status->message[0]) {
532 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
533 PACKI(desc,"W",LPSTAT_OK); /* status */
535 PACKS(desc,"z",status->message);
536 PACKI(desc,"W",status->status); /* status */
538 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
540 if (uLevel == 3 || uLevel == 4) {
541 PACKI(desc,"W",5); /* uPriority */
542 PACKI(desc,"W",0); /* uStarttime */
543 PACKI(desc,"W",0); /* uUntiltime */
544 PACKI(desc,"W",5); /* pad1 */
545 PACKS(desc,"z",""); /* pszSepFile */
546 PACKS(desc,"z","lpd"); /* pszPrProc */
547 PACKS(desc,"z",""); /* pszParms */
548 if (!status || !status->message[0]) {
549 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
550 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
552 PACKS(desc,"z",status->message); /* pszComment */
553 PACKI(desc,"W",status->status); /* fsStatus */
555 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
556 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
557 PACKS(desc,"z","NULL"); /* pszDriverName */
558 PackDriverData(desc); /* pDriverData */
560 if (uLevel == 2 || uLevel == 4) {
562 for (i=0;i<count;i++)
563 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
566 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
569 static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
570 int mdrcnt,int mprcnt,
571 char **rdata,char **rparam,
572 int *rdata_len,int *rparam_len)
574 char *str1 = param+2;
575 char *str2 = skip_string(str1,1);
576 char *p = skip_string(str2,1);
582 struct pack_desc desc;
583 print_queue_struct *queue=NULL;
584 print_status_struct status;
586 bzero(&status,sizeof(status));
587 bzero(&desc,sizeof(desc));
589 p = skip_string(p,1);
594 if ((p = strchr(QueueName,'%'))) *p = 0;
596 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
598 /* check it's a supported varient */
599 if (!prefix_ok(str1,"zWrLh")) return False;
600 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
602 snum = lp_servicenumber(QueueName);
603 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
604 int pnum = lp_servicenumber(PRINTERS_NAME);
606 lp_add_printer(QueueName,pnum);
607 snum = lp_servicenumber(QueueName);
611 if (snum < 0 || !VALID_SNUM(snum)) return(False);
613 count = get_printqueue(snum,cnum,&queue,&status);
614 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
616 desc.buflen = mdrcnt;
617 if (init_package(&desc,1,count)) {
618 desc.subcount = count;
619 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
622 *rdata_len = desc.usedlen;
625 *rparam = REALLOC(*rparam,*rparam_len);
626 SSVALS(*rparam,0,desc.errcode);
628 SSVAL(*rparam,4,desc.neededlen);
630 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
632 if (queue) free(queue);
638 /****************************************************************************
639 view list of all print jobs on all queues
640 ****************************************************************************/
641 static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
642 int mdrcnt, int mprcnt,
643 char **rdata, char** rparam,
644 int *rdata_len, int *rparam_len)
646 char *param_format = param+2;
647 char *output_format1 = skip_string(param_format,1);
648 char *p = skip_string(output_format1,1);
649 int uLevel = SVAL(p,0);
650 char *output_format2 = p + 4;
651 int services = lp_numservices();
653 struct pack_desc desc;
654 print_queue_struct **queue = NULL;
655 print_status_struct *status = NULL;
656 int* subcntarr = NULL;
657 int queuecnt, subcnt=0, succnt=0;
659 bzero(&desc,sizeof(desc));
661 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
663 if (prefix_ok(param_format,"WrLeh")) return False;
664 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
667 for (i = 0; i < services; i++)
668 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
671 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
672 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
673 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
674 memset(status,0,queuecnt*sizeof(print_status_struct));
675 subcntarr = (int*)malloc(queuecnt*sizeof(int));
678 for (i = 0; i < services; i++)
679 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
680 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
681 subcnt += subcntarr[n];
685 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
687 desc.buflen = mdrcnt;
689 if (init_package(&desc,queuecnt,subcnt)) {
692 for (i = 0; i < services; i++)
693 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
694 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
696 if (desc.errcode == NERR_Success) succnt = n;
700 if (subcntarr) free(subcntarr);
702 *rdata_len = desc.usedlen;
704 *rparam = REALLOC(*rparam,*rparam_len);
705 SSVALS(*rparam,0,desc.errcode);
707 SSVAL(*rparam,4,succnt);
708 SSVAL(*rparam,6,queuecnt);
710 for (i = 0; i < queuecnt; i++) {
711 if (queue && queue[i]) free(queue[i]);
714 if (queue) free(queue);
715 if (status) free(status);
720 /****************************************************************************
721 get info level for a server list query
722 ****************************************************************************/
723 static BOOL check_server_info(int uLevel, char* id)
727 if (strcmp(id,"B16") != 0) return False;
730 if (strcmp(id,"B16BBDz") != 0) return False;
738 /* used for server information: client, nameserv and ipc */
739 struct srv_info_struct
744 fstring domain; /* used ONLY in ipc.c NOT namework.c */
745 BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
748 /*******************************************************************
749 filter out unwanted server info
750 ******************************************************************/
751 static BOOL filter_server_info(struct srv_info_struct *server,
753 char *domain, uint32 request)
757 if (strequal(lp_workgroup(), server->domain)) {
762 DEBUG(4,("primary domain:reject %8x %s %s\n",request,server->name,server->domain));
765 else if ((request & SV_TYPE_DOMAIN_ENUM) &&
766 (server->type & SV_TYPE_DOMAIN_ENUM))
768 DEBUG(4,("rej:DOM %8x: %s %s\n",server->type,server->name,server->domain));
776 if (strequal(domain, server->domain))
779 if (request == SV_TYPE_LOCAL_LIST_ONLY &&
780 !(server->type & SV_TYPE_LOCAL_LIST_ONLY))
782 DEBUG(4,("rej:LOC %8x: ok %s %s\n",request,server->name,server->domain));
786 if ((request == (SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM)) &&
787 !(server->type&SV_TYPE_DOMAIN_ENUM))
789 DEBUG(4,("rej:LOCDOM %8x: ok %s %s\n",request,server->name,server->domain));
797 DEBUG(4,("domain:%s %s %s\n",domain,server->name,server->domain));
804 /*******************************************************************
805 get server info lists from the files saved by nmbd. Return the
807 ******************************************************************/
808 static int get_server_info(uint32 servertype,
809 struct srv_info_struct **servers, BOOL domains,
818 strcpy(fname,lp_lockdir());
819 trim_string(fname,NULL,"/");
821 strcat(fname,SERVER_LIST);
823 f = fopen(fname,"r");
826 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
830 /* request for everything is code for request all servers */
831 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
833 DEBUG(4,("Servertype search: %8x domains:%s\n",servertype,BOOLSTR(domains)));
838 struct srv_info_struct *s;
843 fgets(line,sizeof(line)-1,f);
844 if (!*line) continue;
846 if (count == alloced) {
848 (*servers) = (struct srv_info_struct *)
849 Realloc(*servers,sizeof(**servers)*alloced);
850 if (!(*servers)) return(0);
851 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
853 s = &(*servers)[count];
855 if (!next_token(&ptr,s->name , NULL)) continue;
856 if (!next_token(&ptr,stype , NULL)) continue;
857 if (!next_token(&ptr,s->comment, NULL)) continue;
858 if (!next_token(&ptr,s->domain , NULL)) {
859 /* this allows us to cope with an old nmbd */
860 strcpy(s->domain,my_workgroup());
863 if (sscanf(stype,"%X",&s->type) != 1) {
864 DEBUG(4,("r:host file "));
868 /* doesn't match up: don't want it */
869 if (!(servertype & s->type)) {
870 DEBUG(4,("r:serv type "));
874 if ((servertype == ~SV_TYPE_DOMAIN_ENUM) &&
875 (s->type & SV_TYPE_DOMAIN_ENUM))
877 DEBUG(4,("s:all x dom "));
881 if (domains && !(domain && *domain && strequal(domain, s->domain)))
883 if (!(s->type & SV_TYPE_DOMAIN_ENUM))
885 DEBUG(4,("r:dom enum "));
892 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
893 s->name, s->type, s->comment, s->domain));
895 s->type |= SV_TYPE_LOCAL_LIST_ONLY;
896 s->server_added = True;
901 DEBUG(4,("%20s %8x %25s %15s\n",
902 s->name, s->type, s->comment, s->domain));
911 /*******************************************************************
912 fill in a server info structure
913 ******************************************************************/
914 static int fill_srv_info(struct srv_info_struct *service,
915 int uLevel, char **buf, int *buflen,
916 char **stringbuf, int *stringspace, char *baseaddr)
925 case 0: struct_len = 16; break;
926 case 1: struct_len = 26; break;
936 len = strlen(service->comment)+1;
940 if (buflen) *buflen = struct_len;
941 if (stringspace) *stringspace = len;
942 return struct_len + len;
947 if (*buflen < struct_len) return -1;
956 l2 = *buflen - struct_len;
958 if (!baseaddr) baseaddr = p;
963 StrnCpy(p,service->name,15);
967 StrnCpy(p,service->name,15);
968 SIVAL(p,18,service->type);
969 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
970 len += CopyAndAdvance(&p2,service->comment,&l2);
976 *buf = p + struct_len;
977 *buflen -= struct_len;
990 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
992 return(strcmp(s1->name,s2->name));
995 /****************************************************************************
996 view list of servers available (or possibly domains). The info is
997 extracted from lists saved by nmbd on the local host
998 ****************************************************************************/
999 static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
1000 int mdrcnt, int mprcnt, char **rdata,
1001 char **rparam, int *rdata_len, int *rparam_len)
1003 char *str1 = param+2;
1004 char *str2 = skip_string(str1,1);
1005 char *p = skip_string(str2,1);
1006 int uLevel = SVAL(p,0);
1007 int buf_len = SVAL(p,2);
1008 uint32 servertype = IVAL(p,4);
1010 int data_len, fixed_len, string_len;
1012 struct srv_info_struct *servers=NULL;
1013 int counted=0,total=0;
1017 BOOL domain_request;
1018 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
1020 /*if (servertype == SV_TYPE_ALL) servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);*/
1021 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
1023 domain_request = servertype & SV_TYPE_DOMAIN_ENUM;
1028 if (!prefix_ok(str1,"WrLehD")) return False;
1029 if (!check_server_info(uLevel,str2)) return False;
1031 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1032 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1033 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1035 if (strcmp(str1, "WrLehDO") == 0)
1039 else if (strcmp(str1, "WrLehDz") == 0)
1042 StrnCpy(domain, p, sizeof(fstring)-1);
1045 if (lp_browse_list())
1047 total = get_server_info(servertype,&servers,domains,domain);
1050 data_len = fixed_len = string_len = 0;
1052 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1055 char *lastname=NULL;
1057 for (i=0;i<total;i++)
1059 struct srv_info_struct *s = &servers[i];
1060 if (filter_server_info(s,domains,domain,
1061 local_request|domain_request))
1063 if (lastname && strequal(lastname,s->name)) continue;
1065 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1066 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1067 s->name, s->type, s->comment, s->domain));
1069 if (data_len <= buf_len)
1073 string_len += s_len;
1079 *rdata_len = fixed_len + string_len;
1080 *rdata = REALLOC(*rdata,*rdata_len);
1081 bzero(*rdata,*rdata_len);
1083 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1089 char *lastname=NULL;
1090 int count2 = counted;
1091 for (i = 0; i < total && count2;i++)
1093 struct srv_info_struct *s = &servers[i];
1094 if (filter_server_info(s,domains,domain,local_request|domain_request))
1096 if (lastname && strequal(lastname,s->name)) continue;
1098 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1099 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1100 s->name, s->type, s->comment, s->domain));
1107 *rparam = REALLOC(*rparam,*rparam_len);
1108 SSVAL(*rparam,0,NERR_Success);
1110 SSVAL(*rparam,4,counted);
1111 SSVAL(*rparam,6,total);
1113 if (servers) free(servers);
1115 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1116 domain,uLevel,counted,total));
1122 /****************************************************************************
1123 get info about a share
1124 ****************************************************************************/
1125 static BOOL check_share_info(int uLevel, char* id)
1129 if (strcmp(id,"B13") != 0) return False;
1132 if (strcmp(id,"B13BWz") != 0) return False;
1135 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1138 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1140 default: return False;
1145 static int fill_share_info(int cnum, int snum, int uLevel,
1146 char** buf, int* buflen,
1147 char** stringbuf, int* stringspace, char* baseaddr)
1156 case 0: struct_len = 13; break;
1157 case 1: struct_len = 20; break;
1158 case 2: struct_len = 40; break;
1159 case 91: struct_len = 68; break;
1167 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1168 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1169 if (buflen) *buflen = struct_len;
1170 if (stringspace) *stringspace = len;
1171 return struct_len + len;
1176 if ((*buflen) < struct_len) return -1;
1184 p2 = p + struct_len;
1185 l2 = (*buflen) - struct_len;
1187 if (!baseaddr) baseaddr = p;
1189 StrnCpy(p,lp_servicename(snum),13);
1195 type = STYPE_DISKTREE;
1196 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1197 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1198 SSVAL(p,14,type); /* device type */
1199 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1200 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1205 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1206 SSVALS(p,22,-1); /* max uses */
1207 SSVAL(p,24,1); /* current uses */
1208 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1209 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1210 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1215 memset(p+40,0,SHPWLEN+2);
1227 (*buf) = p + struct_len;
1228 (*buflen) -= struct_len;
1230 (*stringspace) = l2;
1240 static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
1241 int mdrcnt,int mprcnt,
1242 char **rdata,char **rparam,
1243 int *rdata_len,int *rparam_len)
1245 char *str1 = param+2;
1246 char *str2 = skip_string(str1,1);
1247 char *netname = skip_string(str2,1);
1248 char *p = skip_string(netname,1);
1249 int uLevel = SVAL(p,0);
1250 int snum = find_service(netname);
1252 if (snum < 0) return False;
1254 /* check it's a supported varient */
1255 if (!prefix_ok(str1,"zWrLh")) return False;
1256 if (!check_share_info(uLevel,str2)) return False;
1258 *rdata = REALLOC(*rdata,mdrcnt);
1260 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1261 if (*rdata_len < 0) return False;
1264 *rparam = REALLOC(*rparam,*rparam_len);
1265 SSVAL(*rparam,0,NERR_Success);
1266 SSVAL(*rparam,2,0); /* converter word */
1267 SSVAL(*rparam,4,*rdata_len);
1272 /****************************************************************************
1273 view list of shares available
1274 ****************************************************************************/
1275 static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
1276 int mdrcnt,int mprcnt,
1277 char **rdata,char **rparam,
1278 int *rdata_len,int *rparam_len)
1280 char *str1 = param+2;
1281 char *str2 = skip_string(str1,1);
1282 char *p = skip_string(str2,1);
1283 int uLevel = SVAL(p,0);
1284 int buf_len = SVAL(p,2);
1286 int count=lp_numservices();
1287 int total=0,counted=0;
1289 int data_len, fixed_len, string_len;
1292 if (!prefix_ok(str1,"WrLeh")) return False;
1293 if (!check_share_info(uLevel,str2)) return False;
1295 data_len = fixed_len = string_len = 0;
1296 for (i=0;i<count;i++)
1297 if (lp_browseable(i) && lp_snum_ok(i))
1300 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1301 if (data_len <= buf_len)
1305 string_len += s_len;
1308 *rdata_len = fixed_len + string_len;
1309 *rdata = REALLOC(*rdata,*rdata_len);
1310 memset(*rdata,0,*rdata_len);
1312 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1316 for (i = 0; i < count;i++)
1317 if (lp_browseable(i) && lp_snum_ok(i))
1318 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1322 *rparam = REALLOC(*rparam,*rparam_len);
1323 SSVAL(*rparam,0,NERR_Success);
1325 SSVAL(*rparam,4,counted);
1326 SSVAL(*rparam,6,total);
1328 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1329 counted,total,uLevel,
1330 buf_len,*rdata_len,mdrcnt));
1336 /****************************************************************************
1337 get the time of day info
1338 ****************************************************************************/
1339 static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
1340 int mdrcnt,int mprcnt,
1341 char **rdata,char **rparam,
1342 int *rdata_len,int *rparam_len)
1346 *rparam = REALLOC(*rparam,*rparam_len);
1349 *rdata = REALLOC(*rdata,*rdata_len);
1351 SSVAL(*rparam,0,NERR_Success);
1352 SSVAL(*rparam,2,0); /* converter word */
1358 time_t unixdate = time(NULL);
1360 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1361 by NT in a "net time" operation,
1362 it seems to ignore the one below */
1364 /* the client expects to get localtime, not GMT, in this bit
1365 (I think, this needs testing) */
1366 t = LocalTime(&unixdate);
1368 SIVAL(p,4,0); /* msecs ? */
1369 CVAL(p,8) = t->tm_hour;
1370 CVAL(p,9) = t->tm_min;
1371 CVAL(p,10) = t->tm_sec;
1372 CVAL(p,11) = 0; /* hundredths of seconds */
1373 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1374 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1375 CVAL(p,16) = t->tm_mday;
1376 CVAL(p,17) = t->tm_mon + 1;
1377 SSVAL(p,18,1900+t->tm_year);
1378 CVAL(p,20) = t->tm_wday;
1385 /****************************************************************************
1386 set the user password
1387 ****************************************************************************/
1388 static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
1389 int mdrcnt,int mprcnt,
1390 char **rdata,char **rparam,
1391 int *rdata_len,int *rparam_len)
1393 char *p = skip_string(param+2,2);
1395 fstring pass1,pass2;
1399 p = skip_string(p,1);
1401 StrnCpy(pass1,p,16);
1402 StrnCpy(pass2,p+16,16);
1405 *rparam = REALLOC(*rparam,*rparam_len);
1409 SSVAL(*rparam,0,NERR_Success);
1410 SSVAL(*rparam,2,0); /* converter word */
1412 DEBUG(3,("Set password for <%s>\n",user));
1414 if (!password_ok(user,pass1,strlen(pass1),NULL,False) ||
1415 !chgpasswd(user,pass1,pass2))
1416 SSVAL(*rparam,0,NERR_badpass);
1418 bzero(pass1,sizeof(fstring));
1419 bzero(pass2,sizeof(fstring));
1424 /****************************************************************************
1427 ****************************************************************************/
1428 static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
1429 int mdrcnt,int mprcnt,
1430 char **rdata,char **rparam,
1431 int *rdata_len,int *rparam_len)
1433 int function = SVAL(param,0);
1434 char *str1 = param+2;
1435 char *str2 = skip_string(str1,1);
1436 char *p = skip_string(str2,1);
1437 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1438 by the print queue api */
1439 int snum = (SVAL(p,0)>>8);
1443 /* check it's a supported varient */
1444 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1448 *rparam = REALLOC(*rparam,*rparam_len);
1452 SSVAL(*rparam,0,NERR_Success);
1454 if (snum >= 0 && VALID_SNUM(snum))
1456 print_queue_struct *queue=NULL;
1458 count = get_printqueue(snum,cnum,&queue,NULL);
1460 for (i=0;i<count;i++)
1461 if ((queue[i].job%0xFF) == jobid)
1464 case 81: /* delete */
1465 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1466 del_printqueue(cnum,snum,queue[i].job);
1468 case 82: /* pause */
1469 case 83: /* resume */
1470 DEBUG(3,("%s queue entry %d\n",
1471 (function==82?"pausing":"resuming"),queue[i].job));
1472 status_printjob(cnum,snum,queue[i].job,
1473 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1480 SSVAL(*rparam,0,NERR_JobNotFound);
1482 if (queue) free(queue);
1485 SSVAL(*rparam,2,0); /* converter word */
1490 static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data,
1491 int mdrcnt,int mprcnt,
1492 char **rdata,char **rparam,
1493 int *rdata_len,int *rparam_len)
1495 char *str1 = param+2;
1496 char *str2 = skip_string(str1,1);
1497 char *QueueName = skip_string(str2,1);
1500 /* check it's a supported varient */
1501 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1505 *rparam = REALLOC(*rparam,*rparam_len);
1509 SSVAL(*rparam,0,NERR_Success);
1510 SSVAL(*rparam,2,0); /* converter word */
1512 snum = lp_servicenumber(QueueName);
1513 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1514 int pnum = lp_servicenumber(PRINTERS_NAME);
1516 lp_add_printer(QueueName,pnum);
1517 snum = lp_servicenumber(QueueName);
1521 if (snum >= 0 && VALID_SNUM(snum)) {
1522 print_queue_struct *queue=NULL;
1526 count = get_printqueue(snum,cnum,&queue,NULL);
1527 for (i = 0; i < count; i++)
1528 del_printqueue(cnum,snum,queue[i].job);
1530 if (queue) free(queue);
1533 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1539 /****************************************************************************
1540 set the property of a print job (undocumented?)
1541 ? function = 0xb -> set name of print job
1542 ? function = 0x6 -> move print job up/down
1543 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1544 or <WWsTP> <WB21BB16B10zWWzDDz>
1545 ****************************************************************************/
1546 static int check_printjob_info(struct pack_desc* desc,
1547 int uLevel, char* id)
1549 desc->subformat = NULL;
1551 case 0: desc->format = "W"; break;
1552 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1553 case 2: desc->format = "WWzWWDDzz"; break;
1554 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1555 default: return False;
1557 if (strcmp(desc->format,id) != 0) return False;
1561 static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
1562 int mdrcnt,int mprcnt,
1563 char **rdata,char **rparam,
1564 int *rdata_len,int *rparam_len)
1566 struct pack_desc desc;
1567 char *str1 = param+2;
1568 char *str2 = skip_string(str1,1);
1569 char *p = skip_string(str2,1);
1570 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1571 by the print queue api */
1572 int snum = (SVAL(p,0)>>8);
1573 int uLevel = SVAL(p,2);
1574 int function = SVAL(p,4); /* what is this ?? */
1579 *rparam = REALLOC(*rparam,*rparam_len);
1583 /* check it's a supported varient */
1584 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1588 case 0x6: /* change job place in the queue, data gives the new place */
1589 if (snum >= 0 && VALID_SNUM(snum))
1591 print_queue_struct *queue=NULL;
1595 count = get_printqueue(snum,cnum,&queue,NULL);
1596 for (i=0;i<count;i++) /* find job */
1597 if ((queue[i].job%0xFF) == jobid) break;
1600 desc.errcode=NERR_JobNotFound;
1601 if (queue) free(queue);
1604 desc.errcode=NERR_Success;
1608 int place= SVAL(data,0);
1609 /* we currently have no way of doing this. Can any unix do it? */
1610 if (i < place) /* move down */;
1611 else if (i > place ) /* move up */;
1614 desc.errcode=NERR_notsupported; /* not yet supported */
1615 if (queue) free(queue);
1618 else desc.errcode=NERR_JobNotFound;
1620 case 0xb: /* change print job name, data gives the name */
1621 /* jobid, snum should be zero */
1628 if (issafe(*s)) name[l++] = *s;
1633 DEBUG(3,("Setting print name to %s\n",name));
1635 for (i=0;i<MAX_OPEN_FILES;i++)
1636 if (Files[i].open && Files[i].print_file)
1642 if (!become_user(Files[i].cnum,uid) ||
1643 !become_service(Files[i].cnum,True))
1646 if (sys_rename(Files[i].name,name) == 0)
1647 string_set(&Files[i].name,name);
1651 desc.errcode=NERR_Success;
1654 default: /* not implemented */
1658 SSVALS(*rparam,0,desc.errcode);
1659 SSVAL(*rparam,2,0); /* converter word */
1665 /****************************************************************************
1666 get info about the server
1667 ****************************************************************************/
1668 static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
1669 int mdrcnt,int mprcnt,
1670 char **rdata,char **rparam,
1671 int *rdata_len,int *rparam_len)
1673 char *str1 = param+2;
1674 char *str2 = skip_string(str1,1);
1675 char *p = skip_string(str2,1);
1676 int uLevel = SVAL(p,0);
1680 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1682 /* check it's a supported varient */
1683 if (!prefix_ok(str1,"WrLh")) return False;
1686 if (strcmp(str2,"B16") != 0) return False;
1690 if (strcmp(str2,"B16BBDz") != 0) return False;
1694 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1699 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1704 if (strcmp(str2,"DN") != 0) return False;
1708 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1711 default: return False;
1714 *rdata_len = mdrcnt;
1715 *rdata = REALLOC(*rdata,*rdata_len);
1718 p2 = p + struct_len;
1720 StrnCpy(p,local_machine,16);
1726 struct srv_info_struct *servers=NULL;
1729 uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION|
1730 SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE;
1732 strcpy(comment,lp_serverstring());
1734 if ((count=get_server_info(SV_TYPE_ALL,&servers,False,NULL))>0) {
1735 for (i=0;i<count;i++)
1736 if (strequal(servers[i].name,local_machine)) {
1737 servertype = servers[i].type;
1738 strcpy(comment,servers[i].comment);
1741 if (servers) free(servers);
1743 SCVAL(p,0,2); /* version_major */
1744 SCVAL(p,1,0); /* version_minor */
1745 SIVAL(p,2,servertype);
1746 if (mdrcnt == struct_len) {
1749 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1750 standard_sub(cnum,comment);
1751 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1752 p2 = skip_string(p2,1);
1757 return False; /* not yet implemented */
1760 *rdata_len = PTR_DIFF(p2,*rdata);
1763 *rparam = REALLOC(*rparam,*rparam_len);
1764 SSVAL(*rparam,0,NERR_Success);
1765 SSVAL(*rparam,2,0); /* converter word */
1766 SSVAL(*rparam,4,*rdata_len);
1772 /****************************************************************************
1773 get info about the server
1774 ****************************************************************************/
1775 static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
1776 int mdrcnt,int mprcnt,
1777 char **rdata,char **rparam,
1778 int *rdata_len,int *rparam_len)
1780 char *str1 = param+2;
1781 char *str2 = skip_string(str1,1);
1782 char *p = skip_string(str2,1);
1784 extern pstring sesssetup_user;
1785 int level = SVAL(p,0);
1787 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1790 *rparam = REALLOC(*rparam,*rparam_len);
1792 /* check it's a supported varient */
1793 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1796 *rdata_len = mdrcnt + 1024;
1797 *rdata = REALLOC(*rdata,*rdata_len);
1799 SSVAL(*rparam,0,NERR_Success);
1800 SSVAL(*rparam,2,0); /* converter word */
1805 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1806 strcpy(p2,local_machine);
1807 p2 = skip_string(p2,1);
1810 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1811 strcpy(p2,sesssetup_user);
1812 p2 = skip_string(p2,1);
1815 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1816 strcpy(p2,my_workgroup());
1817 p2 = skip_string(p2,1);
1820 SCVAL(p,0,2); /* major version?? */
1821 SCVAL(p,1,1); /* minor version?? */
1824 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1825 strcpy(p2,my_workgroup()); /* login domain?? */
1826 p2 = skip_string(p2,1);
1829 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1831 p2 = skip_string(p2,1);
1834 *rdata_len = PTR_DIFF(p2,*rdata);
1836 SSVAL(*rparam,4,*rdata_len);
1842 /****************************************************************************
1843 get info about a user
1844 ****************************************************************************/
1846 #define USER_PRIV_GUEST 0
1847 #define USER_PRIV_USER 1
1848 #define USER_PRIV_ADMIN 2
1850 static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
1851 int mdrcnt,int mprcnt,
1852 char **rdata,char **rparam,
1853 int *rdata_len,int *rparam_len)
1855 char *str1 = param+2;
1856 char *str2 = skip_string(str1,1);
1857 char *UserName = skip_string(str2,1);
1858 char *p = skip_string(UserName,1);
1859 int uLevel = SVAL(p,0);
1863 *rparam = REALLOC(*rparam,*rparam_len);
1865 /* check it's a supported varient */
1866 if (strcmp(str1,"zWrLh") != 0) return False;
1868 case 0: p2 = "B21"; break;
1869 case 1: p2 = "B21BB16DWzzWz"; break;
1870 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1871 case 10: p2 = "B21Bzzz"; break;
1872 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1873 default: return False;
1875 if (strcmp(p2,str2) != 0) return False;
1877 *rdata_len = mdrcnt + 1024;
1878 *rdata = REALLOC(*rdata,*rdata_len);
1880 SSVAL(*rparam,0,NERR_Success);
1881 SSVAL(*rparam,2,0); /* converter word */
1892 SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
1893 strcpy(p2,"<Comment>");
1894 p2 = skip_string(p2,1);
1895 SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
1896 strcpy(p2,"<UserComment>");
1897 p2 = skip_string(p2,1);
1898 SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
1899 strcpy(p2,"<FullName>");
1900 p2 = skip_string(p2,1);
1902 if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
1903 SSVAL(p,34,USER_PRIV_USER); /* user privilege */
1904 SIVAL(p,36,0); /* auth flags */
1905 SIVALS(p,40,-1); /* password age */
1906 SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
1907 strcpy(p2,"\\\\%L\\HOMES");
1908 standard_sub_basic(p2);
1909 p2 = skip_string(p2,1);
1910 SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
1912 p2 = skip_string(p2,1);
1913 SIVAL(p,52,0); /* last logon */
1914 SIVAL(p,56,0); /* last logoff */
1915 SSVALS(p,60,-1); /* bad pw counts */
1916 SSVALS(p,62,-1); /* num logons */
1917 SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
1919 p2 = skip_string(p2,1);
1920 SSVAL(p,68,0); /* country code */
1922 SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
1924 p2 = skip_string(p2,1);
1926 SIVALS(p,74,-1); /* max storage */
1927 SSVAL(p,78,168); /* units per week */
1928 SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
1930 SCVAL(p2,21,0); /* fix zero termination */
1931 p2 = skip_string(p2,1);
1933 SSVAL(p,84,0); /* code page */
1935 if (uLevel == 1 || uLevel == 2) {
1936 memset(p+22,' ',16); /* password */
1937 SIVALS(p,38,-1); /* password age */
1938 SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */
1939 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
1940 strcpy(p2,"\\\\%L\\HOMES");
1941 standard_sub_basic(p2);
1942 p2 = skip_string(p2,1);
1943 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
1945 SSVAL(p,52,0); /* flags */
1946 SIVAL(p,54,0); /* script_path */
1948 SIVAL(p,60,0); /* auth_flags */
1949 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
1950 strcpy(p2,"<Full Name>");
1951 p2 = skip_string(p2,1);
1952 SIVAL(p,68,0); /* urs_comment */
1953 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
1955 p2 = skip_string(p2,1);
1956 SIVAL(p,76,0); /* workstations */
1957 SIVAL(p,80,0); /* last_logon */
1958 SIVAL(p,84,0); /* last_logoff */
1959 SIVALS(p,88,-1); /* acct_expires */
1960 SIVALS(p,92,-1); /* max_storage */
1961 SSVAL(p,96,168); /* units_per_week */
1962 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
1965 SSVALS(p,102,-1); /* bad_pw_count */
1966 SSVALS(p,104,-1); /* num_logons */
1967 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
1968 strcpy(p2,"\\\\%L");
1969 standard_sub_basic(p2);
1970 p2 = skip_string(p2,1);
1971 SSVAL(p,110,49); /* country_code */
1972 SSVAL(p,112,860); /* code page */
1977 *rdata_len = PTR_DIFF(p2,*rdata);
1979 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
1985 /*******************************************************************
1986 get groups that a user is a member of
1987 ******************************************************************/
1988 static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
1989 int mdrcnt,int mprcnt,
1990 char **rdata,char **rparam,
1991 int *rdata_len,int *rparam_len)
1993 char *str1 = param+2;
1994 char *str2 = skip_string(str1,1);
1995 char *UserName = skip_string(str2,1);
1996 char *p = skip_string(UserName,1);
1997 int uLevel = SVAL(p,0);
2002 *rparam = REALLOC(*rparam,*rparam_len);
2004 /* check it's a supported varient */
2005 if (strcmp(str1,"zWrLeh") != 0) return False;
2007 case 0: p2 = "B21"; break;
2008 default: return False;
2010 if (strcmp(p2,str2) != 0) return False;
2012 *rdata_len = mdrcnt + 1024;
2013 *rdata = REALLOC(*rdata,*rdata_len);
2015 SSVAL(*rparam,0,NERR_Success);
2016 SSVAL(*rparam,2,0); /* converter word */
2020 /* XXXX we need a real SAM database some day */
2021 strcpy(p,"Users"); p += 21; count++;
2022 strcpy(p,"Domain Users"); p += 21; count++;
2023 strcpy(p,"Guests"); p += 21; count++;
2024 strcpy(p,"Domain Guests"); p += 21; count++;
2026 *rdata_len = PTR_DIFF(p,*rdata);
2028 SSVAL(*rparam,4,count); /* is this right?? */
2029 SSVAL(*rparam,6,count); /* is this right?? */
2035 static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
2036 int mdrcnt,int mprcnt,
2037 char **rdata,char **rparam,
2038 int *rdata_len,int *rparam_len)
2040 char *str1 = param+2;
2041 char *str2 = skip_string(str1,1);
2042 char *p = skip_string(str2,1);
2044 struct pack_desc desc;
2050 bzero(&desc,sizeof(desc));
2052 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2054 /* check it's a supported varient */
2055 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2056 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2057 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2059 desc.buflen = mdrcnt;
2060 desc.subformat = NULL;
2065 if (init_package(&desc,1,0)) {
2066 PACKI(&desc,"W",0); /* code */
2067 PACKS(&desc,"B21",name); /* eff. name */
2068 PACKS(&desc,"B",""); /* pad */
2070 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2071 PACKI(&desc,"D",0); /* auth flags XXX */
2072 PACKI(&desc,"W",0); /* num logons */
2073 PACKI(&desc,"W",0); /* bad pw count */
2074 PACKI(&desc,"D",-1); /* last logon */
2075 PACKI(&desc,"D",-1); /* last logoff */
2076 PACKI(&desc,"D",-1); /* logoff time */
2077 PACKI(&desc,"D",-1); /* kickoff time */
2078 PACKI(&desc,"D",0); /* password age */
2079 PACKI(&desc,"D",0); /* password can change */
2080 PACKI(&desc,"D",-1); /* password must change */
2083 strcpy(mypath,"\\\\");
2084 strcat(mypath,local_machine);
2086 PACKS(&desc,"z",mypath); /* computer */
2088 PACKS(&desc,"z",my_workgroup());/* domain */
2089 PACKS(&desc,"z",lp_logon_script()); /* script path */
2090 PACKI(&desc,"D",0); /* reserved */
2093 *rdata_len = desc.usedlen;
2095 *rparam = REALLOC(*rparam,*rparam_len);
2096 SSVALS(*rparam,0,desc.errcode);
2098 SSVAL(*rparam,4,desc.neededlen);
2100 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2105 /****************************************************************************
2106 api_WAccessGetUserPerms
2107 ****************************************************************************/
2108 static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
2109 int mdrcnt,int mprcnt,
2110 char **rdata,char **rparam,
2111 int *rdata_len,int *rparam_len)
2113 char *str1 = param+2;
2114 char *str2 = skip_string(str1,1);
2115 char *user = skip_string(str2,1);
2116 char *resource = skip_string(user,1);
2118 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2120 /* check it's a supported varient */
2121 if (strcmp(str1,"zzh") != 0) return False;
2122 if (strcmp(str2,"") != 0) return False;
2125 *rparam = REALLOC(*rparam,*rparam_len);
2126 SSVALS(*rparam,0,0); /* errorcode */
2127 SSVAL(*rparam,2,0); /* converter word */
2128 SSVAL(*rparam,4,0x7f); /* permission flags */
2133 /****************************************************************************
2134 api_WPrintJobEnumerate
2135 ****************************************************************************/
2136 static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
2137 int mdrcnt,int mprcnt,
2138 char **rdata,char **rparam,
2139 int *rdata_len,int *rparam_len)
2141 char *str1 = param+2;
2142 char *str2 = skip_string(str1,1);
2143 char *p = skip_string(str2,1);
2144 int uJobId = SVAL(p,0);
2150 struct pack_desc desc;
2151 print_queue_struct *queue=NULL;
2152 print_status_struct status;
2157 bzero(&desc,sizeof(desc));
2158 bzero(&status,sizeof(status));
2160 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2162 /* check it's a supported varient */
2163 if (strcmp(str1,"WWrLh") != 0) return False;
2164 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2166 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2167 job = uJobId & 0xFF;
2169 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2171 count = get_printqueue(snum,cnum,&queue,&status);
2172 for (i = 0; i < count; i++) {
2173 if ((queue[i].job % 0xFF) == job) break;
2175 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2177 desc.buflen = mdrcnt;
2179 if (init_package(&desc,1,0)) {
2181 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2182 *rdata_len = desc.usedlen;
2185 desc.errcode = NERR_JobNotFound;
2191 *rparam = REALLOC(*rparam,*rparam_len);
2192 SSVALS(*rparam,0,desc.errcode);
2194 SSVAL(*rparam,4,desc.neededlen);
2196 if (queue) free(queue);
2198 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2202 static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
2203 int mdrcnt,int mprcnt,
2204 char **rdata,char **rparam,
2205 int *rdata_len,int *rparam_len)
2207 char *str1 = param+2;
2208 char *str2 = skip_string(str1,1);
2209 char *p = skip_string(str2,1);
2215 struct pack_desc desc;
2216 print_queue_struct *queue=NULL;
2217 print_status_struct status;
2219 bzero(&desc,sizeof(desc));
2220 bzero(&status,sizeof(status));
2222 p = skip_string(p,1);
2226 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2228 /* check it's a supported varient */
2229 if (strcmp(str1,"zWrLeh") != 0) return False;
2230 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2231 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2233 snum = lp_servicenumber(name);
2234 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2235 int pnum = lp_servicenumber(PRINTERS_NAME);
2237 lp_add_printer(name,pnum);
2238 snum = lp_servicenumber(name);
2242 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2244 count = get_printqueue(snum,cnum,&queue,&status);
2245 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2247 desc.buflen = mdrcnt;
2249 if (init_package(&desc,count,0)) {
2251 for (i = 0; i < count; i++) {
2252 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2253 if (desc.errcode == NERR_Success) succnt = i+1;
2257 *rdata_len = desc.usedlen;
2260 *rparam = REALLOC(*rparam,*rparam_len);
2261 SSVALS(*rparam,0,desc.errcode);
2263 SSVAL(*rparam,4,succnt);
2264 SSVAL(*rparam,6,count);
2266 if (queue) free(queue);
2268 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2272 static int check_printdest_info(struct pack_desc* desc,
2273 int uLevel, char* id)
2275 desc->subformat = NULL;
2277 case 0: desc->format = "B9"; break;
2278 case 1: desc->format = "B9B21WWzW"; break;
2279 case 2: desc->format = "z"; break;
2280 case 3: desc->format = "zzzWWzzzWW"; break;
2281 default: return False;
2283 if (strcmp(desc->format,id) != 0) return False;
2287 static void fill_printdest_info(int cnum, int snum, int uLevel,
2288 struct pack_desc* desc)
2291 strcpy(buf,SERVICE(snum));
2294 PACKS(desc,"B9",buf); /* szName */
2296 PACKS(desc,"B21",""); /* szUserName */
2297 PACKI(desc,"W",0); /* uJobId */
2298 PACKI(desc,"W",0); /* fsStatus */
2299 PACKS(desc,"z",""); /* pszStatus */
2300 PACKI(desc,"W",0); /* time */
2303 if (uLevel == 2 || uLevel == 3) {
2304 PACKS(desc,"z",buf); /* pszPrinterName */
2306 PACKS(desc,"z",""); /* pszUserName */
2307 PACKS(desc,"z",""); /* pszLogAddr */
2308 PACKI(desc,"W",0); /* uJobId */
2309 PACKI(desc,"W",0); /* fsStatus */
2310 PACKS(desc,"z",""); /* pszStatus */
2311 PACKS(desc,"z",""); /* pszComment */
2312 PACKS(desc,"z","NULL"); /* pszDrivers */
2313 PACKI(desc,"W",0); /* time */
2314 PACKI(desc,"W",0); /* pad1 */
2319 static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
2320 int mdrcnt,int mprcnt,
2321 char **rdata,char **rparam,
2322 int *rdata_len,int *rparam_len)
2324 char *str1 = param+2;
2325 char *str2 = skip_string(str1,1);
2326 char *p = skip_string(str2,1);
2327 char* PrinterName = p;
2329 struct pack_desc desc;
2332 bzero(&desc,sizeof(desc));
2334 p = skip_string(p,1);
2338 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2340 /* check it's a supported varient */
2341 if (strcmp(str1,"zWrLh") != 0) return False;
2342 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2344 snum = lp_servicenumber(PrinterName);
2345 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2346 int pnum = lp_servicenumber(PRINTERS_NAME);
2348 lp_add_printer(PrinterName,pnum);
2349 snum = lp_servicenumber(PrinterName);
2355 desc.errcode = NERR_DestNotFound;
2359 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2361 desc.buflen = mdrcnt;
2362 if (init_package(&desc,1,0)) {
2363 fill_printdest_info(cnum,snum,uLevel,&desc);
2365 *rdata_len = desc.usedlen;
2369 *rparam = REALLOC(*rparam,*rparam_len);
2370 SSVALS(*rparam,0,desc.errcode);
2372 SSVAL(*rparam,4,desc.neededlen);
2374 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2378 static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
2379 int mdrcnt,int mprcnt,
2380 char **rdata,char **rparam,
2381 int *rdata_len,int *rparam_len)
2383 char *str1 = param+2;
2384 char *str2 = skip_string(str1,1);
2385 char *p = skip_string(str2,1);
2389 struct pack_desc desc;
2390 int services = lp_numservices();
2392 bzero(&desc,sizeof(desc));
2397 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2399 /* check it's a supported varient */
2400 if (strcmp(str1,"WrLeh") != 0) return False;
2401 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2404 for (i = 0; i < services; i++)
2405 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2408 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2410 desc.buflen = mdrcnt;
2411 if (init_package(&desc,queuecnt,0)) {
2414 for (i = 0; i < services; i++) {
2415 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2416 fill_printdest_info(cnum,i,uLevel,&desc);
2418 if (desc.errcode == NERR_Success) succnt = n;
2423 *rdata_len = desc.usedlen;
2426 *rparam = REALLOC(*rparam,*rparam_len);
2427 SSVALS(*rparam,0,desc.errcode);
2429 SSVAL(*rparam,4,succnt);
2430 SSVAL(*rparam,6,queuecnt);
2432 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2436 static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
2437 int mdrcnt,int mprcnt,
2438 char **rdata,char **rparam,
2439 int *rdata_len,int *rparam_len)
2441 char *str1 = param+2;
2442 char *str2 = skip_string(str1,1);
2443 char *p = skip_string(str2,1);
2446 struct pack_desc desc;
2448 bzero(&desc,sizeof(desc));
2453 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2455 /* check it's a supported varient */
2456 if (strcmp(str1,"WrLeh") != 0) return False;
2457 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2459 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2461 desc.buflen = mdrcnt;
2462 if (init_package(&desc,1,0)) {
2463 PACKS(&desc,"B41","NULL");
2466 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2468 *rdata_len = desc.usedlen;
2471 *rparam = REALLOC(*rparam,*rparam_len);
2472 SSVALS(*rparam,0,desc.errcode);
2474 SSVAL(*rparam,4,succnt);
2477 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2481 static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
2482 int mdrcnt,int mprcnt,
2483 char **rdata,char **rparam,
2484 int *rdata_len,int *rparam_len)
2486 char *str1 = param+2;
2487 char *str2 = skip_string(str1,1);
2488 char *p = skip_string(str2,1);
2491 struct pack_desc desc;
2493 bzero(&desc,sizeof(desc));
2498 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2500 /* check it's a supported varient */
2501 if (strcmp(str1,"WrLeh") != 0) return False;
2502 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2504 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2506 desc.buflen = mdrcnt;
2508 if (init_package(&desc,1,0)) {
2509 PACKS(&desc,"B13","lpd");
2512 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2514 *rdata_len = desc.usedlen;
2517 *rparam = REALLOC(*rparam,*rparam_len);
2518 SSVALS(*rparam,0,desc.errcode);
2520 SSVAL(*rparam,4,succnt);
2523 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2527 static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
2528 int mdrcnt,int mprcnt,
2529 char **rdata,char **rparam,
2530 int *rdata_len,int *rparam_len)
2532 char *str1 = param+2;
2533 char *str2 = skip_string(str1,1);
2534 char *p = skip_string(str2,1);
2537 struct pack_desc desc;
2539 bzero(&desc,sizeof(desc));
2544 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2546 /* check it's a supported varient */
2547 if (strcmp(str1,"WrLeh") != 0) return False;
2548 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2550 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2551 bzero(&desc,sizeof(desc));
2553 desc.buflen = mdrcnt;
2555 if (init_package(&desc,1,0)) {
2556 PACKS(&desc,"B13","lp0");
2559 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2561 *rdata_len = desc.usedlen;
2564 *rparam = REALLOC(*rparam,*rparam_len);
2565 SSVALS(*rparam,0,desc.errcode);
2567 SSVAL(*rparam,4,succnt);
2570 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2574 /****************************************************************************
2575 the buffer was too small
2576 ****************************************************************************/
2577 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
2578 int mdrcnt,int mprcnt,
2579 char **rdata,char **rparam,
2580 int *rdata_len,int *rparam_len)
2582 *rparam_len = MIN(*rparam_len,mprcnt);
2583 *rparam = REALLOC(*rparam,*rparam_len);
2587 SSVAL(*rparam,0,NERR_BufTooSmall);
2589 DEBUG(3,("Supplied buffer too small in API command\n"));
2595 /****************************************************************************
2596 the request is not supported
2597 ****************************************************************************/
2598 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
2599 int mdrcnt,int mprcnt,
2600 char **rdata,char **rparam,
2601 int *rdata_len,int *rparam_len)
2604 *rparam = REALLOC(*rparam,*rparam_len);
2608 SSVAL(*rparam,0,NERR_notsupported);
2609 SSVAL(*rparam,2,0); /* converter word */
2611 DEBUG(3,("Unsupported API command\n"));
2625 } api_commands[] = {
2626 {"RNetShareEnum", 0, api_RNetShareEnum,0},
2627 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
2628 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
2629 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
2630 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
2631 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
2632 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
2633 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
2634 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
2635 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
2636 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
2637 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
2638 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
2639 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
2640 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
2641 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
2642 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
2643 {"NetServerEnum", 104, api_RNetServerEnum,0},
2644 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
2645 {"SetUserPassword", 115, api_SetUserPassword,0},
2646 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
2647 {"PrintJobInfo", 147, api_PrintJobInfo,0},
2648 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
2649 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
2650 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
2651 {NULL, -1, api_Unsupported,0}};
2654 /****************************************************************************
2655 handle remote api calls
2656 ****************************************************************************/
2657 static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
2658 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2660 int api_command = SVAL(params,0);
2662 char *rparam = NULL;
2668 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2669 api_command,params+2,skip_string(params+2,1),
2670 tdscnt,tpscnt,mdrcnt,mprcnt));
2672 for (i=0;api_commands[i].name;i++)
2673 if (api_commands[i].id == api_command && api_commands[i].fn)
2675 DEBUG(3,("Doing %s\n",api_commands[i].name));
2679 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2680 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2682 reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2683 &rdata,&rparam,&rdata_len,&rparam_len);
2686 if (rdata_len > mdrcnt ||
2687 rparam_len > mprcnt)
2689 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2690 &rdata,&rparam,&rdata_len,&rparam_len);
2694 /* if we get False back then it's actually unsupported */
2696 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2697 &rdata,&rparam,&rdata_len,&rparam_len);
2701 /* now send the reply */
2702 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2712 /****************************************************************************
2713 handle named pipe commands
2714 ****************************************************************************/
2715 static int named_pipe(int cnum,int uid, char *outbuf,char *name,
2716 uint16 *setup,char *data,char *params,
2717 int suwcnt,int tdscnt,int tpscnt,
2718 int msrcnt,int mdrcnt,int mprcnt)
2721 if (strequal(name,"LANMAN"))
2722 return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2724 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2725 name,(int)setup[0],(int)setup[1]));
2731 /****************************************************************************
2733 ****************************************************************************/
2734 int reply_trans(char *inbuf,char *outbuf)
2738 char *data=NULL,*params=NULL;
2742 int cnum = SVAL(inbuf,smb_tid);
2743 int uid = SVAL(inbuf,smb_uid);
2745 int tpscnt = SVAL(inbuf,smb_vwv0);
2746 int tdscnt = SVAL(inbuf,smb_vwv1);
2747 int mprcnt = SVAL(inbuf,smb_vwv2);
2748 int mdrcnt = SVAL(inbuf,smb_vwv3);
2749 int msrcnt = CVAL(inbuf,smb_vwv4);
2750 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2751 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2752 int pscnt = SVAL(inbuf,smb_vwv9);
2753 int psoff = SVAL(inbuf,smb_vwv10);
2754 int dscnt = SVAL(inbuf,smb_vwv11);
2755 int dsoff = SVAL(inbuf,smb_vwv12);
2756 int suwcnt = CVAL(inbuf,smb_vwv13);
2758 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2762 data = (char *)malloc(tdscnt);
2763 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2767 params = (char *)malloc(tpscnt);
2768 memcpy(params,smb_base(inbuf)+psoff,pscnt);
2774 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
2775 for (i=0;i<suwcnt;i++)
2776 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
2780 if (pscnt < tpscnt || dscnt < tdscnt)
2782 /* We need to send an interim response then receive the rest
2783 of the parameter/data bytes */
2784 outsize = set_message(outbuf,0,0,True);
2786 send_smb(Client,outbuf);
2789 /* receive the rest of the trans packet */
2790 while (pscnt < tpscnt || dscnt < tdscnt)
2792 int pcnt,poff,dcnt,doff,pdisp,ddisp;
2794 receive_smb(Client,inbuf, 0);
2797 /* Ensure this is still a trans packet (sanity check) */
2798 if(CVAL(inbuf, smb_com) != SMBtrans)
2800 DEBUG(2,("Invalid secondary trans2 packet\n"));
2801 if (params) free(params);
2802 if (data) free(data);
2803 if (setup) free(setup);
2804 return(ERROR(ERRSRV,ERRerror));
2807 tpscnt = SVAL(inbuf,smb_vwv0);
2808 tdscnt = SVAL(inbuf,smb_vwv1);
2810 pcnt = SVAL(inbuf,smb_vwv2);
2811 poff = SVAL(inbuf,smb_vwv3);
2812 pdisp = SVAL(inbuf,smb_vwv4);
2814 dcnt = SVAL(inbuf,smb_vwv5);
2815 doff = SVAL(inbuf,smb_vwv6);
2816 ddisp = SVAL(inbuf,smb_vwv7);
2822 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
2824 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
2828 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
2831 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
2832 outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
2833 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
2836 if (data) free(data);
2837 if (params) free(params);
2838 if (setup) free(setup);
2840 if (close_on_completion)
2841 close_cnum(cnum,uid);
2847 return(ERROR(ERRSRV,ERRnosupport));