2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1998
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
37 extern int DEBUGLEVEL;
40 extern fstring local_machine;
41 extern fstring global_myworkgroup;
43 #define NERR_Success 0
44 #define NERR_badpass 86
45 #define NERR_notsupported 50
47 #define NERR_BASE (2100)
48 #define NERR_BufTooSmall (NERR_BASE+23)
49 #define NERR_JobNotFound (NERR_BASE+51)
50 #define NERR_DestNotFound (NERR_BASE+52)
51 #define ERROR_INVALID_LEVEL 124
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 */
63 extern int smb_read_error;
65 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
66 int mdrcnt,int mprcnt,
67 char **rdata,char **rparam,
68 int *rdata_len,int *rparam_len);
69 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
70 int mdrcnt,int mprcnt,
71 char **rdata,char **rparam,
72 int *rdata_len,int *rparam_len);
75 static int CopyExpanded(connection_struct *conn,
76 int snum, char** dst, char* src, int* n)
81 if (!src || !dst || !n || !(*dst)) return(0);
83 StrnCpy(buf,src,sizeof(buf)/2);
84 string_sub(buf,"%S",lp_servicename(snum));
85 standard_sub(conn,buf);
93 static int CopyAndAdvance(char** dst, char* src, int* n)
96 if (!src || !dst || !n || !(*dst)) return(0);
104 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
108 StrnCpy(buf,s,sizeof(buf)/2);
109 string_sub(buf,"%S",lp_servicename(snum));
110 standard_sub(conn,buf);
111 return strlen(buf) + 1;
114 static char* Expand(connection_struct *conn, int snum, char* s)
117 if (!s) return(NULL);
118 StrnCpy(buf,s,sizeof(buf)/2);
119 string_sub(buf,"%S",lp_servicename(snum));
120 standard_sub(conn,buf);
124 /*******************************************************************
125 check a API string for validity when we only need to check the prefix
126 ******************************************************************/
127 static BOOL prefix_ok(char *str,char *prefix)
129 return(strncmp(str,prefix,strlen(prefix)) == 0);
132 /*******************************************************************
133 copies parameters and data, as needed, into the smb buffer
135 *both* the data and params sections should be aligned. this
136 is fudged in the rpc pipes by
137 at present, only the data section is. this may be a possible
138 cause of some of the ipc problems being experienced. lkcl26dec97
140 ******************************************************************/
141 static void copy_trans_params_and_data(char *outbuf, int align,
142 struct mem_buf *rparam, struct mem_buf *rdata,
143 int param_offset, int data_offset,
144 int param_len, int data_len)
146 char *copy_into = smb_buf(outbuf)+1;
148 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
149 param_offset, param_offset + param_len,
150 data_offset , data_offset + data_len));
152 if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len);
153 copy_into += param_len + align;
154 if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len);
157 /****************************************************************************
159 ****************************************************************************/
160 static void send_trans_reply(char *outbuf,
161 struct mem_buf *rdata,
162 struct mem_buf *rparam,
163 uint16 *setup, int lsetup, int max_data_ret)
166 int this_ldata,this_lparam;
167 int tot_data=0,tot_param=0;
170 int ldata = rdata ? mem_buf_len(rdata ) : 0;
171 int lparam = rparam ? mem_buf_len(rparam) : 0;
173 BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False;
175 if (buffer_too_large)
177 DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret));
178 ldata = max_data_ret;
181 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
182 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
184 align = ((this_lparam)%4);
186 set_message(outbuf,10+lsetup,1+align+this_ldata+this_lparam,True);
188 if (buffer_too_large)
190 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
191 SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
192 SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
195 copy_trans_params_and_data(outbuf, align,
197 tot_param , tot_data,
198 this_lparam, this_ldata);
200 SSVAL(outbuf,smb_vwv0,lparam);
201 SSVAL(outbuf,smb_vwv1,ldata);
202 SSVAL(outbuf,smb_vwv3,this_lparam);
203 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
204 SSVAL(outbuf,smb_vwv5,0);
205 SSVAL(outbuf,smb_vwv6,this_ldata);
206 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
207 SSVAL(outbuf,smb_vwv8,0);
208 SSVAL(outbuf,smb_vwv9,lsetup);
210 for (i=0;i<lsetup;i++)
212 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
216 send_smb(Client,outbuf);
218 tot_data = this_ldata;
219 tot_param = this_lparam;
221 while (tot_data < ldata || tot_param < lparam)
223 this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */
224 this_ldata = MIN(ldata -tot_data , max_send - (500+this_lparam));
226 align = (this_lparam%4);
228 set_message(outbuf,10,1+this_ldata+this_lparam+align,False);
230 copy_trans_params_and_data(outbuf, align,
232 tot_param , tot_data,
233 this_lparam, this_ldata);
235 SSVAL(outbuf,smb_vwv3,this_lparam);
236 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
237 SSVAL(outbuf,smb_vwv5,tot_param);
238 SSVAL(outbuf,smb_vwv6,this_ldata);
239 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
240 SSVAL(outbuf,smb_vwv8,tot_data);
241 SSVAL(outbuf,smb_vwv9,0);
244 send_smb(Client,outbuf);
246 tot_data += this_ldata;
247 tot_param += this_lparam;
252 char* format; /* formatstring for structure */
253 char* subformat; /* subformat for structure */
254 char* base; /* baseaddress of buffer */
255 int buflen; /* remaining size for fixed part; on init: length of base */
256 int subcount; /* count of substructures */
257 char* structbuf; /* pointer into buffer for remaining fixed part */
258 int stringlen; /* remaining size for variable part */
259 char* stringbuf; /* pointer into buffer for remaining variable part */
260 int neededlen; /* total needed size */
261 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
262 char* curpos; /* current position; pointer into format or subformat */
266 static int get_counter(char** p)
269 if (!p || !(*p)) return(1);
270 if (!isdigit((int)**p)) return 1;
274 n = 10 * n + (i - '0');
281 static int getlen(char* p)
287 case 'W': /* word (2 byte) */
290 case 'N': /* count of substructures (word) at end */
293 case 'D': /* double word (4 byte) */
294 case 'z': /* offset to zero terminated string (4 byte) */
295 case 'l': /* offset to user data (4 byte) */
298 case 'b': /* offset to data (with counter) (4 byte) */
302 case 'B': /* byte (with optional counter) */
303 n += get_counter(&p);
310 static BOOL init_package(struct pack_desc* p, int count, int subcount)
315 if (!p->format || !p->base) return(False);
317 i = count * getlen(p->format);
318 if (p->subformat) i += subcount * getlen(p->subformat);
319 p->structbuf = p->base;
323 p->curpos = p->format;
327 p->errcode = ERRmoredata;
330 p->errcode = NERR_Success;
333 p->stringbuf = p->base + i;
335 return(p->errcode == NERR_Success);
339 static int package(struct pack_desc* p, ...)
342 static int package(va_alist)
348 int needed=0, stringneeded;
350 int is_string=0, stringused;
357 p = va_arg(args,struct pack_desc *);
362 p->curpos = p->format;
364 p->curpos = p->subformat;
369 str = va_arg(args,char*);
370 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
374 if (!p->curpos) return(0);
376 switch( *p->curpos++ ) {
377 case 'W': /* word (2 byte) */
379 temp = va_arg(args,int);
380 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
382 case 'N': /* count of substructures (word) at end */
384 p->subcount = va_arg(args,int);
385 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
387 case 'D': /* double word (4 byte) */
389 temp = va_arg(args,int);
390 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
392 case 'B': /* byte (with optional counter) */
393 needed = get_counter(&p->curpos);
395 char *s = va_arg(args,char*);
396 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
399 case 'z': /* offset to zero terminated string (4 byte) */
400 str = va_arg(args,char*);
401 stringneeded = (str ? strlen(str)+1 : 0);
404 case 'l': /* offset to user data (4 byte) */
405 str = va_arg(args,char*);
406 stringneeded = va_arg(args,int);
409 case 'b': /* offset to data (with counter) (4 byte) */
410 str = va_arg(args,char*);
411 stringneeded = get_counter(&p->curpos);
416 if (stringneeded >= 0) {
418 if (p->buflen >= needed) {
419 stringused = stringneeded;
420 if (stringused > p->stringlen) {
421 stringused = (is_string ? p->stringlen : 0);
422 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
425 SIVAL(p->structbuf,0,0);
427 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
428 memcpy(p->stringbuf,str?str:"",stringused);
429 if (is_string) p->stringbuf[stringused-1] = '\0';
430 p->stringbuf += stringused;
431 p->stringlen -= stringused;
432 p->usedlen += stringused;
435 p->neededlen += stringneeded;
437 p->neededlen += needed;
438 if (p->buflen >= needed) {
439 p->structbuf += needed;
441 p->usedlen += needed;
444 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
450 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
451 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
453 #define PACK(desc,t,v) package(desc,v)
454 #define PACKl(desc,t,v,l) package(desc,v,l)
457 static void PACKI(struct pack_desc* desc,char *t,int v)
462 static void PACKS(struct pack_desc* desc,char *t,char *v)
468 /****************************************************************************
470 ****************************************************************************/
472 static void PackDriverData(struct pack_desc* desc)
474 char drivdata[4+4+32];
475 SIVAL(drivdata,0,sizeof drivdata); /* cb */
476 SIVAL(drivdata,4,1000); /* lVersion */
477 memset(drivdata+8,0,32); /* szDeviceName */
478 pstrcpy(drivdata+8,"NULL");
479 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
482 static int check_printq_info(struct pack_desc* desc,
483 int uLevel, char *id1, char *id2)
485 desc->subformat = NULL;
488 desc->format = "B13";
491 desc->format = "B13BWWWzzzzzWW";
494 desc->format = "B13BWWWzzzzzWN";
495 desc->subformat = "WB21BB16B10zWWzDDz";
498 desc->format = "zWWWWzzzzWWzzl";
501 desc->format = "zWWWWzzzzWNzzl";
502 desc->subformat = "WWzWWDDzz";
508 desc->format = "WzzzzzzzzN";
509 desc->subformat = "z";
511 default: return False;
513 if (strcmp(desc->format,id1) != 0) return False;
514 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
518 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
519 struct pack_desc* desc,
520 print_queue_struct* queue, int n)
522 time_t t = queue->time;
524 /* the client expects localtime */
527 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
529 PACKS(desc,"B21",queue->user); /* szUserName */
530 PACKS(desc,"B",""); /* pad */
531 PACKS(desc,"B16",""); /* szNotifyName */
532 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
533 PACKS(desc,"z",""); /* pszParms */
534 PACKI(desc,"W",n+1); /* uPosition */
535 PACKI(desc,"W",queue->status); /* fsStatus */
536 PACKS(desc,"z",""); /* pszStatus */
537 PACKI(desc,"D",t); /* ulSubmitted */
538 PACKI(desc,"D",queue->size); /* ulSize */
539 PACKS(desc,"z",queue->file); /* pszComment */
541 if (uLevel == 2 || uLevel == 3) {
542 PACKI(desc,"W",queue->priority); /* uPriority */
543 PACKS(desc,"z",queue->user); /* pszUserName */
544 PACKI(desc,"W",n+1); /* uPosition */
545 PACKI(desc,"W",queue->status); /* fsStatus */
546 PACKI(desc,"D",t); /* ulSubmitted */
547 PACKI(desc,"D",queue->size); /* ulSize */
548 PACKS(desc,"z","Samba"); /* pszComment */
549 PACKS(desc,"z",queue->file); /* pszDocument */
551 PACKS(desc,"z",""); /* pszNotifyName */
552 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
553 PACKS(desc,"z",""); /* pszParms */
554 PACKS(desc,"z",""); /* pszStatus */
555 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
556 PACKS(desc,"z","lpd"); /* pszQProcName */
557 PACKS(desc,"z",""); /* pszQProcParms */
558 PACKS(desc,"z","NULL"); /* pszDriverName */
559 PackDriverData(desc); /* pDriverData */
560 PACKS(desc,"z",""); /* pszPrinterName */
565 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
566 struct pack_desc* desc,
567 int count, print_queue_struct* queue,
568 print_status_struct* status)
573 PACKS(desc,"B13",SERVICE(snum));
578 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
582 if (uLevel == 1 || uLevel == 2) {
583 PACKS(desc,"B",""); /* alignment */
584 PACKI(desc,"W",5); /* priority */
585 PACKI(desc,"W",0); /* start time */
586 PACKI(desc,"W",0); /* until time */
587 PACKS(desc,"z",""); /* pSepFile */
588 PACKS(desc,"z","lpd"); /* pPrProc */
589 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
590 PACKS(desc,"z",""); /* pParms */
592 PACKS(desc,"z","UNKNOWN PRINTER");
593 PACKI(desc,"W",LPSTAT_ERROR);
595 else if (!status || !status->message[0]) {
596 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
597 PACKI(desc,"W",LPSTAT_OK); /* status */
599 PACKS(desc,"z",status->message);
600 PACKI(desc,"W",status->status); /* status */
602 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
604 if (uLevel == 3 || uLevel == 4) {
605 PACKI(desc,"W",5); /* uPriority */
606 PACKI(desc,"W",0); /* uStarttime */
607 PACKI(desc,"W",0); /* uUntiltime */
608 PACKI(desc,"W",5); /* pad1 */
609 PACKS(desc,"z",""); /* pszSepFile */
610 PACKS(desc,"z","WinPrint"); /* pszPrProc */
611 PACKS(desc,"z",""); /* pszParms */
612 if (!status || !status->message[0]) {
613 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
614 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
616 PACKS(desc,"z",status->message); /* pszComment */
617 PACKI(desc,"W",status->status); /* fsStatus */
619 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
620 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
621 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
622 PackDriverData(desc); /* pDriverData */
624 if (uLevel == 2 || uLevel == 4) {
626 for (i=0;i<count;i++)
627 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
632 pstring tok,driver,datafile,langmon,helpfile,datatype;
637 pstrcpy(fname,lp_driverfile());
640 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
641 desc->errcode=NERR_notsupported;
645 if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
646 DEBUG(0,("fill_printq_info: malloc fail !\n"));
647 desc->errcode=NERR_notsupported;
652 bzero(p, 8192*sizeof(char));
655 /* lookup the long printer driver name in the file description */
656 while (f && !feof(f) && !ok)
658 p = q; /* reset string pointer */
661 if (next_token(&p,tok,":",sizeof(tok)) &&
662 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
663 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
668 /* driver file name */
669 if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0;
671 if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0;
673 * for the next tokens - which may be empty - I have to check for empty
674 * tokens first because the next_token function will skip all empty
682 } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0;
686 /* language monitor */
690 } else if (!next_token(&p,langmon,":",sizeof(langmon))) ok = 0;
693 /* default data type */
694 if (ok && !next_token(&p,datatype,":",sizeof(datatype))) ok = 0;
697 PACKI(desc,"W",0x0400); /* don't know */
698 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
699 PACKS(desc,"z",driver); /* Driverfile Name */
700 PACKS(desc,"z",datafile); /* Datafile name */
701 PACKS(desc,"z",langmon); /* language monitor */
702 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
703 PACKS(desc,"z",datatype); /* default data type */
704 PACKS(desc,"z",helpfile); /* helpfile name */
705 PACKS(desc,"z",driver); /* driver name */
706 DEBUG(3,("Driver:%s:\n",driver));
707 DEBUG(3,("Data File:%s:\n",datafile));
708 DEBUG(3,("Language Monitor:%s:\n",langmon));
709 DEBUG(3,("Data Type:%s:\n",datatype));
710 DEBUG(3,("Help File:%s:\n",helpfile));
711 PACKI(desc,"N",count); /* number of files to copy */
712 for (i=0;i<count;i++)
714 /* no need to check return value here - it was already tested in
715 * get_printerdrivernumber
717 next_token(&p,tok,",",sizeof(tok));
718 PACKS(desc,"z",tok); /* driver files to copy */
719 DEBUG(3,("file:%s:\n",tok));
722 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
723 SERVICE(snum),count));
725 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
726 desc->errcode=NERR_notsupported;
732 /* This function returns the number of files for a given driver */
733 static int get_printerdrivernumber(int snum)
741 pstrcpy(fname,lp_driverfile());
743 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
746 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
750 if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
751 DEBUG(3,("get_printerdrivernumber: malloc fail !\n"));
756 q=p; /* need it to free memory because p change ! */
758 /* lookup the long printer driver name in the file description */
759 while (!feof(f) && !ok)
761 p = q; /* reset string pointer */
763 if (next_token(&p,tok,":",sizeof(tok)) &&
764 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
773 if (*p++ == ':') i--;
778 /* count the number of files */
779 while (next_token(&p,tok,",",sizeof(tok)))
787 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
788 uint16 vuid, char *param,char *data,
789 int mdrcnt,int mprcnt,
790 char **rdata,char **rparam,
791 int *rdata_len,int *rparam_len)
793 char *str1 = param+2;
794 char *str2 = skip_string(str1,1);
795 char *p = skip_string(str2,1);
801 struct pack_desc desc;
802 print_queue_struct *queue=NULL;
803 print_status_struct status;
805 bzero(&status,sizeof(status));
806 bzero(&desc,sizeof(desc));
808 p = skip_string(p,1);
812 /* remove any trailing username */
813 if ((p = strchr(QueueName,'%'))) *p = 0;
815 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
817 /* check it's a supported varient */
818 if (!prefix_ok(str1,"zWrLh")) return False;
819 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
821 snum = lp_servicenumber(QueueName);
822 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
823 int pnum = lp_servicenumber(PRINTERS_NAME);
825 lp_add_printer(QueueName,pnum);
826 snum = lp_servicenumber(QueueName);
830 if (snum < 0 || !VALID_SNUM(snum)) return(False);
833 count = get_printerdrivernumber(snum);
834 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
836 count = get_printqueue(snum, conn,&queue,&status);
839 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
841 desc.buflen = mdrcnt;
842 if (init_package(&desc,1,count)) {
843 desc.subcount = count;
844 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
847 *rdata_len = desc.usedlen;
850 *rparam = REALLOC(*rparam,*rparam_len);
851 SSVALS(*rparam,0,desc.errcode);
853 SSVAL(*rparam,4,desc.neededlen);
855 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
857 if (queue) free(queue);
863 /****************************************************************************
864 view list of all print jobs on all queues
865 ****************************************************************************/
866 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
867 int mdrcnt, int mprcnt,
868 char **rdata, char** rparam,
869 int *rdata_len, int *rparam_len)
871 char *param_format = param+2;
872 char *output_format1 = skip_string(param_format,1);
873 char *p = skip_string(output_format1,1);
874 int uLevel = SVAL(p,0);
875 char *output_format2 = p + 4;
876 int services = lp_numservices();
878 struct pack_desc desc;
879 print_queue_struct **queue = NULL;
880 print_status_struct *status = NULL;
881 int* subcntarr = NULL;
882 int queuecnt, subcnt=0, succnt=0;
884 bzero(&desc,sizeof(desc));
886 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
888 if (!prefix_ok(param_format,"WrLeh")) return False;
889 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
892 for (i = 0; i < services; i++)
893 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
896 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
897 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
900 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
901 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
902 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
905 memset(status,0,queuecnt*sizeof(print_status_struct));
906 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
907 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
912 for (i = 0; i < services; i++)
913 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
914 subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]);
915 subcnt += subcntarr[n];
919 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
921 desc.buflen = mdrcnt;
923 if (init_package(&desc,queuecnt,subcnt)) {
926 for (i = 0; i < services; i++)
927 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
928 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
930 if (desc.errcode == NERR_Success) succnt = n;
934 if (subcntarr) free(subcntarr);
936 *rdata_len = desc.usedlen;
938 *rparam = REALLOC(*rparam,*rparam_len);
939 SSVALS(*rparam,0,desc.errcode);
941 SSVAL(*rparam,4,succnt);
942 SSVAL(*rparam,6,queuecnt);
944 for (i = 0; i < queuecnt; i++) {
945 if (queue && queue[i]) free(queue[i]);
948 if (queue) free(queue);
949 if (status) free(status);
954 /****************************************************************************
955 get info level for a server list query
956 ****************************************************************************/
957 static BOOL check_server_info(int uLevel, char* id)
961 if (strcmp(id,"B16") != 0) return False;
964 if (strcmp(id,"B16BBDz") != 0) return False;
972 struct srv_info_struct
982 /*******************************************************************
983 get server info lists from the files saved by nmbd. Return the
985 ******************************************************************/
986 static int get_server_info(uint32 servertype,
987 struct srv_info_struct **servers,
995 BOOL local_list_only;
997 pstrcpy(fname,lp_lockdir());
998 trim_string(fname,NULL,"/");
1000 pstrcat(fname,SERVER_LIST);
1002 f = fopen(fname,"r");
1005 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1009 /* request for everything is code for request all servers */
1010 if (servertype == SV_TYPE_ALL)
1011 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1013 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1015 DEBUG(4,("Servertype search: %8x\n",servertype));
1020 struct srv_info_struct *s;
1025 fgets(line,sizeof(line)-1,f);
1026 if (!*line) continue;
1028 if (count == alloced) {
1030 (*servers) = (struct srv_info_struct *)
1031 Realloc(*servers,sizeof(**servers)*alloced);
1032 if (!(*servers)) return(0);
1033 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
1035 s = &(*servers)[count];
1037 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1038 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1039 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1040 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1041 /* this allows us to cope with an old nmbd */
1042 pstrcpy(s->domain,global_myworkgroup);
1045 if (sscanf(stype,"%X",&s->type) != 1) {
1046 DEBUG(4,("r:host file "));
1050 /* Filter the servers/domains we return based on what was asked for. */
1052 /* Check to see if we are being asked for a local list only. */
1053 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1054 DEBUG(4,("r: local list only"));
1058 /* doesn't match up: don't want it */
1059 if (!(servertype & s->type)) {
1060 DEBUG(4,("r:serv type "));
1064 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1065 (s->type & SV_TYPE_DOMAIN_ENUM))
1067 DEBUG(4,("s: dom mismatch "));
1071 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1076 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1077 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1081 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1082 s->name, s->type, s->comment, s->domain));
1084 s->server_added = True;
1089 DEBUG(4,("%20s %8x %25s %15s\n",
1090 s->name, s->type, s->comment, s->domain));
1099 /*******************************************************************
1100 fill in a server info structure
1101 ******************************************************************/
1102 static int fill_srv_info(struct srv_info_struct *service,
1103 int uLevel, char **buf, int *buflen,
1104 char **stringbuf, int *stringspace, char *baseaddr)
1113 case 0: struct_len = 16; break;
1114 case 1: struct_len = 26; break;
1124 len = strlen(service->comment)+1;
1128 if (buflen) *buflen = struct_len;
1129 if (stringspace) *stringspace = len;
1130 return struct_len + len;
1135 if (*buflen < struct_len) return -1;
1143 p2 = p + struct_len;
1144 l2 = *buflen - struct_len;
1146 if (!baseaddr) baseaddr = p;
1151 StrnCpy(p,service->name,15);
1155 StrnCpy(p,service->name,15);
1156 SIVAL(p,18,service->type);
1157 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1158 len += CopyAndAdvance(&p2,service->comment,&l2);
1164 *buf = p + struct_len;
1165 *buflen -= struct_len;
1178 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1180 return(strcmp(s1->name,s2->name));
1183 /****************************************************************************
1184 view list of servers available (or possibly domains). The info is
1185 extracted from lists saved by nmbd on the local host
1186 ****************************************************************************/
1187 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1188 int mdrcnt, int mprcnt, char **rdata,
1189 char **rparam, int *rdata_len, int *rparam_len)
1191 char *str1 = param+2;
1192 char *str2 = skip_string(str1,1);
1193 char *p = skip_string(str2,1);
1194 int uLevel = SVAL(p,0);
1195 int buf_len = SVAL(p,2);
1196 uint32 servertype = IVAL(p,4);
1198 int data_len, fixed_len, string_len;
1199 int f_len = 0, s_len = 0;
1200 struct srv_info_struct *servers=NULL;
1201 int counted=0,total=0;
1204 BOOL domain_request;
1207 /* If someone sets all the bits they don't really mean to set
1208 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1211 if (servertype == SV_TYPE_ALL)
1212 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1214 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1215 any other bit (they may just set this bit on it's own) they
1216 want all the locally seen servers. However this bit can be
1217 set on its own so set the requested servers to be
1218 ALL - DOMAIN_ENUM. */
1220 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1221 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1223 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1224 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1228 if (!prefix_ok(str1,"WrLehD")) return False;
1229 if (!check_server_info(uLevel,str2)) return False;
1231 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1232 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1233 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1235 if (strcmp(str1, "WrLehDz") == 0) {
1236 StrnCpy(domain, p, sizeof(fstring)-1);
1238 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1241 if (lp_browse_list())
1242 total = get_server_info(servertype,&servers,domain);
1244 data_len = fixed_len = string_len = 0;
1247 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1250 char *lastname=NULL;
1252 for (i=0;i<total;i++)
1254 struct srv_info_struct *s = &servers[i];
1255 if (lastname && strequal(lastname,s->name)) continue;
1257 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1258 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1259 s->name, s->type, s->comment, s->domain));
1261 if (data_len <= buf_len) {
1264 string_len += s_len;
1271 *rdata_len = fixed_len + string_len;
1272 *rdata = REALLOC(*rdata,*rdata_len);
1273 bzero(*rdata,*rdata_len);
1275 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1281 char *lastname=NULL;
1282 int count2 = counted;
1283 for (i = 0; i < total && count2;i++)
1285 struct srv_info_struct *s = &servers[i];
1286 if (lastname && strequal(lastname,s->name)) continue;
1288 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1289 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1290 s->name, s->type, s->comment, s->domain));
1296 *rparam = REALLOC(*rparam,*rparam_len);
1297 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1299 SSVAL(*rparam,4,counted);
1300 SSVAL(*rparam,6,counted+missed);
1302 if (servers) free(servers);
1304 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1305 domain,uLevel,counted,counted+missed));
1310 /****************************************************************************
1311 command 0x34 - suspected of being a "Lookup Names" stub api
1312 ****************************************************************************/
1313 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1314 int mdrcnt, int mprcnt, char **rdata,
1315 char **rparam, int *rdata_len, int *rparam_len)
1317 char *str1 = param+2;
1318 char *str2 = skip_string(str1,1);
1319 char *p = skip_string(str2,1);
1320 int uLevel = SVAL(p,0);
1321 int buf_len = SVAL(p,2);
1325 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1326 str1, str2, p, uLevel, buf_len));
1328 if (!prefix_ok(str1,"zWrLeh")) return False;
1334 *rparam = REALLOC(*rparam,*rparam_len);
1336 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1338 SSVAL(*rparam,4,counted);
1339 SSVAL(*rparam,6,counted+missed);
1344 /****************************************************************************
1345 get info about a share
1346 ****************************************************************************/
1347 static BOOL check_share_info(int uLevel, char* id)
1351 if (strcmp(id,"B13") != 0) return False;
1354 if (strcmp(id,"B13BWz") != 0) return False;
1357 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1360 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1362 default: return False;
1367 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1368 char** buf, int* buflen,
1369 char** stringbuf, int* stringspace, char* baseaddr)
1378 case 0: struct_len = 13; break;
1379 case 1: struct_len = 20; break;
1380 case 2: struct_len = 40; break;
1381 case 91: struct_len = 68; break;
1389 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1390 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1391 if (buflen) *buflen = struct_len;
1392 if (stringspace) *stringspace = len;
1393 return struct_len + len;
1398 if ((*buflen) < struct_len) return -1;
1406 p2 = p + struct_len;
1407 l2 = (*buflen) - struct_len;
1409 if (!baseaddr) baseaddr = p;
1411 StrnCpy(p,lp_servicename(snum),13);
1417 type = STYPE_DISKTREE;
1418 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1419 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1420 SSVAL(p,14,type); /* device type */
1421 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1422 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1427 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1428 SSVALS(p,22,-1); /* max uses */
1429 SSVAL(p,24,1); /* current uses */
1430 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1431 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1432 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1437 memset(p+40,0,SHPWLEN+2);
1449 (*buf) = p + struct_len;
1450 (*buflen) -= struct_len;
1452 (*stringspace) = l2;
1462 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1463 int mdrcnt,int mprcnt,
1464 char **rdata,char **rparam,
1465 int *rdata_len,int *rparam_len)
1467 char *str1 = param+2;
1468 char *str2 = skip_string(str1,1);
1469 char *netname = skip_string(str2,1);
1470 char *p = skip_string(netname,1);
1471 int uLevel = SVAL(p,0);
1472 int snum = find_service(netname);
1474 if (snum < 0) return False;
1476 /* check it's a supported varient */
1477 if (!prefix_ok(str1,"zWrLh")) return False;
1478 if (!check_share_info(uLevel,str2)) return False;
1480 *rdata = REALLOC(*rdata,mdrcnt);
1482 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1483 if (*rdata_len < 0) return False;
1486 *rparam = REALLOC(*rparam,*rparam_len);
1487 SSVAL(*rparam,0,NERR_Success);
1488 SSVAL(*rparam,2,0); /* converter word */
1489 SSVAL(*rparam,4,*rdata_len);
1494 /****************************************************************************
1495 view list of shares available
1496 ****************************************************************************/
1497 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1498 int mdrcnt,int mprcnt,
1499 char **rdata,char **rparam,
1500 int *rdata_len,int *rparam_len)
1502 char *str1 = param+2;
1503 char *str2 = skip_string(str1,1);
1504 char *p = skip_string(str2,1);
1505 int uLevel = SVAL(p,0);
1506 int buf_len = SVAL(p,2);
1508 int count=lp_numservices();
1509 int total=0,counted=0;
1510 BOOL missed = False;
1512 int data_len, fixed_len, string_len;
1513 int f_len = 0, s_len = 0;
1515 if (!prefix_ok(str1,"WrLeh")) return False;
1516 if (!check_share_info(uLevel,str2)) return False;
1518 data_len = fixed_len = string_len = 0;
1519 for (i=0;i<count;i++)
1520 if (lp_browseable(i) && lp_snum_ok(i))
1523 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1524 if (data_len <= buf_len)
1528 string_len += s_len;
1533 *rdata_len = fixed_len + string_len;
1534 *rdata = REALLOC(*rdata,*rdata_len);
1535 memset(*rdata,0,*rdata_len);
1537 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1541 for (i = 0; i < count;i++)
1542 if (lp_browseable(i) && lp_snum_ok(i))
1543 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1547 *rparam = REALLOC(*rparam,*rparam_len);
1548 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1550 SSVAL(*rparam,4,counted);
1551 SSVAL(*rparam,6,total);
1553 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1554 counted,total,uLevel,
1555 buf_len,*rdata_len,mdrcnt));
1561 /****************************************************************************
1562 get the time of day info
1563 ****************************************************************************/
1564 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1565 int mdrcnt,int mprcnt,
1566 char **rdata,char **rparam,
1567 int *rdata_len,int *rparam_len)
1571 *rparam = REALLOC(*rparam,*rparam_len);
1574 *rdata = REALLOC(*rdata,*rdata_len);
1576 SSVAL(*rparam,0,NERR_Success);
1577 SSVAL(*rparam,2,0); /* converter word */
1583 time_t unixdate = time(NULL);
1585 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1586 by NT in a "net time" operation,
1587 it seems to ignore the one below */
1589 /* the client expects to get localtime, not GMT, in this bit
1590 (I think, this needs testing) */
1591 t = LocalTime(&unixdate);
1593 SIVAL(p,4,0); /* msecs ? */
1594 CVAL(p,8) = t->tm_hour;
1595 CVAL(p,9) = t->tm_min;
1596 CVAL(p,10) = t->tm_sec;
1597 CVAL(p,11) = 0; /* hundredths of seconds */
1598 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1599 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1600 CVAL(p,16) = t->tm_mday;
1601 CVAL(p,17) = t->tm_mon + 1;
1602 SSVAL(p,18,1900+t->tm_year);
1603 CVAL(p,20) = t->tm_wday;
1610 /****************************************************************************
1611 set the user password
1612 ****************************************************************************/
1613 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1614 int mdrcnt,int mprcnt,
1615 char **rdata,char **rparam,
1616 int *rdata_len,int *rparam_len)
1618 char *p = skip_string(param+2,2);
1620 fstring pass1,pass2;
1624 p = skip_string(p,1);
1627 memcpy(pass2,p+16,16);
1630 *rparam = REALLOC(*rparam,*rparam_len);
1634 SSVAL(*rparam,0,NERR_badpass);
1635 SSVAL(*rparam,2,0); /* converter word */
1637 DEBUG(3,("Set password for <%s>\n",user));
1640 * Pass the user through the NT -> unix user mapping
1644 (void)map_username(user);
1647 * Do any UNIX username case mangling.
1649 (void)Get_Pwnam( user, True);
1652 * Attempt the plaintext password change first.
1653 * Older versions of Windows seem to do this.
1656 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1657 chgpasswd(user,pass1,pass2,False))
1659 SSVAL(*rparam,0,NERR_Success);
1663 * If the plaintext change failed, attempt
1664 * the encrypted. NT will generate this
1665 * after trying the samr method.
1668 if(SVAL(*rparam,0) != NERR_Success)
1670 struct smb_passwd *sampw = NULL;
1672 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1673 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1675 SSVAL(*rparam,0,NERR_Success);
1679 bzero(pass1,sizeof(fstring));
1680 bzero(pass2,sizeof(fstring));
1685 /****************************************************************************
1686 Set the user password (SamOEM version - gets plaintext).
1687 ****************************************************************************/
1689 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1690 int mdrcnt,int mprcnt,
1691 char **rdata,char **rparam,
1692 int *rdata_len,int *rparam_len)
1695 char *p = param + 2;
1697 *rparam = REALLOC(*rparam,*rparam_len);
1701 SSVAL(*rparam,0,NERR_badpass);
1704 * Check the parameter definition is correct.
1706 if(!strequal(param + 2, "zsT")) {
1707 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1710 p = skip_string(p, 1);
1712 if(!strequal(p, "B516B16")) {
1713 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1716 p = skip_string(p,1);
1719 p = skip_string(p,1);
1721 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1724 * Pass the user through the NT -> unix user mapping
1728 (void)map_username(user);
1731 * Do any UNIX username case mangling.
1733 (void)Get_Pwnam( user, True);
1735 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1737 SSVAL(*rparam,0,NERR_Success);
1743 /****************************************************************************
1746 ****************************************************************************/
1747 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1748 int mdrcnt,int mprcnt,
1749 char **rdata,char **rparam,
1750 int *rdata_len,int *rparam_len)
1752 int function = SVAL(param,0);
1753 char *str1 = param+2;
1754 char *str2 = skip_string(str1,1);
1755 char *p = skip_string(str2,1);
1759 printjob_decode(SVAL(p,0), &snum, &jobid);
1761 /* check it's a supported varient */
1762 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1766 *rparam = REALLOC(*rparam,*rparam_len);
1770 SSVAL(*rparam,0,NERR_Success);
1772 if (snum >= 0 && VALID_SNUM(snum))
1774 print_queue_struct *queue=NULL;
1776 count = get_printqueue(snum,conn,&queue,NULL);
1778 for (i=0;i<count;i++)
1779 if ((queue[i].job&0xFF) == jobid)
1782 case 81: /* delete */
1783 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1784 del_printqueue(conn,snum,queue[i].job);
1786 case 82: /* pause */
1787 case 83: /* resume */
1788 DEBUG(3,("%s queue entry %d\n",
1789 (function==82?"pausing":"resuming"),queue[i].job));
1790 status_printjob(conn,snum,queue[i].job,
1791 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1798 SSVAL(*rparam,0,NERR_JobNotFound);
1800 if (queue) free(queue);
1803 SSVAL(*rparam,2,0); /* converter word */
1808 /****************************************************************************
1809 Purge a print queue - or pause or resume it.
1810 ****************************************************************************/
1811 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1812 int mdrcnt,int mprcnt,
1813 char **rdata,char **rparam,
1814 int *rdata_len,int *rparam_len)
1816 int function = SVAL(param,0);
1817 char *str1 = param+2;
1818 char *str2 = skip_string(str1,1);
1819 char *QueueName = skip_string(str2,1);
1822 /* check it's a supported varient */
1823 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1827 *rparam = REALLOC(*rparam,*rparam_len);
1831 SSVAL(*rparam,0,NERR_Success);
1832 SSVAL(*rparam,2,0); /* converter word */
1834 snum = lp_servicenumber(QueueName);
1835 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1836 int pnum = lp_servicenumber(PRINTERS_NAME);
1838 lp_add_printer(QueueName,pnum);
1839 snum = lp_servicenumber(QueueName);
1843 if (snum >= 0 && VALID_SNUM(snum)) {
1847 case 74: /* Pause queue */
1848 case 75: /* Resume queue */
1849 status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
1850 DEBUG(3,("Print queue %s, queue=%s\n",
1851 (function==74?"pause":"resume"),QueueName));
1853 case 103: /* Purge */
1855 print_queue_struct *queue=NULL;
1857 count = get_printqueue(snum,conn,&queue,NULL);
1858 for (i = 0; i < count; i++)
1859 del_printqueue(conn,snum,queue[i].job);
1861 if (queue) free(queue);
1862 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1872 /****************************************************************************
1873 set the property of a print job (undocumented?)
1874 ? function = 0xb -> set name of print job
1875 ? function = 0x6 -> move print job up/down
1876 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1877 or <WWsTP> <WB21BB16B10zWWzDDz>
1878 ****************************************************************************/
1879 static int check_printjob_info(struct pack_desc* desc,
1880 int uLevel, char* id)
1882 desc->subformat = NULL;
1884 case 0: desc->format = "W"; break;
1885 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1886 case 2: desc->format = "WWzWWDDzz"; break;
1887 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1888 default: return False;
1890 if (strcmp(desc->format,id) != 0) return False;
1894 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1895 int mdrcnt,int mprcnt,
1896 char **rdata,char **rparam,
1897 int *rdata_len,int *rparam_len)
1899 struct pack_desc desc;
1900 char *str1 = param+2;
1901 char *str2 = skip_string(str1,1);
1902 char *p = skip_string(str2,1);
1904 int uLevel = SVAL(p,2);
1905 int function = SVAL(p,4); /* what is this ?? */
1910 printjob_decode(SVAL(p,0), &snum, &jobid);
1913 *rparam = REALLOC(*rparam,*rparam_len);
1917 /* check it's a supported varient */
1918 if ((strcmp(str1,"WWsTP")) ||
1919 (!check_printjob_info(&desc,uLevel,str2)))
1923 case 0x6: /* change job place in the queue,
1924 data gives the new place */
1925 if (snum >= 0 && VALID_SNUM(snum)) {
1926 print_queue_struct *queue=NULL;
1930 count = get_printqueue(snum,conn,&queue,NULL);
1931 for (i=0;i<count;i++) /* find job */
1932 if ((queue[i].job&0xFF) == jobid) break;
1935 desc.errcode=NERR_JobNotFound;
1936 if (queue) free(queue);
1938 desc.errcode=NERR_Success;
1942 int place= SVAL(data,0);
1943 /* we currently have no way of
1944 doing this. Can any unix do it? */
1945 if (i < place) /* move down */;
1946 else if (i > place ) /* move up */;
1949 desc.errcode=NERR_notsupported; /* not yet
1951 if (queue) free(queue);
1954 desc.errcode=NERR_JobNotFound;
1958 case 0xb: /* change print job name, data gives the name */
1959 /* jobid, snum should be zero */
1960 if (isalpha((int)*s)) {
1963 while (l<64 && *s) {
1964 if (issafe(*s)) name[l++] = *s;
1969 DEBUG(3,("Setting print name to %s\n",name));
1971 fsp = file_find_print();
1974 connection_struct *fconn = fsp->conn;
1977 if (!become_user(fconn,vuid) ||
1978 !become_service(fconn,True))
1981 if (dos_rename(fsp->fsp_name,name) == 0) {
1982 string_set(&fsp->fsp_name,name);
1987 desc.errcode=NERR_Success;
1990 default: /* not implemented */
1994 SSVALS(*rparam,0,desc.errcode);
1995 SSVAL(*rparam,2,0); /* converter word */
2001 /****************************************************************************
2002 get info about the server
2003 ****************************************************************************/
2004 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2005 int mdrcnt,int mprcnt,
2006 char **rdata,char **rparam,
2007 int *rdata_len,int *rparam_len)
2009 char *str1 = param+2;
2010 char *str2 = skip_string(str1,1);
2011 char *p = skip_string(str2,1);
2012 int uLevel = SVAL(p,0);
2016 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2018 /* check it's a supported varient */
2019 if (!prefix_ok(str1,"WrLh")) return False;
2022 if (strcmp(str2,"B16") != 0) return False;
2026 if (strcmp(str2,"B16BBDz") != 0) return False;
2030 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2035 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2040 if (strcmp(str2,"DN") != 0) return False;
2044 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2047 default: return False;
2050 *rdata_len = mdrcnt;
2051 *rdata = REALLOC(*rdata,*rdata_len);
2054 p2 = p + struct_len;
2056 StrnCpy(p,local_machine,16);
2062 struct srv_info_struct *servers=NULL;
2065 uint32 servertype= lp_default_server_announce();
2067 pstrcpy(comment,lp_serverstring());
2069 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2070 for (i=0;i<count;i++)
2071 if (strequal(servers[i].name,local_machine))
2073 servertype = servers[i].type;
2074 pstrcpy(comment,servers[i].comment);
2077 if (servers) free(servers);
2079 SCVAL(p,0,lp_major_announce_version());
2080 SCVAL(p,1,lp_minor_announce_version());
2081 SIVAL(p,2,servertype);
2083 if (mdrcnt == struct_len) {
2086 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2087 standard_sub(conn,comment);
2088 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2089 p2 = skip_string(p2,1);
2094 return False; /* not yet implemented */
2097 *rdata_len = PTR_DIFF(p2,*rdata);
2100 *rparam = REALLOC(*rparam,*rparam_len);
2101 SSVAL(*rparam,0,NERR_Success);
2102 SSVAL(*rparam,2,0); /* converter word */
2103 SSVAL(*rparam,4,*rdata_len);
2109 /****************************************************************************
2110 get info about the server
2111 ****************************************************************************/
2112 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2113 int mdrcnt,int mprcnt,
2114 char **rdata,char **rparam,
2115 int *rdata_len,int *rparam_len)
2117 char *str1 = param+2;
2118 char *str2 = skip_string(str1,1);
2119 char *p = skip_string(str2,1);
2121 extern pstring sesssetup_user;
2122 int level = SVAL(p,0);
2124 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2127 *rparam = REALLOC(*rparam,*rparam_len);
2129 /* check it's a supported varient */
2130 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2133 *rdata_len = mdrcnt + 1024;
2134 *rdata = REALLOC(*rdata,*rdata_len);
2136 SSVAL(*rparam,0,NERR_Success);
2137 SSVAL(*rparam,2,0); /* converter word */
2143 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2144 pstrcpy(p2,local_machine);
2146 p2 = skip_string(p2,1);
2149 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2150 pstrcpy(p2,sesssetup_user);
2151 p2 = skip_string(p2,1);
2154 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2155 pstrcpy(p2,global_myworkgroup);
2157 p2 = skip_string(p2,1);
2160 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2161 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2164 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2165 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2166 p2 = skip_string(p2,1);
2169 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2171 p2 = skip_string(p2,1);
2174 *rdata_len = PTR_DIFF(p2,*rdata);
2176 SSVAL(*rparam,4,*rdata_len);
2181 /****************************************************************************
2182 get info about a user
2184 struct user_info_11 {
2185 char usri11_name[21]; 0-20
2187 char *usri11_comment; 22-25
2188 char *usri11_usr_comment; 26-29
2189 unsigned short usri11_priv; 30-31
2190 unsigned long usri11_auth_flags; 32-35
2191 long usri11_password_age; 36-39
2192 char *usri11_homedir; 40-43
2193 char *usri11_parms; 44-47
2194 long usri11_last_logon; 48-51
2195 long usri11_last_logoff; 52-55
2196 unsigned short usri11_bad_pw_count; 56-57
2197 unsigned short usri11_num_logons; 58-59
2198 char *usri11_logon_server; 60-63
2199 unsigned short usri11_country_code; 64-65
2200 char *usri11_workstations; 66-69
2201 unsigned long usri11_max_storage; 70-73
2202 unsigned short usri11_units_per_week; 74-75
2203 unsigned char *usri11_logon_hours; 76-79
2204 unsigned short usri11_code_page; 80-81
2209 usri11_name specifies the user name for which information is retireved
2211 usri11_pad aligns the next data structure element to a word boundary
2213 usri11_comment is a null terminated ASCII comment
2215 usri11_user_comment is a null terminated ASCII comment about the user
2217 usri11_priv specifies the level of the privilege assigned to the user.
2218 The possible values are:
2220 Name Value Description
2221 USER_PRIV_GUEST 0 Guest privilege
2222 USER_PRIV_USER 1 User privilege
2223 USER_PRV_ADMIN 2 Administrator privilege
2225 usri11_auth_flags specifies the account operator privileges. The
2226 possible values are:
2228 Name Value Description
2229 AF_OP_PRINT 0 Print operator
2232 Leach, Naik [Page 28]
\r\f
2235 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2238 AF_OP_COMM 1 Communications operator
2239 AF_OP_SERVER 2 Server operator
2240 AF_OP_ACCOUNTS 3 Accounts operator
2243 usri11_password_age specifies how many seconds have elapsed since the
2244 password was last changed.
2246 usri11_home_dir points to a null terminated ASCII string that contains
2247 the path name of the user's home directory.
2249 usri11_parms points to a null terminated ASCII string that is set
2250 aside for use by applications.
2252 usri11_last_logon specifies the time when the user last logged on.
2253 This value is stored as the number of seconds elapsed since
2254 00:00:00, January 1, 1970.
2256 usri11_last_logoff specifies the time when the user last logged off.
2257 This value is stored as the number of seconds elapsed since
2258 00:00:00, January 1, 1970. A value of 0 means the last logoff
2261 usri11_bad_pw_count specifies the number of incorrect passwords
2262 entered since the last successful logon.
2264 usri11_log1_num_logons specifies the number of times this user has
2265 logged on. A value of -1 means the number of logons is unknown.
2267 usri11_logon_server points to a null terminated ASCII string that
2268 contains the name of the server to which logon requests are sent.
2269 A null string indicates logon requests should be sent to the
2272 usri11_country_code specifies the country code for the user's language
2275 usri11_workstations points to a null terminated ASCII string that
2276 contains the names of workstations the user may log on from.
2277 There may be up to 8 workstations, with the names separated by
2278 commas. A null strings indicates there are no restrictions.
2280 usri11_max_storage specifies the maximum amount of disk space the user
2281 can occupy. A value of 0xffffffff indicates there are no
2284 usri11_units_per_week specifies the equal number of time units into
2285 which a week is divided. This value must be equal to 168.
2287 usri11_logon_hours points to a 21 byte (168 bits) string that
2288 specifies the time during which the user can log on. Each bit
2289 represents one unique hour in a week. The first bit (bit 0, word
2290 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2294 Leach, Naik [Page 29]
\r\f
2297 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2300 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2301 are no restrictions.
2303 usri11_code_page specifies the code page for the user's language of
2306 All of the pointers in this data structure need to be treated
2307 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2308 to be ignored. The converter word returned in the parameters section
2309 needs to be subtracted from the lower 16 bits to calculate an offset
2310 into the return buffer where this ASCII string resides.
2312 There is no auxiliary data in the response.
2314 ****************************************************************************/
2316 #define usri11_name 0
2317 #define usri11_pad 21
2318 #define usri11_comment 22
2319 #define usri11_usr_comment 26
2320 #define usri11_full_name 30
2321 #define usri11_priv 34
2322 #define usri11_auth_flags 36
2323 #define usri11_password_age 40
2324 #define usri11_homedir 44
2325 #define usri11_parms 48
2326 #define usri11_last_logon 52
2327 #define usri11_last_logoff 56
2328 #define usri11_bad_pw_count 60
2329 #define usri11_num_logons 62
2330 #define usri11_logon_server 64
2331 #define usri11_country_code 68
2332 #define usri11_workstations 70
2333 #define usri11_max_storage 74
2334 #define usri11_units_per_week 78
2335 #define usri11_logon_hours 80
2336 #define usri11_code_page 84
2337 #define usri11_end 86
2339 #define USER_PRIV_GUEST 0
2340 #define USER_PRIV_USER 1
2341 #define USER_PRIV_ADMIN 2
2343 #define AF_OP_PRINT 0
2344 #define AF_OP_COMM 1
2345 #define AF_OP_SERVER 2
2346 #define AF_OP_ACCOUNTS 3
2349 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2350 int mdrcnt,int mprcnt,
2351 char **rdata,char **rparam,
2352 int *rdata_len,int *rparam_len)
2354 char *str1 = param+2;
2355 char *str2 = skip_string(str1,1);
2356 char *UserName = skip_string(str2,1);
2357 char *p = skip_string(UserName,1);
2358 int uLevel = SVAL(p,0);
2361 /* get NIS home of a previously validated user - simeon */
2362 /* With share level security vuid will always be zero.
2363 Don't depend on vuser being non-null !!. JRA */
2364 user_struct *vuser = get_valid_user_struct(vuid);
2366 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name));
2369 *rparam = REALLOC(*rparam,*rparam_len);
2371 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2373 /* check it's a supported variant */
2374 if (strcmp(str1,"zWrLh") != 0) return False;
2377 case 0: p2 = "B21"; break;
2378 case 1: p2 = "B21BB16DWzzWz"; break;
2379 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2380 case 10: p2 = "B21Bzzz"; break;
2381 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2382 default: return False;
2385 if (strcmp(p2,str2) != 0) return False;
2387 *rdata_len = mdrcnt + 1024;
2388 *rdata = REALLOC(*rdata,*rdata_len);
2390 SSVAL(*rparam,0,NERR_Success);
2391 SSVAL(*rparam,2,0); /* converter word */
2394 p2 = p + usri11_end;
2397 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2401 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2406 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2407 pstrcpy(p2,"Comment");
2408 p2 = skip_string(p2,1);
2410 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2411 pstrcpy(p2,"UserComment");
2412 p2 = skip_string(p2,1);
2414 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2415 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2416 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2417 p2 = skip_string(p2,1);
2420 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2422 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2423 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2424 SIVALS(p,usri11_password_age,-1); /* password age */
2425 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2426 pstrcpy(p2, lp_logon_path());
2427 p2 = skip_string(p2,1);
2428 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2430 p2 = skip_string(p2,1);
2431 SIVAL(p,usri11_last_logon,0); /* last logon */
2432 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2433 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2434 SSVALS(p,usri11_num_logons,-1); /* num logons */
2435 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2436 pstrcpy(p2,"\\\\*");
2437 p2 = skip_string(p2,1);
2438 SSVAL(p,usri11_country_code,0); /* country code */
2440 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2442 p2 = skip_string(p2,1);
2444 SIVALS(p,usri11_max_storage,-1); /* max storage */
2445 SSVAL(p,usri11_units_per_week,168); /* units per week */
2446 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2448 /* a simple way to get logon hours at all times. */
2450 SCVAL(p2,21,0); /* fix zero termination */
2451 p2 = skip_string(p2,1);
2453 SSVAL(p,usri11_code_page,0); /* code page */
2455 if (uLevel == 1 || uLevel == 2)
2457 memset(p+22,' ',16); /* password */
2458 SIVALS(p,38,-1); /* password age */
2460 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2461 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2462 pstrcpy(p2,lp_logon_path());
2463 p2 = skip_string(p2,1);
2464 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2466 SSVAL(p,52,0); /* flags */
2467 SIVAL(p,54,0); /* script_path */
2470 SIVAL(p,60,0); /* auth_flags */
2471 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2472 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2473 p2 = skip_string(p2,1);
2474 SIVAL(p,68,0); /* urs_comment */
2475 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2477 p2 = skip_string(p2,1);
2478 SIVAL(p,76,0); /* workstations */
2479 SIVAL(p,80,0); /* last_logon */
2480 SIVAL(p,84,0); /* last_logoff */
2481 SIVALS(p,88,-1); /* acct_expires */
2482 SIVALS(p,92,-1); /* max_storage */
2483 SSVAL(p,96,168); /* units_per_week */
2484 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2487 SSVALS(p,102,-1); /* bad_pw_count */
2488 SSVALS(p,104,-1); /* num_logons */
2489 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2490 pstrcpy(p2,"\\\\%L");
2491 standard_sub_basic(p2);
2492 p2 = skip_string(p2,1);
2493 SSVAL(p,110,49); /* country_code */
2494 SSVAL(p,112,860); /* code page */
2498 *rdata_len = PTR_DIFF(p2,*rdata);
2500 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2505 /*******************************************************************
2506 get groups that a user is a member of
2507 ******************************************************************/
2508 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2509 int mdrcnt,int mprcnt,
2510 char **rdata,char **rparam,
2511 int *rdata_len,int *rparam_len)
2513 char *str1 = param+2;
2514 char *str2 = skip_string(str1,1);
2515 char *UserName = skip_string(str2,1);
2516 char *p = skip_string(UserName,1);
2517 int uLevel = SVAL(p,0);
2522 *rparam = REALLOC(*rparam,*rparam_len);
2524 /* check it's a supported varient */
2525 if (strcmp(str1,"zWrLeh") != 0) return False;
2527 case 0: p2 = "B21"; break;
2528 default: return False;
2530 if (strcmp(p2,str2) != 0) return False;
2532 *rdata_len = mdrcnt + 1024;
2533 *rdata = REALLOC(*rdata,*rdata_len);
2535 SSVAL(*rparam,0,NERR_Success);
2536 SSVAL(*rparam,2,0); /* converter word */
2540 /* XXXX we need a real SAM database some day */
2541 pstrcpy(p,"Users"); p += 21; count++;
2542 pstrcpy(p,"Domain Users"); p += 21; count++;
2543 pstrcpy(p,"Guests"); p += 21; count++;
2544 pstrcpy(p,"Domain Guests"); p += 21; count++;
2546 *rdata_len = PTR_DIFF(p,*rdata);
2548 SSVAL(*rparam,4,count); /* is this right?? */
2549 SSVAL(*rparam,6,count); /* is this right?? */
2555 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2556 int mdrcnt,int mprcnt,
2557 char **rdata,char **rparam,
2558 int *rdata_len,int *rparam_len)
2560 char *str1 = param+2;
2561 char *str2 = skip_string(str1,1);
2562 char *p = skip_string(str2,1);
2564 struct pack_desc desc;
2571 bzero(&desc,sizeof(desc));
2573 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2575 /* check it's a supported varient */
2576 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2577 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2578 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2580 desc.buflen = mdrcnt;
2581 desc.subformat = NULL;
2584 if (init_package(&desc,1,0))
2586 PACKI(&desc,"W",0); /* code */
2587 PACKS(&desc,"B21",name); /* eff. name */
2588 PACKS(&desc,"B",""); /* pad */
2590 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2591 PACKI(&desc,"D",0); /* auth flags XXX */
2592 PACKI(&desc,"W",0); /* num logons */
2593 PACKI(&desc,"W",0); /* bad pw count */
2594 PACKI(&desc,"D",0); /* last logon */
2595 PACKI(&desc,"D",-1); /* last logoff */
2596 PACKI(&desc,"D",-1); /* logoff time */
2597 PACKI(&desc,"D",-1); /* kickoff time */
2598 PACKI(&desc,"D",0); /* password age */
2599 PACKI(&desc,"D",0); /* password can change */
2600 PACKI(&desc,"D",-1); /* password must change */
2603 fstrcpy(mypath,"\\\\");
2604 fstrcat(mypath,local_machine);
2606 PACKS(&desc,"z",mypath); /* computer */
2608 PACKS(&desc,"z",global_myworkgroup);/* domain */
2610 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2611 /* made sure all macros are fully substituted and available */
2612 logon_script = lp_logon_script();
2613 standard_sub( conn, logon_script );
2614 PACKS(&desc,"z", logon_script); /* script path */
2615 /* End of JHT mods */
2617 PACKI(&desc,"D",0x00000000); /* reserved */
2620 *rdata_len = desc.usedlen;
2622 *rparam = REALLOC(*rparam,*rparam_len);
2623 SSVALS(*rparam,0,desc.errcode);
2625 SSVAL(*rparam,4,desc.neededlen);
2627 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2632 /****************************************************************************
2633 api_WAccessGetUserPerms
2634 ****************************************************************************/
2635 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2636 int mdrcnt,int mprcnt,
2637 char **rdata,char **rparam,
2638 int *rdata_len,int *rparam_len)
2640 char *str1 = param+2;
2641 char *str2 = skip_string(str1,1);
2642 char *user = skip_string(str2,1);
2643 char *resource = skip_string(user,1);
2645 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2647 /* check it's a supported varient */
2648 if (strcmp(str1,"zzh") != 0) return False;
2649 if (strcmp(str2,"") != 0) return False;
2652 *rparam = REALLOC(*rparam,*rparam_len);
2653 SSVALS(*rparam,0,0); /* errorcode */
2654 SSVAL(*rparam,2,0); /* converter word */
2655 SSVAL(*rparam,4,0x7f); /* permission flags */
2660 /****************************************************************************
2661 api_WPrintJobEnumerate
2662 ****************************************************************************/
2663 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2664 int mdrcnt,int mprcnt,
2665 char **rdata,char **rparam,
2666 int *rdata_len,int *rparam_len)
2668 char *str1 = param+2;
2669 char *str2 = skip_string(str1,1);
2670 char *p = skip_string(str2,1);
2676 struct pack_desc desc;
2677 print_queue_struct *queue=NULL;
2678 print_status_struct status;
2682 bzero(&desc,sizeof(desc));
2683 bzero(&status,sizeof(status));
2685 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2687 /* check it's a supported varient */
2688 if (strcmp(str1,"WWrLh") != 0) return False;
2689 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2691 printjob_decode(SVAL(p,0), &snum, &job);
2693 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2695 count = get_printqueue(snum,conn,&queue,&status);
2696 for (i = 0; i < count; i++) {
2697 if ((queue[i].job & 0xFF) == job) break;
2699 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2701 desc.buflen = mdrcnt;
2703 if (init_package(&desc,1,0)) {
2705 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2706 *rdata_len = desc.usedlen;
2709 desc.errcode = NERR_JobNotFound;
2715 *rparam = REALLOC(*rparam,*rparam_len);
2716 SSVALS(*rparam,0,desc.errcode);
2718 SSVAL(*rparam,4,desc.neededlen);
2720 if (queue) free(queue);
2722 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2726 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2727 int mdrcnt,int mprcnt,
2728 char **rdata,char **rparam,
2729 int *rdata_len,int *rparam_len)
2731 char *str1 = param+2;
2732 char *str2 = skip_string(str1,1);
2733 char *p = skip_string(str2,1);
2739 struct pack_desc desc;
2740 print_queue_struct *queue=NULL;
2741 print_status_struct status;
2743 bzero(&desc,sizeof(desc));
2744 bzero(&status,sizeof(status));
2746 p = skip_string(p,1);
2749 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2751 /* check it's a supported varient */
2752 if (strcmp(str1,"zWrLeh") != 0) return False;
2753 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2754 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2756 snum = lp_servicenumber(name);
2757 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2758 int pnum = lp_servicenumber(PRINTERS_NAME);
2760 lp_add_printer(name,pnum);
2761 snum = lp_servicenumber(name);
2765 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2767 count = get_printqueue(snum,conn,&queue,&status);
2768 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2770 desc.buflen = mdrcnt;
2772 if (init_package(&desc,count,0)) {
2774 for (i = 0; i < count; i++) {
2775 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2776 if (desc.errcode == NERR_Success) succnt = i+1;
2780 *rdata_len = desc.usedlen;
2783 *rparam = REALLOC(*rparam,*rparam_len);
2784 SSVALS(*rparam,0,desc.errcode);
2786 SSVAL(*rparam,4,succnt);
2787 SSVAL(*rparam,6,count);
2789 if (queue) free(queue);
2791 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2795 static int check_printdest_info(struct pack_desc* desc,
2796 int uLevel, char* id)
2798 desc->subformat = NULL;
2800 case 0: desc->format = "B9"; break;
2801 case 1: desc->format = "B9B21WWzW"; break;
2802 case 2: desc->format = "z"; break;
2803 case 3: desc->format = "zzzWWzzzWW"; break;
2804 default: return False;
2806 if (strcmp(desc->format,id) != 0) return False;
2810 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2811 struct pack_desc* desc)
2814 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2815 buf[sizeof(buf)-1] = 0;
2818 PACKS(desc,"B9",buf); /* szName */
2820 PACKS(desc,"B21",""); /* szUserName */
2821 PACKI(desc,"W",0); /* uJobId */
2822 PACKI(desc,"W",0); /* fsStatus */
2823 PACKS(desc,"z",""); /* pszStatus */
2824 PACKI(desc,"W",0); /* time */
2827 if (uLevel == 2 || uLevel == 3) {
2828 PACKS(desc,"z",buf); /* pszPrinterName */
2830 PACKS(desc,"z",""); /* pszUserName */
2831 PACKS(desc,"z",""); /* pszLogAddr */
2832 PACKI(desc,"W",0); /* uJobId */
2833 PACKI(desc,"W",0); /* fsStatus */
2834 PACKS(desc,"z",""); /* pszStatus */
2835 PACKS(desc,"z",""); /* pszComment */
2836 PACKS(desc,"z","NULL"); /* pszDrivers */
2837 PACKI(desc,"W",0); /* time */
2838 PACKI(desc,"W",0); /* pad1 */
2843 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2844 int mdrcnt,int mprcnt,
2845 char **rdata,char **rparam,
2846 int *rdata_len,int *rparam_len)
2848 char *str1 = param+2;
2849 char *str2 = skip_string(str1,1);
2850 char *p = skip_string(str2,1);
2851 char* PrinterName = p;
2853 struct pack_desc desc;
2856 bzero(&desc,sizeof(desc));
2858 p = skip_string(p,1);
2861 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2863 /* check it's a supported varient */
2864 if (strcmp(str1,"zWrLh") != 0) return False;
2865 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2867 snum = lp_servicenumber(PrinterName);
2868 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2869 int pnum = lp_servicenumber(PRINTERS_NAME);
2871 lp_add_printer(PrinterName,pnum);
2872 snum = lp_servicenumber(PrinterName);
2878 desc.errcode = NERR_DestNotFound;
2882 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2884 desc.buflen = mdrcnt;
2885 if (init_package(&desc,1,0)) {
2886 fill_printdest_info(conn,snum,uLevel,&desc);
2888 *rdata_len = desc.usedlen;
2892 *rparam = REALLOC(*rparam,*rparam_len);
2893 SSVALS(*rparam,0,desc.errcode);
2895 SSVAL(*rparam,4,desc.neededlen);
2897 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2901 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2902 int mdrcnt,int mprcnt,
2903 char **rdata,char **rparam,
2904 int *rdata_len,int *rparam_len)
2906 char *str1 = param+2;
2907 char *str2 = skip_string(str1,1);
2908 char *p = skip_string(str2,1);
2912 struct pack_desc desc;
2913 int services = lp_numservices();
2915 bzero(&desc,sizeof(desc));
2919 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2921 /* check it's a supported varient */
2922 if (strcmp(str1,"WrLeh") != 0) return False;
2923 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2926 for (i = 0; i < services; i++)
2927 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2930 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2932 desc.buflen = mdrcnt;
2933 if (init_package(&desc,queuecnt,0)) {
2936 for (i = 0; i < services; i++) {
2937 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2938 fill_printdest_info(conn,i,uLevel,&desc);
2940 if (desc.errcode == NERR_Success) succnt = n;
2945 *rdata_len = desc.usedlen;
2948 *rparam = REALLOC(*rparam,*rparam_len);
2949 SSVALS(*rparam,0,desc.errcode);
2951 SSVAL(*rparam,4,succnt);
2952 SSVAL(*rparam,6,queuecnt);
2954 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2958 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2959 int mdrcnt,int mprcnt,
2960 char **rdata,char **rparam,
2961 int *rdata_len,int *rparam_len)
2963 char *str1 = param+2;
2964 char *str2 = skip_string(str1,1);
2965 char *p = skip_string(str2,1);
2968 struct pack_desc desc;
2970 bzero(&desc,sizeof(desc));
2974 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2976 /* check it's a supported varient */
2977 if (strcmp(str1,"WrLeh") != 0) return False;
2978 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2980 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2982 desc.buflen = mdrcnt;
2983 if (init_package(&desc,1,0)) {
2984 PACKS(&desc,"B41","NULL");
2987 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2989 *rdata_len = desc.usedlen;
2992 *rparam = REALLOC(*rparam,*rparam_len);
2993 SSVALS(*rparam,0,desc.errcode);
2995 SSVAL(*rparam,4,succnt);
2998 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3002 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3003 int mdrcnt,int mprcnt,
3004 char **rdata,char **rparam,
3005 int *rdata_len,int *rparam_len)
3007 char *str1 = param+2;
3008 char *str2 = skip_string(str1,1);
3009 char *p = skip_string(str2,1);
3012 struct pack_desc desc;
3014 bzero(&desc,sizeof(desc));
3018 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3020 /* check it's a supported varient */
3021 if (strcmp(str1,"WrLeh") != 0) return False;
3022 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3024 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3026 desc.buflen = mdrcnt;
3028 if (init_package(&desc,1,0)) {
3029 PACKS(&desc,"B13","lpd");
3032 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3034 *rdata_len = desc.usedlen;
3037 *rparam = REALLOC(*rparam,*rparam_len);
3038 SSVALS(*rparam,0,desc.errcode);
3040 SSVAL(*rparam,4,succnt);
3043 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3047 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3048 int mdrcnt,int mprcnt,
3049 char **rdata,char **rparam,
3050 int *rdata_len,int *rparam_len)
3052 char *str1 = param+2;
3053 char *str2 = skip_string(str1,1);
3054 char *p = skip_string(str2,1);
3057 struct pack_desc desc;
3059 bzero(&desc,sizeof(desc));
3063 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3065 /* check it's a supported varient */
3066 if (strcmp(str1,"WrLeh") != 0) return False;
3067 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3069 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3070 bzero(&desc,sizeof(desc));
3072 desc.buflen = mdrcnt;
3074 if (init_package(&desc,1,0)) {
3075 PACKS(&desc,"B13","lp0");
3078 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3080 *rdata_len = desc.usedlen;
3083 *rparam = REALLOC(*rparam,*rparam_len);
3084 SSVALS(*rparam,0,desc.errcode);
3086 SSVAL(*rparam,4,succnt);
3089 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3093 static void api_rpc_trans_reply(char *outbuf,
3097 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
3099 if (mem_buf_len(p->rhdr.data) <= p->file_offset)
3101 /* all of data was sent: no need to wait for SMBreadX calls */
3102 mem_free_data(p->rhdr .data);
3103 mem_free_data(p->rdata.data);
3104 mem_free_data(p->rdata_i.data);
3108 /****************************************************************************
3109 WaitNamedPipeHandleState
3110 ****************************************************************************/
3111 static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param)
3115 if (!param) return False;
3117 priority = param[0] + (param[1] << 8);
3118 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
3120 if (wait_rpc_pipe_hnd_state(p, priority))
3122 /* now send the reply */
3123 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3131 /****************************************************************************
3132 SetNamedPipeHandleState
3133 ****************************************************************************/
3134 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3138 if (!param) return False;
3140 id = param[0] + (param[1] << 8);
3141 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
3143 if (set_rpc_pipe_hnd_state(p, id))
3145 /* now send the reply */
3146 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3154 /****************************************************************************
3155 when no reply is generated, indicate unsupported.
3156 ****************************************************************************/
3157 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3159 struct mem_buf rparam;
3161 mem_init(&rparam, 0);
3162 mem_alloc_data(&rparam, 4);
3164 rparam.offset.start = 0;
3165 rparam.offset.end = 4;
3168 SSVAL(rparam.data,0,NERR_notsupported);
3169 SSVAL(rparam.data,2,0); /* converter word */
3171 DEBUG(3,("Unsupported API fd command\n"));
3173 /* now send the reply */
3174 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3176 mem_free_data(&rparam);
3181 /****************************************************************************
3182 handle remote api calls delivered to a named pipe already opened.
3183 ****************************************************************************/
3184 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
3185 uint16 *setup,char *data,char *params,
3186 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3192 pipes_struct *p = NULL;
3195 DEBUG(5,("api_fd_reply\n"));
3197 /* make a static data parsing structure from the api_fd_reply data */
3198 prs_init(&pd, 0, 4, 0, True);
3199 mem_create(pd.data, data, 0, tdscnt, 0, False);
3201 /* First find out the name of this file. */
3204 DEBUG(0,("Unexpected named pipe transaction.\n"));
3208 /* Get the file handle and hence the file name. */
3210 subcommand = setup[0];
3211 p = get_rpc_pipe(pnum);
3215 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3216 subcommand, p->name, pnum));
3218 /* record maximum data length that can be transmitted in an SMBtrans */
3219 p->file_offset = mdrcnt;
3221 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3222 p, p->file_offset));
3228 /* dce/rpc command */
3229 reply = rpc_command(p, &pd);
3232 api_rpc_trans_reply(outbuf, p, &pd);
3238 /* Wait Named Pipe Handle state */
3239 reply = api_WNPHS(outbuf, p, params);
3244 /* Set Named Pipe Handle state */
3245 reply = api_SNPHS(outbuf, p, params);
3252 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3255 mem_free_data(pd.data);
3259 return api_no_reply(outbuf, mdrcnt);
3264 /****************************************************************************
3265 the buffer was too small
3266 ****************************************************************************/
3267 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3268 int mdrcnt,int mprcnt,
3269 char **rdata,char **rparam,
3270 int *rdata_len,int *rparam_len)
3272 *rparam_len = MIN(*rparam_len,mprcnt);
3273 *rparam = REALLOC(*rparam,*rparam_len);
3277 SSVAL(*rparam,0,NERR_BufTooSmall);
3279 DEBUG(3,("Supplied buffer too small in API command\n"));
3285 /****************************************************************************
3286 the request is not supported
3287 ****************************************************************************/
3288 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3289 int mdrcnt,int mprcnt,
3290 char **rdata,char **rparam,
3291 int *rdata_len,int *rparam_len)
3294 *rparam = REALLOC(*rparam,*rparam_len);
3298 SSVAL(*rparam,0,NERR_notsupported);
3299 SSVAL(*rparam,2,0); /* converter word */
3301 DEBUG(3,("Unsupported API command\n"));
3313 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3314 int,int,char **,char **,int *,int *);
3316 } api_commands[] = {
3317 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3318 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3319 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3320 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3321 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3322 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3323 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3324 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3325 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3326 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3327 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3328 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3329 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3330 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3331 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3332 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3333 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3334 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3335 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3336 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3337 {"NetServerEnum", 104, api_RNetServerEnum,0},
3338 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3339 {"SetUserPassword", 115, api_SetUserPassword,0},
3340 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3341 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3342 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3343 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3344 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3345 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3346 {NULL, -1, api_Unsupported,0}};
3349 /****************************************************************************
3350 handle remote api calls
3351 ****************************************************************************/
3352 static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3353 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3356 struct mem_buf rdata_buf;
3357 struct mem_buf rparam_buf;
3359 char *rparam = NULL;
3365 SMB_ASSERT(params != 0);
3367 api_command = SVAL(params,0);
3369 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3372 skip_string(params+2,1),
3373 tdscnt,tpscnt,mdrcnt,mprcnt));
3375 for (i=0;api_commands[i].name;i++)
3376 if (api_commands[i].id == api_command && api_commands[i].fn)
3378 DEBUG(3,("Doing %s\n",api_commands[i].name));
3382 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3383 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3385 if(!rdata || !rparam) {
3386 DEBUG(0,("api_reply: malloc fail !\n"));
3390 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3391 &rdata,&rparam,&rdata_len,&rparam_len);
3394 if (rdata_len > mdrcnt ||
3395 rparam_len > mprcnt)
3397 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3398 &rdata,&rparam,&rdata_len,&rparam_len);
3402 /* if we get False back then it's actually unsupported */
3404 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3405 &rdata,&rparam,&rdata_len,&rparam_len);
3408 mem_create(&rdata_buf , rdata , 0, rdata_len , 0, False);
3409 mem_create(&rparam_buf, rparam, 0, rparam_len, 0, False);
3411 /* now send the reply */
3412 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3414 if (rdata ) free(rdata);
3415 if (rparam) free(rparam);
3420 /****************************************************************************
3421 handle named pipe commands
3422 ****************************************************************************/
3423 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
3424 uint16 *setup,char *data,char *params,
3425 int suwcnt,int tdscnt,int tpscnt,
3426 int msrcnt,int mdrcnt,int mprcnt)
3428 DEBUG(3,("named pipe command on <%s> name\n", name));
3430 if (strequal(name,"LANMAN"))
3432 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3435 if (strequal(name,"WKSSVC") ||
3436 strequal(name,"SRVSVC") ||
3437 strequal(name,"WINREG") ||
3438 strequal(name,"SAMR") ||
3439 strequal(name,"LSARPC"))
3441 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
3442 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3445 if (strlen(name) < 1)
3447 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3452 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3459 /****************************************************************************
3461 ****************************************************************************/
3462 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
3465 int name_offset = 0;
3466 char *data=NULL,*params=NULL;
3469 uint16 vuid = SVAL(inbuf,smb_uid);
3470 int tpscnt = SVAL(inbuf,smb_vwv0);
3471 int tdscnt = SVAL(inbuf,smb_vwv1);
3472 int mprcnt = SVAL(inbuf,smb_vwv2);
3473 int mdrcnt = SVAL(inbuf,smb_vwv3);
3474 int msrcnt = CVAL(inbuf,smb_vwv4);
3475 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3476 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3477 int pscnt = SVAL(inbuf,smb_vwv9);
3478 int psoff = SVAL(inbuf,smb_vwv10);
3479 int dscnt = SVAL(inbuf,smb_vwv11);
3480 int dsoff = SVAL(inbuf,smb_vwv12);
3481 int suwcnt = CVAL(inbuf,smb_vwv13);
3483 bzero(name, sizeof(name));
3484 fstrcpy(name,smb_buf(inbuf));
3486 if (dscnt > tdscnt || pscnt > tpscnt) {
3487 exit_server("invalid trans parameters\n");
3491 if((data = (char *)malloc(tdscnt)) == NULL) {
3492 DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt));
3493 return(ERROR(ERRDOS,ERRnomem));
3495 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3499 if((params = (char *)malloc(tpscnt)) == NULL) {
3500 DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt));
3501 return(ERROR(ERRDOS,ERRnomem));
3503 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3508 if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
3509 DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", suwcnt * sizeof(uint16)));
3510 return(ERROR(ERRDOS,ERRnomem));
3512 for (i=0;i<suwcnt;i++)
3513 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3517 if (pscnt < tpscnt || dscnt < tdscnt) {
3518 /* We need to send an interim response then receive the rest
3519 of the parameter/data bytes */
3520 outsize = set_message(outbuf,0,0,True);
3522 send_smb(Client,outbuf);
3525 /* receive the rest of the trans packet */
3526 while (pscnt < tpscnt || dscnt < tdscnt) {
3528 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3530 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3532 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) {
3534 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3536 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3537 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3539 if (params) free(params);
3540 if (data) free(data);
3541 if (setup) free(setup);
3542 return(ERROR(ERRSRV,ERRerror));
3547 tpscnt = SVAL(inbuf,smb_vwv0);
3548 tdscnt = SVAL(inbuf,smb_vwv1);
3550 pcnt = SVAL(inbuf,smb_vwv2);
3551 poff = SVAL(inbuf,smb_vwv3);
3552 pdisp = SVAL(inbuf,smb_vwv4);
3554 dcnt = SVAL(inbuf,smb_vwv5);
3555 doff = SVAL(inbuf,smb_vwv6);
3556 ddisp = SVAL(inbuf,smb_vwv7);
3561 if (dscnt > tdscnt || pscnt > tpscnt) {
3562 exit_server("invalid trans parameters\n");
3566 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3568 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3572 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3573 name,tdscnt,tpscnt,suwcnt));
3576 * WinCE wierdness....
3579 if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine,
3580 strlen(local_machine)) == 0)) {
3581 name_offset = strlen(local_machine)+1;
3584 if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3585 DEBUG(5,("calling named_pipe\n"));
3586 outsize = named_pipe(conn,vuid,outbuf,
3587 name+name_offset+strlen("\\PIPE\\"),setup,data,params,
3588 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3590 DEBUG(3,("invalid pipe name\n"));
3595 if (data) free(data);
3596 if (params) free(params);
3597 if (setup) free(setup);
3599 if (close_on_completion)
3600 close_cnum(conn,vuid);
3606 return(ERROR(ERRSRV,ERRnosupport));