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
36 extern fstring local_machine;
37 extern pstring global_myname;
38 extern fstring global_myworkgroup;
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)
49 #define ACCESS_READ 0x01
50 #define ACCESS_WRITE 0x02
51 #define ACCESS_CREATE 0x04
53 #define SHPWLEN 8 /* share password length */
55 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
56 int mdrcnt,int mprcnt,
57 char **rdata,char **rparam,
58 int *rdata_len,int *rparam_len);
59 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
60 int mdrcnt,int mprcnt,
61 char **rdata,char **rparam,
62 int *rdata_len,int *rparam_len);
65 static int CopyExpanded(connection_struct *conn,
66 int snum, char** dst, char* src, int* n)
71 if (!src || !dst || !n || !(*dst)) return(0);
73 StrnCpy(buf,src,sizeof(buf)/2);
74 pstring_sub(buf,"%S",lp_servicename(snum));
75 standard_sub_conn(conn,buf);
76 l = push_ascii(*dst,buf,*n-1, STR_TERMINATE);
82 static int CopyAndAdvance(char** dst, char* src, int* n)
85 if (!src || !dst || !n || !(*dst)) return(0);
86 l = push_ascii(*dst,src,*n-1, STR_TERMINATE);
92 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
96 StrnCpy(buf,s,sizeof(buf)/2);
97 pstring_sub(buf,"%S",lp_servicename(snum));
98 standard_sub_conn(conn,buf);
99 return strlen(buf) + 1;
102 static char* Expand(connection_struct *conn, int snum, char* s)
105 if (!s) return(NULL);
106 StrnCpy(buf,s,sizeof(buf)/2);
107 pstring_sub(buf,"%S",lp_servicename(snum));
108 standard_sub_conn(conn,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 char* format; /* formatstring for structure */
122 char* subformat; /* subformat for structure */
123 char* base; /* baseaddress of buffer */
124 int buflen; /* remaining size for fixed part; on init: length of base */
125 int subcount; /* count of substructures */
126 char* structbuf; /* pointer into buffer for remaining fixed part */
127 int stringlen; /* remaining size for variable part */
128 char* stringbuf; /* pointer into buffer for remaining variable part */
129 int neededlen; /* total needed size */
130 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
131 char* curpos; /* current position; pointer into format or subformat */
135 static int get_counter(char** p)
138 if (!p || !(*p)) return(1);
139 if (!isdigit((int)**p)) return 1;
143 n = 10 * n + (i - '0');
150 static int getlen(char* p)
156 case 'W': /* word (2 byte) */
159 case 'K': /* status word? (2 byte) */
162 case 'N': /* count of substructures (word) at end */
165 case 'D': /* double word (4 byte) */
166 case 'z': /* offset to zero terminated string (4 byte) */
167 case 'l': /* offset to user data (4 byte) */
170 case 'b': /* offset to data (with counter) (4 byte) */
174 case 'B': /* byte (with optional counter) */
175 n += get_counter(&p);
182 static BOOL init_package(struct pack_desc* p, int count, int subcount)
187 if (!p->format || !p->base) return(False);
189 i = count * getlen(p->format);
190 if (p->subformat) i += subcount * getlen(p->subformat);
191 p->structbuf = p->base;
195 p->curpos = p->format;
201 * This is the old error code we used. Aparently
202 * WinNT/2k systems return ERRbuftoosmall (2123) and
203 * OS/2 needs this. I'm leaving this here so we can revert
206 p->errcode = ERRmoredata;
208 p->errcode = ERRbuftoosmall;
212 p->errcode = NERR_Success;
215 p->stringbuf = p->base + i;
217 return(p->errcode == NERR_Success);
220 static int package(struct pack_desc* p, ...)
223 int needed=0, stringneeded;
225 int is_string=0, stringused;
232 p->curpos = p->format;
234 p->curpos = p->subformat;
239 str = va_arg(args,char*);
240 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
249 switch( *p->curpos++ ) {
250 case 'W': /* word (2 byte) */
252 temp = va_arg(args,int);
253 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
255 case 'K': /* status word? (2 byte) */
257 temp = va_arg(args,int);
258 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
260 case 'N': /* count of substructures (word) at end */
262 p->subcount = va_arg(args,int);
263 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
265 case 'D': /* double word (4 byte) */
267 temp = va_arg(args,int);
268 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
270 case 'B': /* byte (with optional counter) */
271 needed = get_counter(&p->curpos);
273 char *s = va_arg(args,char*);
274 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
277 case 'z': /* offset to zero terminated string (4 byte) */
278 str = va_arg(args,char*);
279 stringneeded = (str ? strlen(str)+1 : 0);
282 case 'l': /* offset to user data (4 byte) */
283 str = va_arg(args,char*);
284 stringneeded = va_arg(args,int);
287 case 'b': /* offset to data (with counter) (4 byte) */
288 str = va_arg(args,char*);
289 stringneeded = get_counter(&p->curpos);
294 if (stringneeded >= 0) {
296 if (p->buflen >= needed) {
297 stringused = stringneeded;
298 if (stringused > p->stringlen) {
299 stringused = (is_string ? p->stringlen : 0);
300 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
303 SIVAL(p->structbuf,0,0);
305 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
306 memcpy(p->stringbuf,str?str:"",stringused);
307 if (is_string) p->stringbuf[stringused-1] = '\0';
308 p->stringbuf += stringused;
309 p->stringlen -= stringused;
310 p->usedlen += stringused;
313 p->neededlen += stringneeded;
315 p->neededlen += needed;
316 if (p->buflen >= needed) {
317 p->structbuf += needed;
319 p->usedlen += needed;
322 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
328 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
329 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
331 #define PACK(desc,t,v) package(desc,v)
332 #define PACKl(desc,t,v,l) package(desc,v,l)
335 static void PACKI(struct pack_desc* desc,char *t,int v)
340 static void PACKS(struct pack_desc* desc,char *t,char *v)
346 /****************************************************************************
348 ****************************************************************************/
349 static void PackDriverData(struct pack_desc* desc)
351 char drivdata[4+4+32];
352 SIVAL(drivdata,0,sizeof drivdata); /* cb */
353 SIVAL(drivdata,4,1000); /* lVersion */
354 memset(drivdata+8,0,32); /* szDeviceName */
355 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
356 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
359 static int check_printq_info(struct pack_desc* desc,
360 int uLevel, char *id1, char *id2)
362 desc->subformat = NULL;
365 desc->format = "B13";
368 desc->format = "B13BWWWzzzzzWW";
371 desc->format = "B13BWWWzzzzzWN";
372 desc->subformat = "WB21BB16B10zWWzDDz";
375 desc->format = "zWWWWzzzzWWzzl";
378 desc->format = "zWWWWzzzzWNzzl";
379 desc->subformat = "WWzWWDDzz";
388 desc->format = "WzzzzzzzzN";
389 desc->subformat = "z";
391 default: return False;
393 if (strcmp(desc->format,id1) != 0) return False;
394 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
399 #define RAP_JOB_STATUS_QUEUED 0
400 #define RAP_JOB_STATUS_PAUSED 1
401 #define RAP_JOB_STATUS_SPOOLING 2
402 #define RAP_JOB_STATUS_PRINTING 3
403 #define RAP_JOB_STATUS_PRINTED 4
405 #define RAP_QUEUE_STATUS_PAUSED 1
406 #define RAP_QUEUE_STATUS_ERROR 2
408 /* turn a print job status into a on the wire status
410 static int printj_status(int v)
414 return RAP_JOB_STATUS_QUEUED;
416 return RAP_JOB_STATUS_PAUSED;
418 return RAP_JOB_STATUS_SPOOLING;
420 return RAP_JOB_STATUS_PRINTING;
425 /* turn a print queue status into a on the wire status
427 static int printq_status(int v)
433 return RAP_QUEUE_STATUS_PAUSED;
435 return RAP_QUEUE_STATUS_ERROR;
438 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
439 struct pack_desc* desc,
440 print_queue_struct* queue, int n)
442 time_t t = queue->time;
444 /* the client expects localtime */
447 PACKI(desc,"W",queue->job); /* uJobId */
449 PACKS(desc,"B21",queue->user); /* szUserName */
450 PACKS(desc,"B",""); /* pad */
451 PACKS(desc,"B16",""); /* szNotifyName */
452 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
453 PACKS(desc,"z",""); /* pszParms */
454 PACKI(desc,"W",n+1); /* uPosition */
455 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
456 PACKS(desc,"z",""); /* pszStatus */
457 PACKI(desc,"D",t); /* ulSubmitted */
458 PACKI(desc,"D",queue->size); /* ulSize */
459 PACKS(desc,"z",queue->file); /* pszComment */
461 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
462 PACKI(desc,"W",queue->priority); /* uPriority */
463 PACKS(desc,"z",queue->user); /* pszUserName */
464 PACKI(desc,"W",n+1); /* uPosition */
465 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
466 PACKI(desc,"D",t); /* ulSubmitted */
467 PACKI(desc,"D",queue->size); /* ulSize */
468 PACKS(desc,"z","Samba"); /* pszComment */
469 PACKS(desc,"z",queue->file); /* pszDocument */
471 PACKS(desc,"z",""); /* pszNotifyName */
472 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
473 PACKS(desc,"z",""); /* pszParms */
474 PACKS(desc,"z",""); /* pszStatus */
475 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
476 PACKS(desc,"z","lpd"); /* pszQProcName */
477 PACKS(desc,"z",""); /* pszQProcParms */
478 PACKS(desc,"z","NULL"); /* pszDriverName */
479 PackDriverData(desc); /* pDriverData */
480 PACKS(desc,"z",""); /* pszPrinterName */
481 } else if (uLevel == 4) { /* OS2 */
482 PACKS(desc,"z",""); /* pszSpoolFileName */
483 PACKS(desc,"z",""); /* pszPortName */
484 PACKS(desc,"z",""); /* pszStatus */
485 PACKI(desc,"D",0); /* ulPagesSpooled */
486 PACKI(desc,"D",0); /* ulPagesSent */
487 PACKI(desc,"D",0); /* ulPagesPrinted */
488 PACKI(desc,"D",0); /* ulTimePrinted */
489 PACKI(desc,"D",0); /* ulExtendJobStatus */
490 PACKI(desc,"D",0); /* ulStartPage */
491 PACKI(desc,"D",0); /* ulEndPage */
496 /********************************************************************
497 Return a driver name given an snum.
498 Looks in a tdb first. Returns True if from tdb, False otherwise.
499 ********************************************************************/
501 static BOOL get_driver_name(int snum, pstring drivername)
503 NT_PRINTER_INFO_LEVEL *info = NULL;
506 get_a_printer (&info, 2, lp_servicename(snum));
508 pstrcpy( drivername, info->info_2->drivername);
510 free_a_printer(&info, 2);
512 pstrcpy( drivername, lp_printerdriver(snum));
518 /********************************************************************
519 Respond to the DosPrintQInfo command with a level of 52
520 This is used to get printer driver information for Win9x clients
521 ********************************************************************/
522 static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
523 struct pack_desc* desc,
524 int count, print_queue_struct* queue,
525 print_status_struct* status)
529 pstring tok,driver,datafile,langmon,helpfile,datatype;
538 * Check in the tdb *first* before checking the legacy
539 * files. This allows an NT upload to take precedence over
540 * the existing fileset. JRA.
542 * we need to lookup the driver name prior to making the call
543 * to get_a_printer_driver_9x_compatible() and not rely on the
544 * 'print driver' parameter --jerry
548 if ((get_driver_name(snum,drivername)) &&
549 ((ok = get_a_printer_driver_9x_compatible(gen_line, drivername)) == True))
553 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line));
557 /* didn't find driver in tdb */
559 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
560 snum, drivername, lp_driverfile(snum)));
562 lines = file_lines_load(lp_driverfile(snum),NULL);
565 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),
567 desc->errcode=NERR_notsupported;
571 /* lookup the long printer driver name in the file description */
572 for (i=0;lines[i] && !ok;i++)
575 if (next_token(&p,tok,":",sizeof(tok)) &&
576 (strlen(drivername) == strlen(tok)) &&
577 (!strncmp(tok,drivername,strlen(drivername))))
586 /* driver file name */
587 if (!next_token(&p,driver,":",sizeof(driver)))
591 if (!next_token(&p,datafile,":",sizeof(datafile)))
595 * for the next tokens - which may be empty - I have
596 * to check for empty tokens first because the
597 * next_token function will skip all empty token
606 else if (!next_token(&p,helpfile,":",sizeof(helpfile)))
609 /* language monitor */
615 else if (!next_token(&p,langmon,":",sizeof(langmon)))
618 /* default data type */
619 if (!next_token(&p,datatype,":",sizeof(datatype)))
622 PACKI(desc,"W",0x0400); /* don't know */
623 PACKS(desc,"z",drivername); /* long printer name */
624 PACKS(desc,"z",driver); /* Driverfile Name */
625 PACKS(desc,"z",datafile); /* Datafile name */
626 PACKS(desc,"z",langmon); /* language monitor */
629 fstrcpy(location, "\\\\");
630 fstrcat(location, global_myname);
631 fstrcat(location, "\\print$\\WIN40\\0");
632 PACKS(desc,"z",location); /* share to retrieve files */
636 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
638 PACKS(desc,"z",datatype); /* default data type */
639 PACKS(desc,"z",helpfile); /* helpfile name */
640 PACKS(desc,"z",driver); /* driver name */
642 DEBUG(3,("printerdriver:%s:\n",drivername));
643 DEBUG(3,("Driver:%s:\n",driver));
644 DEBUG(3,("Data File:%s:\n",datafile));
645 DEBUG(3,("Language Monitor:%s:\n",langmon));
647 DEBUG(3,("lp_driverlocation:%s:\n",location));
649 DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum)));
650 DEBUG(3,("Data Type:%s:\n",datatype));
651 DEBUG(3,("Help File:%s:\n",helpfile));
652 PACKI(desc,"N",count); /* number of files to copy */
654 for (i=0;i<count;i++)
656 /* no need to check return value here
657 * - it was already tested in
658 * get_printerdrivernumber */
659 next_token(&p,tok,",",sizeof(tok));
660 PACKS(desc,"z",tok); /* driver files to copy */
661 DEBUG(3,("file:%s:\n",tok));
664 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
665 SERVICE(snum),count));
667 desc->errcode=NERR_Success;
673 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
674 desc->errcode=NERR_notsupported;
677 file_lines_free(lines);
681 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
682 struct pack_desc* desc,
683 int count, print_queue_struct* queue,
684 print_status_struct* status)
689 PACKS(desc,"B13",SERVICE(snum));
694 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
697 PACKI(desc,"K",printq_status(status->status));
701 if (uLevel == 1 || uLevel == 2) {
702 PACKS(desc,"B",""); /* alignment */
703 PACKI(desc,"W",5); /* priority */
704 PACKI(desc,"W",0); /* start time */
705 PACKI(desc,"W",0); /* until time */
706 PACKS(desc,"z",""); /* pSepFile */
707 PACKS(desc,"z","lpd"); /* pPrProc */
708 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
709 PACKS(desc,"z",""); /* pParms */
711 PACKS(desc,"z","UNKNOWN PRINTER");
712 PACKI(desc,"W",LPSTAT_ERROR);
714 else if (!status || !status->message[0]) {
715 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
716 PACKI(desc,"W",LPSTAT_OK); /* status */
718 PACKS(desc,"z",status->message);
719 PACKI(desc,"W",printq_status(status->status)); /* status */
721 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
724 if (uLevel == 3 || uLevel == 4) {
727 PACKI(desc,"W",5); /* uPriority */
728 PACKI(desc,"W",0); /* uStarttime */
729 PACKI(desc,"W",0); /* uUntiltime */
730 PACKI(desc,"W",5); /* pad1 */
731 PACKS(desc,"z",""); /* pszSepFile */
732 PACKS(desc,"z","WinPrint"); /* pszPrProc */
733 PACKS(desc,"z",NULL); /* pszParms */
734 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
735 /* "don't ask" that it's done this way to fix corrupted
736 Win9X/ME printer comments. */
738 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
740 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
742 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
743 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
744 get_driver_name(snum,drivername);
745 PACKS(desc,"z",drivername); /* pszDriverName */
746 PackDriverData(desc); /* pDriverData */
749 if (uLevel == 2 || uLevel == 4) {
751 for (i=0;i<count;i++)
752 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
756 fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status);
760 /* This function returns the number of files for a given driver */
761 static int get_printerdrivernumber(int snum)
772 * Check in the tdb *first* before checking the legacy
773 * files. This allows an NT upload to take precedence over
774 * the existing fileset. JRA.
776 * we need to lookup the driver name prior to making the call
777 * to get_a_printer_driver_9x_compatible() and not rely on the
778 * 'print driver' parameter --jerry
781 if ((get_driver_name(snum,drivername)) &&
782 (ok = get_a_printer_driver_9x_compatible(gen_line, drivername) == True))
785 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line));
789 /* didn't find driver in tdb */
791 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
792 snum, drivername, lp_driverfile(snum)));
794 lines = file_lines_load(lp_driverfile(snum), NULL);
797 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
801 /* lookup the long printer driver name in the file description */
802 for (i=0;lines[i] && !ok;i++)
805 if (next_token(&p,tok,":",sizeof(tok)) &&
806 (strlen(drivername) == strlen(tok)) &&
807 (!strncmp(tok,drivername,strlen(drivername))))
819 if (*p++ == ':') i--;
822 DEBUG(3,("Can't determine number of printer driver files\n"));
826 /* count the number of files */
827 while (next_token(&p,tok,",",sizeof(tok)))
835 file_lines_free(lines);
840 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
841 uint16 vuid, char *param,char *data,
842 int mdrcnt,int mprcnt,
843 char **rdata,char **rparam,
844 int *rdata_len,int *rparam_len)
846 char *str1 = param+2;
847 char *str2 = skip_string(str1,1);
848 char *p = skip_string(str2,1);
854 struct pack_desc desc;
855 print_queue_struct *queue=NULL;
856 print_status_struct status;
859 memset((char *)&status,'\0',sizeof(status));
860 memset((char *)&desc,'\0',sizeof(desc));
862 p = skip_string(p,1);
866 /* remove any trailing username */
867 if ((p = strchr_m(QueueName,'%')))
870 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
872 /* check it's a supported varient */
873 if (!prefix_ok(str1,"zWrLh"))
875 if (!check_printq_info(&desc,uLevel,str2,str3)) {
877 * Patch from Scott Moomaw <scott@bridgewater.edu>
878 * to return the 'invalid info level' error if an
879 * unknown level was requested.
883 *rparam = REALLOC(*rparam,*rparam_len);
884 SSVALS(*rparam,0,ERRunknownlevel);
890 snum = lp_servicenumber(QueueName);
891 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
892 int pnum = lp_servicenumber(PRINTERS_NAME);
894 lp_add_printer(QueueName,pnum);
895 snum = lp_servicenumber(QueueName);
899 if (snum < 0 || !VALID_SNUM(snum))
903 count = get_printerdrivernumber(snum);
904 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
906 count = print_queue_status(snum, &queue,&status);
910 *rdata = REALLOC(*rdata,mdrcnt);
912 desc.buflen = mdrcnt;
915 * Don't return data but need to get correct length
916 * init_package will return wrong size if buflen=0
918 desc.buflen = getlen(desc.format);
919 desc.base = tmpdata = (char *) malloc (desc.buflen);
922 if (init_package(&desc,1,count)) {
923 desc.subcount = count;
924 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
927 *rdata_len = desc.usedlen;
930 * We must set the return code to ERRbuftoosmall
931 * in order to support lanman style printing with Win NT/2k
934 if (!mdrcnt && lp_disable_spoolss())
935 desc.errcode = ERRbuftoosmall;
937 *rdata_len = desc.usedlen;
939 *rparam = REALLOC(*rparam,*rparam_len);
940 SSVALS(*rparam,0,desc.errcode);
942 SSVAL(*rparam,4,desc.neededlen);
944 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
952 /****************************************************************************
953 View list of all print jobs on all queues.
954 ****************************************************************************/
956 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
957 int mdrcnt, int mprcnt,
958 char **rdata, char** rparam,
959 int *rdata_len, int *rparam_len)
961 char *param_format = param+2;
962 char *output_format1 = skip_string(param_format,1);
963 char *p = skip_string(output_format1,1);
964 int uLevel = SVAL(p,0);
965 char *output_format2 = p + 4;
966 int services = lp_numservices();
968 struct pack_desc desc;
969 print_queue_struct **queue = NULL;
970 print_status_struct *status = NULL;
971 int* subcntarr = NULL;
972 int queuecnt, subcnt=0, succnt=0;
974 memset((char *)&desc,'\0',sizeof(desc));
976 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
978 if (!prefix_ok(param_format,"WrLeh")) return False;
979 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
981 * Patch from Scott Moomaw <scott@bridgewater.edu>
982 * to return the 'invalid info level' error if an
983 * unknown level was requested.
987 *rparam = REALLOC(*rparam,*rparam_len);
988 SSVALS(*rparam,0,ERRunknownlevel);
995 for (i = 0; i < services; i++)
996 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
999 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
1000 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1003 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1004 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
1005 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1008 memset(status,0,queuecnt*sizeof(print_status_struct));
1009 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
1010 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1015 for (i = 0; i < services; i++)
1016 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1017 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1018 subcnt += subcntarr[n];
1022 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
1024 desc.buflen = mdrcnt;
1026 if (init_package(&desc,queuecnt,subcnt)) {
1029 for (i = 0; i < services; i++)
1030 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1031 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1033 if (desc.errcode == NERR_Success) succnt = n;
1037 SAFE_FREE(subcntarr);
1039 *rdata_len = desc.usedlen;
1041 *rparam = REALLOC(*rparam,*rparam_len);
1042 SSVALS(*rparam,0,desc.errcode);
1044 SSVAL(*rparam,4,succnt);
1045 SSVAL(*rparam,6,queuecnt);
1047 for (i = 0; i < queuecnt; i++) {
1048 if (queue) SAFE_FREE(queue[i]);
1057 /****************************************************************************
1058 get info level for a server list query
1059 ****************************************************************************/
1060 static BOOL check_server_info(int uLevel, char* id)
1064 if (strcmp(id,"B16") != 0) return False;
1067 if (strcmp(id,"B16BBDz") != 0) return False;
1075 struct srv_info_struct
1085 /*******************************************************************
1086 get server info lists from the files saved by nmbd. Return the
1088 ******************************************************************/
1089 static int get_server_info(uint32 servertype,
1090 struct srv_info_struct **servers,
1096 BOOL local_list_only;
1099 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
1101 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1105 /* request for everything is code for request all servers */
1106 if (servertype == SV_TYPE_ALL)
1107 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1109 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1111 DEBUG(4,("Servertype search: %8x\n",servertype));
1113 for (i=0;lines[i];i++) {
1115 struct srv_info_struct *s;
1116 char *ptr = lines[i];
1119 if (!*ptr) continue;
1121 if (count == alloced) {
1122 struct srv_info_struct *ts;
1125 ts = (struct srv_info_struct *)
1126 Realloc(*servers,sizeof(**servers)*alloced);
1128 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1132 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1134 s = &(*servers)[count];
1136 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1137 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1138 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1139 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1140 /* this allows us to cope with an old nmbd */
1141 pstrcpy(s->domain,global_myworkgroup);
1144 if (sscanf(stype,"%X",&s->type) != 1) {
1145 DEBUG(4,("r:host file "));
1149 /* Filter the servers/domains we return based on what was asked for. */
1151 /* Check to see if we are being asked for a local list only. */
1152 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1153 DEBUG(4,("r: local list only"));
1157 /* doesn't match up: don't want it */
1158 if (!(servertype & s->type)) {
1159 DEBUG(4,("r:serv type "));
1163 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1164 (s->type & SV_TYPE_DOMAIN_ENUM))
1166 DEBUG(4,("s: dom mismatch "));
1170 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1175 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1176 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1180 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1181 s->name, s->type, s->comment, s->domain));
1183 s->server_added = True;
1188 DEBUG(4,("%20s %8x %25s %15s\n",
1189 s->name, s->type, s->comment, s->domain));
1193 file_lines_free(lines);
1198 /*******************************************************************
1199 fill in a server info structure
1200 ******************************************************************/
1201 static int fill_srv_info(struct srv_info_struct *service,
1202 int uLevel, char **buf, int *buflen,
1203 char **stringbuf, int *stringspace, char *baseaddr)
1212 case 0: struct_len = 16; break;
1213 case 1: struct_len = 26; break;
1223 len = strlen(service->comment)+1;
1227 if (buflen) *buflen = struct_len;
1228 if (stringspace) *stringspace = len;
1229 return struct_len + len;
1234 if (*buflen < struct_len) return -1;
1242 p2 = p + struct_len;
1243 l2 = *buflen - struct_len;
1245 if (!baseaddr) baseaddr = p;
1250 push_ascii(p,service->name, 15, STR_TERMINATE);
1254 push_ascii(p,service->name,15, STR_TERMINATE);
1255 SIVAL(p,18,service->type);
1256 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1257 len += CopyAndAdvance(&p2,service->comment,&l2);
1263 *buf = p + struct_len;
1264 *buflen -= struct_len;
1277 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1279 return(strcmp(s1->name,s2->name));
1282 /****************************************************************************
1283 view list of servers available (or possibly domains). The info is
1284 extracted from lists saved by nmbd on the local host
1285 ****************************************************************************/
1286 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1287 int mdrcnt, int mprcnt, char **rdata,
1288 char **rparam, int *rdata_len, int *rparam_len)
1290 char *str1 = param+2;
1291 char *str2 = skip_string(str1,1);
1292 char *p = skip_string(str2,1);
1293 int uLevel = SVAL(p,0);
1294 int buf_len = SVAL(p,2);
1295 uint32 servertype = IVAL(p,4);
1297 int data_len, fixed_len, string_len;
1298 int f_len = 0, s_len = 0;
1299 struct srv_info_struct *servers=NULL;
1300 int counted=0,total=0;
1303 BOOL domain_request;
1306 /* If someone sets all the bits they don't really mean to set
1307 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1310 if (servertype == SV_TYPE_ALL)
1311 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1313 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1314 any other bit (they may just set this bit on it's own) they
1315 want all the locally seen servers. However this bit can be
1316 set on its own so set the requested servers to be
1317 ALL - DOMAIN_ENUM. */
1319 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1320 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1322 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1323 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1327 if (!prefix_ok(str1,"WrLehD")) return False;
1328 if (!check_server_info(uLevel,str2)) return False;
1330 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1331 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1332 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1334 if (strcmp(str1, "WrLehDz") == 0) {
1335 pull_ascii_fstring(domain, p);
1337 fstrcpy(domain, global_myworkgroup);
1340 if (lp_browse_list())
1341 total = get_server_info(servertype,&servers,domain);
1343 data_len = fixed_len = string_len = 0;
1347 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1350 char *lastname=NULL;
1352 for (i=0;i<total;i++)
1354 struct srv_info_struct *s = &servers[i];
1355 if (lastname && strequal(lastname,s->name)) continue;
1357 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1358 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1359 s->name, s->type, s->comment, s->domain));
1361 if (data_len <= buf_len) {
1364 string_len += s_len;
1371 *rdata_len = fixed_len + string_len;
1372 *rdata = REALLOC(*rdata,*rdata_len);
1373 memset(*rdata,'\0',*rdata_len);
1375 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1381 char *lastname=NULL;
1382 int count2 = counted;
1383 for (i = 0; i < total && count2;i++)
1385 struct srv_info_struct *s = &servers[i];
1386 if (lastname && strequal(lastname,s->name)) continue;
1388 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1389 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1390 s->name, s->type, s->comment, s->domain));
1396 *rparam = REALLOC(*rparam,*rparam_len);
1397 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1399 SSVAL(*rparam,4,counted);
1400 SSVAL(*rparam,6,counted+missed);
1404 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1405 domain,uLevel,counted,counted+missed));
1410 /****************************************************************************
1411 command 0x34 - suspected of being a "Lookup Names" stub api
1412 ****************************************************************************/
1413 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1414 int mdrcnt, int mprcnt, char **rdata,
1415 char **rparam, int *rdata_len, int *rparam_len)
1417 char *str1 = param+2;
1418 char *str2 = skip_string(str1,1);
1419 char *p = skip_string(str2,1);
1420 int uLevel = SVAL(p,0);
1421 int buf_len = SVAL(p,2);
1425 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1426 str1, str2, p, uLevel, buf_len));
1428 if (!prefix_ok(str1,"zWrLeh")) return False;
1433 *rparam = REALLOC(*rparam,*rparam_len);
1435 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1437 SSVAL(*rparam,4,counted);
1438 SSVAL(*rparam,6,counted+missed);
1443 /****************************************************************************
1444 get info about a share
1445 ****************************************************************************/
1446 static BOOL check_share_info(int uLevel, char* id)
1450 if (strcmp(id,"B13") != 0) return False;
1453 if (strcmp(id,"B13BWz") != 0) return False;
1456 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1459 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1461 default: return False;
1466 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1467 char** buf, int* buflen,
1468 char** stringbuf, int* stringspace, char* baseaddr)
1477 case 0: struct_len = 13; break;
1478 case 1: struct_len = 20; break;
1479 case 2: struct_len = 40; break;
1480 case 91: struct_len = 68; break;
1488 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1489 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1490 if (buflen) *buflen = struct_len;
1491 if (stringspace) *stringspace = len;
1492 return struct_len + len;
1497 if ((*buflen) < struct_len) return -1;
1505 p2 = p + struct_len;
1506 l2 = (*buflen) - struct_len;
1508 if (!baseaddr) baseaddr = p;
1510 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1516 type = STYPE_DISKTREE;
1517 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1518 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1519 SSVAL(p,14,type); /* device type */
1520 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1521 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1526 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1527 SSVALS(p,22,-1); /* max uses */
1528 SSVAL(p,24,1); /* current uses */
1529 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1530 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1531 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1536 memset(p+40,0,SHPWLEN+2);
1548 (*buf) = p + struct_len;
1549 (*buflen) -= struct_len;
1551 (*stringspace) = l2;
1561 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1562 int mdrcnt,int mprcnt,
1563 char **rdata,char **rparam,
1564 int *rdata_len,int *rparam_len)
1566 char *str1 = param+2;
1567 char *str2 = skip_string(str1,1);
1568 char *netname = skip_string(str2,1);
1569 char *p = skip_string(netname,1);
1570 int uLevel = SVAL(p,0);
1571 int snum = find_service(netname);
1573 if (snum < 0) return False;
1575 /* check it's a supported varient */
1576 if (!prefix_ok(str1,"zWrLh")) return False;
1577 if (!check_share_info(uLevel,str2)) return False;
1579 *rdata = REALLOC(*rdata,mdrcnt);
1581 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1582 if (*rdata_len < 0) return False;
1585 *rparam = REALLOC(*rparam,*rparam_len);
1586 SSVAL(*rparam,0,NERR_Success);
1587 SSVAL(*rparam,2,0); /* converter word */
1588 SSVAL(*rparam,4,*rdata_len);
1593 /****************************************************************************
1594 view list of shares available
1595 ****************************************************************************/
1596 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1597 int mdrcnt,int mprcnt,
1598 char **rdata,char **rparam,
1599 int *rdata_len,int *rparam_len)
1601 char *str1 = param+2;
1602 char *str2 = skip_string(str1,1);
1603 char *p = skip_string(str2,1);
1604 int uLevel = SVAL(p,0);
1605 int buf_len = SVAL(p,2);
1607 int count=lp_numservices();
1608 int total=0,counted=0;
1609 BOOL missed = False;
1611 int data_len, fixed_len, string_len;
1612 int f_len = 0, s_len = 0;
1614 if (!prefix_ok(str1,"WrLeh")) return False;
1615 if (!check_share_info(uLevel,str2)) return False;
1617 data_len = fixed_len = string_len = 0;
1618 for (i=0;i<count;i++)
1619 if (lp_browseable(i) && lp_snum_ok(i))
1622 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1623 if (data_len <= buf_len)
1627 string_len += s_len;
1632 *rdata_len = fixed_len + string_len;
1633 *rdata = REALLOC(*rdata,*rdata_len);
1634 memset(*rdata,0,*rdata_len);
1636 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1640 for (i = 0; i < count;i++)
1641 if (lp_browseable(i) && lp_snum_ok(i))
1642 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1646 *rparam = REALLOC(*rparam,*rparam_len);
1647 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1649 SSVAL(*rparam,4,counted);
1650 SSVAL(*rparam,6,total);
1652 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1653 counted,total,uLevel,
1654 buf_len,*rdata_len,mdrcnt));
1658 /****************************************************************************
1660 ****************************************************************************/
1661 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1662 int mdrcnt,int mprcnt,
1663 char **rdata,char **rparam,
1664 int *rdata_len,int *rparam_len)
1666 char *str1 = param+2;
1667 char *str2 = skip_string(str1,1);
1668 char *p = skip_string(str2,1);
1669 int uLevel = SVAL(p,0);
1678 /* check it's a supported varient */
1679 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1680 if (!check_share_info(uLevel,str2)) return False;
1683 *rparam = REALLOC(*rparam,*rparam_len);
1685 SSVAL(*rparam,0,NERR_notsupported);
1690 pull_ascii_fstring(sharename,data);
1691 snum = find_service(sharename);
1692 if (snum >= 0) { /* already exists */
1694 *rparam = REALLOC(*rparam,*rparam_len);
1695 SSVAL(*rparam,0,ERRfilexists);
1700 /* only support disk share adds */
1701 if (SVAL(data,14)!=STYPE_DISKTREE) {
1703 *rparam = REALLOC(*rparam,*rparam_len);
1705 SSVAL(*rparam,0,NERR_notsupported);
1710 offset = IVAL(data, 16);
1711 pull_ascii_fstring(comment, offset? (data+offset) : "");
1712 offset = IVAL(data, 26);
1713 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1715 string_replace(sharename, '"', ' ');
1716 string_replace(pathname, '"', ' ');
1717 string_replace(comment, '"', ' ');
1719 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1720 lp_add_share_cmd(), CONFIGFILE, sharename, pathname, comment);
1722 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1723 if ((res = smbrun(command, NULL)) != 0) {
1724 DEBUG(0,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1727 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False);
1731 *rparam = REALLOC(*rparam,*rparam_len);
1732 SSVAL(*rparam,0,NERR_Success);
1733 SSVAL(*rparam,2,0); /* converter word */
1734 SSVAL(*rparam,4,*rdata_len);
1740 /****************************************************************************
1741 view list of groups available
1742 ****************************************************************************/
1743 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1744 int mdrcnt,int mprcnt,
1745 char **rdata,char **rparam,
1746 int *rdata_len,int *rparam_len)
1748 char *str1 = param+2;
1749 char *str2 = skip_string(str1,1);
1750 char *p = skip_string(str2,1);
1751 int uLevel = SVAL(p,0);
1755 if (!prefix_ok(str1,"WrLeh")) return False;
1757 /* check it's a supported variant */
1767 if (strcmp(p2,str2) != 0) return False;
1769 *rdata_len = mdrcnt + 1024;
1770 *rdata = REALLOC(*rdata,*rdata_len);
1772 SSVAL(*rparam,0,NERR_Success);
1773 SSVAL(*rparam,2,0); /* converter word */
1777 /* XXXX we need a real SAM database some day */
1778 pstrcpy(p,"Users"); p += 21; count++;
1779 pstrcpy(p,"Domain Users"); p += 21; count++;
1780 pstrcpy(p,"Guests"); p += 21; count++;
1781 pstrcpy(p,"Domain Guests"); p += 21; count++;
1783 *rdata_len = PTR_DIFF(p,*rdata);
1786 *rparam = REALLOC(*rparam,*rparam_len);
1788 SSVAL(*rparam,4,count); /* is this right?? */
1789 SSVAL(*rparam,6,count); /* is this right?? */
1791 DEBUG(3,("api_RNetGroupEnum gave %d entries\n", count));
1796 /****************************************************************************
1797 view list of groups available
1798 ****************************************************************************/
1799 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1800 int mdrcnt,int mprcnt,
1801 char **rdata,char **rparam,
1802 int *rdata_len,int *rparam_len)
1804 char *str1 = param+2;
1805 char *str2 = skip_string(str1,1);
1806 char *p = skip_string(str2,1);
1807 int uLevel = SVAL(p,0);
1811 if (!prefix_ok(str1,"WrLeh")) return False;
1813 /* check it's a supported variant */
1823 if (strcmp(p2,str2) != 0) return False;
1825 *rdata_len = mdrcnt + 1024;
1826 *rdata = REALLOC(*rdata,*rdata_len);
1828 SSVAL(*rparam,0,NERR_Success);
1829 SSVAL(*rparam,2,0); /* converter word */
1833 /* XXXX we need a real SAM database some day */
1834 pstrcpy(p,"Users"); p += 21; count++;
1835 pstrcpy(p,"Domain Users"); p += 21; count++;
1836 pstrcpy(p,"Guests"); p += 21; count++;
1837 pstrcpy(p,"Domain Guests"); p += 21; count++;
1839 *rdata_len = PTR_DIFF(p,*rdata);
1842 *rparam = REALLOC(*rparam,*rparam_len);
1844 SSVAL(*rparam,4,count); /* is this right?? */
1845 SSVAL(*rparam,6,count); /* is this right?? */
1847 DEBUG(3,("api_RNetUserEnum gave %d entries\n", count));
1854 /****************************************************************************
1855 get the time of day info
1856 ****************************************************************************/
1857 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1858 int mdrcnt,int mprcnt,
1859 char **rdata,char **rparam,
1860 int *rdata_len,int *rparam_len)
1864 *rparam = REALLOC(*rparam,*rparam_len);
1867 *rdata = REALLOC(*rdata,*rdata_len);
1869 SSVAL(*rparam,0,NERR_Success);
1870 SSVAL(*rparam,2,0); /* converter word */
1876 time_t unixdate = time(NULL);
1878 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1879 by NT in a "net time" operation,
1880 it seems to ignore the one below */
1882 /* the client expects to get localtime, not GMT, in this bit
1883 (I think, this needs testing) */
1884 t = LocalTime(&unixdate);
1886 SIVAL(p,4,0); /* msecs ? */
1887 CVAL(p,8) = t->tm_hour;
1888 CVAL(p,9) = t->tm_min;
1889 CVAL(p,10) = t->tm_sec;
1890 CVAL(p,11) = 0; /* hundredths of seconds */
1891 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1892 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1893 CVAL(p,16) = t->tm_mday;
1894 CVAL(p,17) = t->tm_mon + 1;
1895 SSVAL(p,18,1900+t->tm_year);
1896 CVAL(p,20) = t->tm_wday;
1903 /****************************************************************************
1904 Set the user password.
1905 *****************************************************************************/
1907 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1908 int mdrcnt,int mprcnt,
1909 char **rdata,char **rparam,
1910 int *rdata_len,int *rparam_len)
1912 char *p = skip_string(param+2,2);
1914 fstring pass1,pass2;
1916 struct passwd *passwd;
1918 pull_ascii_fstring(user,p);
1920 p = skip_string(p,1);
1922 memset(pass1,'\0',sizeof(pass1));
1923 memset(pass2,'\0',sizeof(pass2));
1925 memcpy(pass2,p+16,16);
1928 *rparam = REALLOC(*rparam,*rparam_len);
1932 SSVAL(*rparam,0,NERR_badpass);
1933 SSVAL(*rparam,2,0); /* converter word */
1935 DEBUG(3,("Set password for <%s>\n",user));
1938 * Pass the user through the NT -> unix user mapping
1942 (void)map_username(user);
1945 * Do any UNIX username case mangling.
1947 passwd = Get_Pwnam( user, True);
1950 * Attempt to verify the old password against smbpasswd entries
1951 * Win98 clients send old and new password in plaintext for this call.
1955 fstring saved_pass2;
1956 SAM_ACCOUNT *sampass=NULL;
1959 * Save the new password as change_oem_password overwrites it
1963 fstrcpy(saved_pass2, pass2);
1965 if (check_plaintext_password(user,pass1,strlen(pass1),&sampass) &&
1966 change_oem_password(sampass,pass2))
1968 SSVAL(*rparam,0,NERR_Success);
1971 * If unix password sync was requested, attempt to change
1972 * the /etc/passwd database also. Return failure if this cannot
1976 if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
1977 SSVAL(*rparam,0,NERR_badpass);
1979 pdb_free_sam(&sampass);
1984 * If the above failed, attempt the plaintext password change.
1985 * This tests against the /etc/passwd database only.
1988 if(SVAL(*rparam,0) != NERR_Success)
1990 if NT_STATUS_IS_OK(pass_check(passwd, user, pass1,
1991 strlen(pass1), NULL, False))
1993 if (chgpasswd(user,pass1,pass2,False)) {
1994 SSVAL(*rparam,0,NERR_Success);
2000 * If the plaintext change failed, attempt
2001 * the old encrypted method. NT will generate this
2002 * after trying the samr method. Note that this
2003 * method is done as a last resort as this
2004 * password change method loses the NT password hash
2005 * and cannot change the UNIX password as no plaintext
2009 if(SVAL(*rparam,0) != NERR_Success)
2011 SAM_ACCOUNT *hnd = NULL;
2013 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) &&
2014 change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2))
2016 SSVAL(*rparam,0,NERR_Success);
2022 memset((char *)pass1,'\0',sizeof(fstring));
2023 memset((char *)pass2,'\0',sizeof(fstring));
2028 /****************************************************************************
2029 Set the user password (SamOEM version - gets plaintext).
2030 ****************************************************************************/
2032 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2033 int mdrcnt,int mprcnt,
2034 char **rdata,char **rparam,
2035 int *rdata_len,int *rparam_len)
2038 char *p = param + 2;
2040 *rparam = REALLOC(*rparam,*rparam_len);
2044 SSVAL(*rparam,0,NERR_badpass);
2047 * Check the parameter definition is correct.
2049 if(!strequal(param + 2, "zsT")) {
2050 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2053 p = skip_string(p, 1);
2055 if(!strequal(p, "B516B16")) {
2056 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2059 p = skip_string(p,1);
2061 p += pull_ascii_fstring(user,p);
2063 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2066 * Pass the user through the NT -> unix user mapping
2070 (void)map_username(user);
2073 * Do any UNIX username case mangling.
2075 (void)Get_Pwnam( user, True);
2077 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
2079 SSVAL(*rparam,0,NERR_Success);
2085 /****************************************************************************
2088 ****************************************************************************/
2089 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2090 int mdrcnt,int mprcnt,
2091 char **rdata,char **rparam,
2092 int *rdata_len,int *rparam_len)
2094 int function = SVAL(param,0);
2095 char *str1 = param+2;
2096 char *str2 = skip_string(str1,1);
2097 char *p = skip_string(str2,1);
2099 extern struct current_user current_user;
2100 WERROR werr = WERR_OK;
2104 /* check it's a supported varient */
2105 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2109 *rparam = REALLOC(*rparam,*rparam_len);
2112 if (!print_job_exists(jobid)) {
2113 errcode = NERR_JobNotFound;
2117 errcode = NERR_notsupported;
2120 case 81: /* delete */
2121 if (print_job_delete(¤t_user, jobid, &werr))
2122 errcode = NERR_Success;
2124 case 82: /* pause */
2125 if (print_job_pause(¤t_user, jobid, &werr))
2126 errcode = NERR_Success;
2128 case 83: /* resume */
2129 if (print_job_resume(¤t_user, jobid, &werr))
2130 errcode = NERR_Success;
2134 if (!W_ERROR_IS_OK(werr))
2135 errcode = W_ERROR_V(werr);
2138 SSVAL(*rparam,0,errcode);
2139 SSVAL(*rparam,2,0); /* converter word */
2144 /****************************************************************************
2145 Purge a print queue - or pause or resume it.
2146 ****************************************************************************/
2147 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2148 int mdrcnt,int mprcnt,
2149 char **rdata,char **rparam,
2150 int *rdata_len,int *rparam_len)
2152 int function = SVAL(param,0);
2153 char *str1 = param+2;
2154 char *str2 = skip_string(str1,1);
2155 char *QueueName = skip_string(str2,1);
2156 int errcode = NERR_notsupported;
2158 WERROR werr = WERR_OK;
2159 extern struct current_user current_user;
2161 /* check it's a supported varient */
2162 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2166 *rparam = REALLOC(*rparam,*rparam_len);
2169 snum = print_queue_snum(QueueName);
2172 errcode = NERR_JobNotFound;
2177 case 74: /* Pause queue */
2178 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2180 case 75: /* Resume queue */
2181 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2183 case 103: /* Purge */
2184 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2188 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2191 SSVAL(*rparam,0,errcode);
2192 SSVAL(*rparam,2,0); /* converter word */
2198 /****************************************************************************
2199 set the property of a print job (undocumented?)
2200 ? function = 0xb -> set name of print job
2201 ? function = 0x6 -> move print job up/down
2202 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2203 or <WWsTP> <WB21BB16B10zWWzDDz>
2204 ****************************************************************************/
2205 static int check_printjob_info(struct pack_desc* desc,
2206 int uLevel, char* id)
2208 desc->subformat = NULL;
2210 case 0: desc->format = "W"; break;
2211 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2212 case 2: desc->format = "WWzWWDDzz"; break;
2213 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2214 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2215 default: return False;
2217 if (strcmp(desc->format,id) != 0) return False;
2221 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2222 int mdrcnt,int mprcnt,
2223 char **rdata,char **rparam,
2224 int *rdata_len,int *rparam_len)
2226 struct pack_desc desc;
2227 char *str1 = param+2;
2228 char *str2 = skip_string(str1,1);
2229 char *p = skip_string(str2,1);
2231 int uLevel = SVAL(p,2);
2232 int function = SVAL(p,4);
2237 *rparam = REALLOC(*rparam,*rparam_len);
2241 /* check it's a supported varient */
2242 if ((strcmp(str1,"WWsTP")) ||
2243 (!check_printjob_info(&desc,uLevel,str2)))
2246 if (!print_job_exists(jobid)) {
2247 errcode=NERR_JobNotFound;
2251 errcode = NERR_notsupported;
2255 /* change job place in the queue,
2256 data gives the new place */
2257 place = SVAL(data,0);
2258 if (print_job_set_place(jobid, place)) {
2259 errcode=NERR_Success;
2264 /* change print job name, data gives the name */
2265 if (print_job_set_name(jobid, data)) {
2266 errcode=NERR_Success;
2275 SSVALS(*rparam,0,errcode);
2276 SSVAL(*rparam,2,0); /* converter word */
2282 /****************************************************************************
2283 get info about the server
2284 ****************************************************************************/
2285 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2286 int mdrcnt,int mprcnt,
2287 char **rdata,char **rparam,
2288 int *rdata_len,int *rparam_len)
2290 char *str1 = param+2;
2291 char *str2 = skip_string(str1,1);
2292 char *p = skip_string(str2,1);
2293 int uLevel = SVAL(p,0);
2297 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2299 /* check it's a supported varient */
2300 if (!prefix_ok(str1,"WrLh")) return False;
2303 if (strcmp(str2,"B16") != 0) return False;
2307 if (strcmp(str2,"B16BBDz") != 0) return False;
2311 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2316 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2321 if (strcmp(str2,"DN") != 0) return False;
2325 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2328 default: return False;
2331 *rdata_len = mdrcnt;
2332 *rdata = REALLOC(*rdata,*rdata_len);
2335 p2 = p + struct_len;
2337 srvstr_push(NULL, p,local_machine,16,
2338 STR_ASCII|STR_UPPER|STR_TERMINATE);
2343 struct srv_info_struct *servers=NULL;
2346 uint32 servertype= lp_default_server_announce();
2348 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2350 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2351 for (i=0;i<count;i++)
2352 if (strequal(servers[i].name,local_machine))
2354 servertype = servers[i].type;
2355 pstrcpy(comment,servers[i].comment);
2360 SCVAL(p,0,lp_major_announce_version());
2361 SCVAL(p,1,lp_minor_announce_version());
2362 SIVAL(p,2,servertype);
2364 if (mdrcnt == struct_len) {
2367 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2368 standard_sub_conn(conn,comment);
2369 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2370 p2 = skip_string(p2,1);
2375 return False; /* not yet implemented */
2378 *rdata_len = PTR_DIFF(p2,*rdata);
2381 *rparam = REALLOC(*rparam,*rparam_len);
2382 SSVAL(*rparam,0,NERR_Success);
2383 SSVAL(*rparam,2,0); /* converter word */
2384 SSVAL(*rparam,4,*rdata_len);
2390 /****************************************************************************
2391 get info about the server
2392 ****************************************************************************/
2393 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2394 int mdrcnt,int mprcnt,
2395 char **rdata,char **rparam,
2396 int *rdata_len,int *rparam_len)
2398 char *str1 = param+2;
2399 char *str2 = skip_string(str1,1);
2400 char *p = skip_string(str2,1);
2402 extern userdom_struct current_user_info;
2403 int level = SVAL(p,0);
2405 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2408 *rparam = REALLOC(*rparam,*rparam_len);
2410 /* check it's a supported varient */
2411 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2414 *rdata_len = mdrcnt + 1024;
2415 *rdata = REALLOC(*rdata,*rdata_len);
2417 SSVAL(*rparam,0,NERR_Success);
2418 SSVAL(*rparam,2,0); /* converter word */
2424 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2425 pstrcpy(p2,local_machine);
2427 p2 = skip_string(p2,1);
2430 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2431 pstrcpy(p2,current_user_info.smb_name);
2432 p2 = skip_string(p2,1);
2435 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2436 pstrcpy(p2,global_myworkgroup);
2438 p2 = skip_string(p2,1);
2441 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2442 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2445 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2446 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2447 p2 = skip_string(p2,1);
2450 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2452 p2 = skip_string(p2,1);
2455 *rdata_len = PTR_DIFF(p2,*rdata);
2457 SSVAL(*rparam,4,*rdata_len);
2462 /****************************************************************************
2463 get info about a user
2465 struct user_info_11 {
2466 char usri11_name[21]; 0-20
2468 char *usri11_comment; 22-25
2469 char *usri11_usr_comment; 26-29
2470 unsigned short usri11_priv; 30-31
2471 unsigned long usri11_auth_flags; 32-35
2472 long usri11_password_age; 36-39
2473 char *usri11_homedir; 40-43
2474 char *usri11_parms; 44-47
2475 long usri11_last_logon; 48-51
2476 long usri11_last_logoff; 52-55
2477 unsigned short usri11_bad_pw_count; 56-57
2478 unsigned short usri11_num_logons; 58-59
2479 char *usri11_logon_server; 60-63
2480 unsigned short usri11_country_code; 64-65
2481 char *usri11_workstations; 66-69
2482 unsigned long usri11_max_storage; 70-73
2483 unsigned short usri11_units_per_week; 74-75
2484 unsigned char *usri11_logon_hours; 76-79
2485 unsigned short usri11_code_page; 80-81
2490 usri11_name specifies the user name for which information is retireved
2492 usri11_pad aligns the next data structure element to a word boundary
2494 usri11_comment is a null terminated ASCII comment
2496 usri11_user_comment is a null terminated ASCII comment about the user
2498 usri11_priv specifies the level of the privilege assigned to the user.
2499 The possible values are:
2501 Name Value Description
2502 USER_PRIV_GUEST 0 Guest privilege
2503 USER_PRIV_USER 1 User privilege
2504 USER_PRV_ADMIN 2 Administrator privilege
2506 usri11_auth_flags specifies the account operator privileges. The
2507 possible values are:
2509 Name Value Description
2510 AF_OP_PRINT 0 Print operator
2513 Leach, Naik [Page 28]
2517 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2520 AF_OP_COMM 1 Communications operator
2521 AF_OP_SERVER 2 Server operator
2522 AF_OP_ACCOUNTS 3 Accounts operator
2525 usri11_password_age specifies how many seconds have elapsed since the
2526 password was last changed.
2528 usri11_home_dir points to a null terminated ASCII string that contains
2529 the path name of the user's home directory.
2531 usri11_parms points to a null terminated ASCII string that is set
2532 aside for use by applications.
2534 usri11_last_logon specifies the time when the user last logged on.
2535 This value is stored as the number of seconds elapsed since
2536 00:00:00, January 1, 1970.
2538 usri11_last_logoff specifies the time when the user last logged off.
2539 This value is stored as the number of seconds elapsed since
2540 00:00:00, January 1, 1970. A value of 0 means the last logoff
2543 usri11_bad_pw_count specifies the number of incorrect passwords
2544 entered since the last successful logon.
2546 usri11_log1_num_logons specifies the number of times this user has
2547 logged on. A value of -1 means the number of logons is unknown.
2549 usri11_logon_server points to a null terminated ASCII string that
2550 contains the name of the server to which logon requests are sent.
2551 A null string indicates logon requests should be sent to the
2554 usri11_country_code specifies the country code for the user's language
2557 usri11_workstations points to a null terminated ASCII string that
2558 contains the names of workstations the user may log on from.
2559 There may be up to 8 workstations, with the names separated by
2560 commas. A null strings indicates there are no restrictions.
2562 usri11_max_storage specifies the maximum amount of disk space the user
2563 can occupy. A value of 0xffffffff indicates there are no
2566 usri11_units_per_week specifies the equal number of time units into
2567 which a week is divided. This value must be equal to 168.
2569 usri11_logon_hours points to a 21 byte (168 bits) string that
2570 specifies the time during which the user can log on. Each bit
2571 represents one unique hour in a week. The first bit (bit 0, word
2572 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2576 Leach, Naik [Page 29]
2580 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2583 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2584 are no restrictions.
2586 usri11_code_page specifies the code page for the user's language of
2589 All of the pointers in this data structure need to be treated
2590 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2591 to be ignored. The converter word returned in the parameters section
2592 needs to be subtracted from the lower 16 bits to calculate an offset
2593 into the return buffer where this ASCII string resides.
2595 There is no auxiliary data in the response.
2597 ****************************************************************************/
2599 #define usri11_name 0
2600 #define usri11_pad 21
2601 #define usri11_comment 22
2602 #define usri11_usr_comment 26
2603 #define usri11_full_name 30
2604 #define usri11_priv 34
2605 #define usri11_auth_flags 36
2606 #define usri11_password_age 40
2607 #define usri11_homedir 44
2608 #define usri11_parms 48
2609 #define usri11_last_logon 52
2610 #define usri11_last_logoff 56
2611 #define usri11_bad_pw_count 60
2612 #define usri11_num_logons 62
2613 #define usri11_logon_server 64
2614 #define usri11_country_code 68
2615 #define usri11_workstations 70
2616 #define usri11_max_storage 74
2617 #define usri11_units_per_week 78
2618 #define usri11_logon_hours 80
2619 #define usri11_code_page 84
2620 #define usri11_end 86
2622 #define USER_PRIV_GUEST 0
2623 #define USER_PRIV_USER 1
2624 #define USER_PRIV_ADMIN 2
2626 #define AF_OP_PRINT 0
2627 #define AF_OP_COMM 1
2628 #define AF_OP_SERVER 2
2629 #define AF_OP_ACCOUNTS 3
2632 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2633 int mdrcnt,int mprcnt,
2634 char **rdata,char **rparam,
2635 int *rdata_len,int *rparam_len)
2637 char *str1 = param+2;
2638 char *str2 = skip_string(str1,1);
2639 char *UserName = skip_string(str2,1);
2640 char *p = skip_string(UserName,1);
2641 int uLevel = SVAL(p,0);
2644 /* get NIS home of a previously validated user - simeon */
2645 /* With share level security vuid will always be zero.
2646 Don't depend on vuser being non-null !!. JRA */
2647 user_struct *vuser = get_valid_user_struct(vuid);
2649 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2650 vuser->user.unix_name));
2653 *rparam = REALLOC(*rparam,*rparam_len);
2655 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2657 /* check it's a supported variant */
2658 if (strcmp(str1,"zWrLh") != 0) return False;
2661 case 0: p2 = "B21"; break;
2662 case 1: p2 = "B21BB16DWzzWz"; break;
2663 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2664 case 10: p2 = "B21Bzzz"; break;
2665 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2666 default: return False;
2669 if (strcmp(p2,str2) != 0) return False;
2671 *rdata_len = mdrcnt + 1024;
2672 *rdata = REALLOC(*rdata,*rdata_len);
2674 SSVAL(*rparam,0,NERR_Success);
2675 SSVAL(*rparam,2,0); /* converter word */
2678 p2 = p + usri11_end;
2681 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2685 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2690 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2691 pstrcpy(p2,"Comment");
2692 p2 = skip_string(p2,1);
2694 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2695 pstrcpy(p2,"UserComment");
2696 p2 = skip_string(p2,1);
2698 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2699 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2700 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2701 p2 = skip_string(p2,1);
2704 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2706 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2707 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2708 SIVALS(p,usri11_password_age,-1); /* password age */
2709 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2710 pstrcpy(p2, lp_logon_home());
2711 standard_sub_conn(conn, p2);
2712 p2 = skip_string(p2,1);
2713 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2715 p2 = skip_string(p2,1);
2716 SIVAL(p,usri11_last_logon,0); /* last logon */
2717 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2718 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2719 SSVALS(p,usri11_num_logons,-1); /* num logons */
2720 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2721 pstrcpy(p2,"\\\\*");
2722 p2 = skip_string(p2,1);
2723 SSVAL(p,usri11_country_code,0); /* country code */
2725 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2727 p2 = skip_string(p2,1);
2729 SIVALS(p,usri11_max_storage,-1); /* max storage */
2730 SSVAL(p,usri11_units_per_week,168); /* units per week */
2731 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2733 /* a simple way to get logon hours at all times. */
2735 SCVAL(p2,21,0); /* fix zero termination */
2736 p2 = skip_string(p2,1);
2738 SSVAL(p,usri11_code_page,0); /* code page */
2740 if (uLevel == 1 || uLevel == 2)
2742 memset(p+22,' ',16); /* password */
2743 SIVALS(p,38,-1); /* password age */
2745 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2746 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2747 pstrcpy(p2,lp_logon_home());
2748 standard_sub_conn(conn, p2);
2749 p2 = skip_string(p2,1);
2750 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2752 SSVAL(p,52,0); /* flags */
2753 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2754 pstrcpy(p2,lp_logon_script());
2755 standard_sub_conn( conn, p2 );
2756 p2 = skip_string(p2,1);
2759 SIVAL(p,60,0); /* auth_flags */
2760 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2761 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2762 p2 = skip_string(p2,1);
2763 SIVAL(p,68,0); /* urs_comment */
2764 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2766 p2 = skip_string(p2,1);
2767 SIVAL(p,76,0); /* workstations */
2768 SIVAL(p,80,0); /* last_logon */
2769 SIVAL(p,84,0); /* last_logoff */
2770 SIVALS(p,88,-1); /* acct_expires */
2771 SIVALS(p,92,-1); /* max_storage */
2772 SSVAL(p,96,168); /* units_per_week */
2773 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2776 SSVALS(p,102,-1); /* bad_pw_count */
2777 SSVALS(p,104,-1); /* num_logons */
2778 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2779 pstrcpy(p2,"\\\\%L");
2780 standard_sub_conn(conn, p2);
2781 p2 = skip_string(p2,1);
2782 SSVAL(p,110,49); /* country_code */
2783 SSVAL(p,112,860); /* code page */
2787 *rdata_len = PTR_DIFF(p2,*rdata);
2789 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2794 /*******************************************************************
2795 get groups that a user is a member of
2796 ******************************************************************/
2797 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2798 int mdrcnt,int mprcnt,
2799 char **rdata,char **rparam,
2800 int *rdata_len,int *rparam_len)
2802 char *str1 = param+2;
2803 char *str2 = skip_string(str1,1);
2804 char *UserName = skip_string(str2,1);
2805 char *p = skip_string(UserName,1);
2806 int uLevel = SVAL(p,0);
2811 *rparam = REALLOC(*rparam,*rparam_len);
2813 /* check it's a supported varient */
2814 if (strcmp(str1,"zWrLeh") != 0) return False;
2816 case 0: p2 = "B21"; break;
2817 default: return False;
2819 if (strcmp(p2,str2) != 0) return False;
2821 *rdata_len = mdrcnt + 1024;
2822 *rdata = REALLOC(*rdata,*rdata_len);
2824 SSVAL(*rparam,0,NERR_Success);
2825 SSVAL(*rparam,2,0); /* converter word */
2829 /* XXXX we need a real SAM database some day */
2830 pstrcpy(p,"Users"); p += 21; count++;
2831 pstrcpy(p,"Domain Users"); p += 21; count++;
2832 pstrcpy(p,"Guests"); p += 21; count++;
2833 pstrcpy(p,"Domain Guests"); p += 21; count++;
2835 *rdata_len = PTR_DIFF(p,*rdata);
2837 SSVAL(*rparam,4,count); /* is this right?? */
2838 SSVAL(*rparam,6,count); /* is this right?? */
2844 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2845 int mdrcnt,int mprcnt,
2846 char **rdata,char **rparam,
2847 int *rdata_len,int *rparam_len)
2849 char *str1 = param+2;
2850 char *str2 = skip_string(str1,1);
2851 char *p = skip_string(str2,1);
2853 struct pack_desc desc;
2859 memset((char *)&desc,'\0',sizeof(desc));
2861 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2863 /* check it's a supported varient */
2864 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2865 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2866 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2868 desc.buflen = mdrcnt;
2869 desc.subformat = NULL;
2872 if (init_package(&desc,1,0))
2874 PACKI(&desc,"W",0); /* code */
2875 PACKS(&desc,"B21",name); /* eff. name */
2876 PACKS(&desc,"B",""); /* pad */
2878 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2879 PACKI(&desc,"D",0); /* auth flags XXX */
2880 PACKI(&desc,"W",0); /* num logons */
2881 PACKI(&desc,"W",0); /* bad pw count */
2882 PACKI(&desc,"D",0); /* last logon */
2883 PACKI(&desc,"D",-1); /* last logoff */
2884 PACKI(&desc,"D",-1); /* logoff time */
2885 PACKI(&desc,"D",-1); /* kickoff time */
2886 PACKI(&desc,"D",0); /* password age */
2887 PACKI(&desc,"D",0); /* password can change */
2888 PACKI(&desc,"D",-1); /* password must change */
2891 fstrcpy(mypath,"\\\\");
2892 fstrcat(mypath,local_machine);
2894 PACKS(&desc,"z",mypath); /* computer */
2896 PACKS(&desc,"z",global_myworkgroup);/* domain */
2898 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2899 /* made sure all macros are fully substituted and available */
2901 pstring logon_script;
2902 pstrcpy(logon_script,lp_logon_script());
2903 standard_sub_conn( conn, logon_script );
2904 PACKS(&desc,"z", logon_script); /* script path */
2906 /* End of JHT mods */
2908 PACKI(&desc,"D",0x00000000); /* reserved */
2911 *rdata_len = desc.usedlen;
2913 *rparam = REALLOC(*rparam,*rparam_len);
2914 SSVALS(*rparam,0,desc.errcode);
2916 SSVAL(*rparam,4,desc.neededlen);
2918 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2923 /****************************************************************************
2924 api_WAccessGetUserPerms
2925 ****************************************************************************/
2926 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2927 int mdrcnt,int mprcnt,
2928 char **rdata,char **rparam,
2929 int *rdata_len,int *rparam_len)
2931 char *str1 = param+2;
2932 char *str2 = skip_string(str1,1);
2933 char *user = skip_string(str2,1);
2934 char *resource = skip_string(user,1);
2936 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2938 /* check it's a supported varient */
2939 if (strcmp(str1,"zzh") != 0) return False;
2940 if (strcmp(str2,"") != 0) return False;
2943 *rparam = REALLOC(*rparam,*rparam_len);
2944 SSVALS(*rparam,0,0); /* errorcode */
2945 SSVAL(*rparam,2,0); /* converter word */
2946 SSVAL(*rparam,4,0x7f); /* permission flags */
2951 /****************************************************************************
2952 api_WPrintJobEnumerate
2953 ****************************************************************************/
2954 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2955 int mdrcnt,int mprcnt,
2956 char **rdata,char **rparam,
2957 int *rdata_len,int *rparam_len)
2959 char *str1 = param+2;
2960 char *str2 = skip_string(str1,1);
2961 char *p = skip_string(str2,1);
2967 struct pack_desc desc;
2968 print_queue_struct *queue=NULL;
2969 print_status_struct status;
2974 memset((char *)&desc,'\0',sizeof(desc));
2975 memset((char *)&status,'\0',sizeof(status));
2977 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2979 /* check it's a supported varient */
2980 if (strcmp(str1,"WWrLh") != 0) return False;
2981 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2984 snum = print_job_snum(job);
2986 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2988 count = print_queue_status(snum,&queue,&status);
2989 for (i = 0; i < count; i++) {
2990 if (queue[i].job == job) break;
2994 *rdata = REALLOC(*rdata,mdrcnt);
2996 desc.buflen = mdrcnt;
2999 * Don't return data but need to get correct length
3000 * init_package will return wrong size if buflen=0
3002 desc.buflen = getlen(desc.format);
3003 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3006 if (init_package(&desc,1,0)) {
3008 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3009 *rdata_len = desc.usedlen;
3012 desc.errcode = NERR_JobNotFound;
3018 *rparam = REALLOC(*rparam,*rparam_len);
3019 SSVALS(*rparam,0,desc.errcode);
3021 SSVAL(*rparam,4,desc.neededlen);
3026 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3030 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3031 int mdrcnt,int mprcnt,
3032 char **rdata,char **rparam,
3033 int *rdata_len,int *rparam_len)
3035 char *str1 = param+2;
3036 char *str2 = skip_string(str1,1);
3037 char *p = skip_string(str2,1);
3043 struct pack_desc desc;
3044 print_queue_struct *queue=NULL;
3045 print_status_struct status;
3047 memset((char *)&desc,'\0',sizeof(desc));
3048 memset((char *)&status,'\0',sizeof(status));
3050 p = skip_string(p,1);
3053 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3055 /* check it's a supported varient */
3056 if (strcmp(str1,"zWrLeh") != 0) return False;
3057 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
3058 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3060 snum = lp_servicenumber(name);
3061 if (snum < 0 && pcap_printername_ok(name,NULL)) {
3062 int pnum = lp_servicenumber(PRINTERS_NAME);
3064 lp_add_printer(name,pnum);
3065 snum = lp_servicenumber(name);
3069 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3071 count = print_queue_status(snum,&queue,&status);
3072 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3074 desc.buflen = mdrcnt;
3076 if (init_package(&desc,count,0)) {
3078 for (i = 0; i < count; i++) {
3079 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3080 if (desc.errcode == NERR_Success) succnt = i+1;
3084 *rdata_len = desc.usedlen;
3087 *rparam = REALLOC(*rparam,*rparam_len);
3088 SSVALS(*rparam,0,desc.errcode);
3090 SSVAL(*rparam,4,succnt);
3091 SSVAL(*rparam,6,count);
3095 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3099 static int check_printdest_info(struct pack_desc* desc,
3100 int uLevel, char* id)
3102 desc->subformat = NULL;
3104 case 0: desc->format = "B9"; break;
3105 case 1: desc->format = "B9B21WWzW"; break;
3106 case 2: desc->format = "z"; break;
3107 case 3: desc->format = "zzzWWzzzWW"; break;
3108 default: return False;
3110 if (strcmp(desc->format,id) != 0) return False;
3114 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3115 struct pack_desc* desc)
3118 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3119 buf[sizeof(buf)-1] = 0;
3122 PACKS(desc,"B9",buf); /* szName */
3124 PACKS(desc,"B21",""); /* szUserName */
3125 PACKI(desc,"W",0); /* uJobId */
3126 PACKI(desc,"W",0); /* fsStatus */
3127 PACKS(desc,"z",""); /* pszStatus */
3128 PACKI(desc,"W",0); /* time */
3131 if (uLevel == 2 || uLevel == 3) {
3132 PACKS(desc,"z",buf); /* pszPrinterName */
3134 PACKS(desc,"z",""); /* pszUserName */
3135 PACKS(desc,"z",""); /* pszLogAddr */
3136 PACKI(desc,"W",0); /* uJobId */
3137 PACKI(desc,"W",0); /* fsStatus */
3138 PACKS(desc,"z",""); /* pszStatus */
3139 PACKS(desc,"z",""); /* pszComment */
3140 PACKS(desc,"z","NULL"); /* pszDrivers */
3141 PACKI(desc,"W",0); /* time */
3142 PACKI(desc,"W",0); /* pad1 */
3147 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3148 int mdrcnt,int mprcnt,
3149 char **rdata,char **rparam,
3150 int *rdata_len,int *rparam_len)
3152 char *str1 = param+2;
3153 char *str2 = skip_string(str1,1);
3154 char *p = skip_string(str2,1);
3155 char* PrinterName = p;
3157 struct pack_desc desc;
3161 memset((char *)&desc,'\0',sizeof(desc));
3163 p = skip_string(p,1);
3166 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3168 /* check it's a supported varient */
3169 if (strcmp(str1,"zWrLh") != 0) return False;
3170 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3172 snum = lp_servicenumber(PrinterName);
3173 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3174 int pnum = lp_servicenumber(PRINTERS_NAME);
3176 lp_add_printer(PrinterName,pnum);
3177 snum = lp_servicenumber(PrinterName);
3183 desc.errcode = NERR_DestNotFound;
3188 *rdata = REALLOC(*rdata,mdrcnt);
3190 desc.buflen = mdrcnt;
3193 * Don't return data but need to get correct length
3194 * init_package will return wrong size if buflen=0
3196 desc.buflen = getlen(desc.format);
3197 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3199 if (init_package(&desc,1,0)) {
3200 fill_printdest_info(conn,snum,uLevel,&desc);
3202 *rdata_len = desc.usedlen;
3206 *rparam = REALLOC(*rparam,*rparam_len);
3207 SSVALS(*rparam,0,desc.errcode);
3209 SSVAL(*rparam,4,desc.neededlen);
3211 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3216 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3217 int mdrcnt,int mprcnt,
3218 char **rdata,char **rparam,
3219 int *rdata_len,int *rparam_len)
3221 char *str1 = param+2;
3222 char *str2 = skip_string(str1,1);
3223 char *p = skip_string(str2,1);
3227 struct pack_desc desc;
3228 int services = lp_numservices();
3230 memset((char *)&desc,'\0',sizeof(desc));
3234 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3236 /* check it's a supported varient */
3237 if (strcmp(str1,"WrLeh") != 0) return False;
3238 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3241 for (i = 0; i < services; i++)
3242 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3245 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3247 desc.buflen = mdrcnt;
3248 if (init_package(&desc,queuecnt,0)) {
3251 for (i = 0; i < services; i++) {
3252 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3253 fill_printdest_info(conn,i,uLevel,&desc);
3255 if (desc.errcode == NERR_Success) succnt = n;
3260 *rdata_len = desc.usedlen;
3263 *rparam = REALLOC(*rparam,*rparam_len);
3264 SSVALS(*rparam,0,desc.errcode);
3266 SSVAL(*rparam,4,succnt);
3267 SSVAL(*rparam,6,queuecnt);
3269 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3273 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3274 int mdrcnt,int mprcnt,
3275 char **rdata,char **rparam,
3276 int *rdata_len,int *rparam_len)
3278 char *str1 = param+2;
3279 char *str2 = skip_string(str1,1);
3280 char *p = skip_string(str2,1);
3283 struct pack_desc desc;
3285 memset((char *)&desc,'\0',sizeof(desc));
3289 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3291 /* check it's a supported varient */
3292 if (strcmp(str1,"WrLeh") != 0) return False;
3293 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3295 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3297 desc.buflen = mdrcnt;
3298 if (init_package(&desc,1,0)) {
3299 PACKS(&desc,"B41","NULL");
3302 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3304 *rdata_len = desc.usedlen;
3307 *rparam = REALLOC(*rparam,*rparam_len);
3308 SSVALS(*rparam,0,desc.errcode);
3310 SSVAL(*rparam,4,succnt);
3313 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3317 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3318 int mdrcnt,int mprcnt,
3319 char **rdata,char **rparam,
3320 int *rdata_len,int *rparam_len)
3322 char *str1 = param+2;
3323 char *str2 = skip_string(str1,1);
3324 char *p = skip_string(str2,1);
3327 struct pack_desc desc;
3329 memset((char *)&desc,'\0',sizeof(desc));
3333 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3335 /* check it's a supported varient */
3336 if (strcmp(str1,"WrLeh") != 0) return False;
3337 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3339 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3341 desc.buflen = mdrcnt;
3343 if (init_package(&desc,1,0)) {
3344 PACKS(&desc,"B13","lpd");
3347 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3349 *rdata_len = desc.usedlen;
3352 *rparam = REALLOC(*rparam,*rparam_len);
3353 SSVALS(*rparam,0,desc.errcode);
3355 SSVAL(*rparam,4,succnt);
3358 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3362 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3363 int mdrcnt,int mprcnt,
3364 char **rdata,char **rparam,
3365 int *rdata_len,int *rparam_len)
3367 char *str1 = param+2;
3368 char *str2 = skip_string(str1,1);
3369 char *p = skip_string(str2,1);
3372 struct pack_desc desc;
3374 memset((char *)&desc,'\0',sizeof(desc));
3378 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3380 /* check it's a supported varient */
3381 if (strcmp(str1,"WrLeh") != 0) return False;
3382 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3384 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3385 memset((char *)&desc,'\0',sizeof(desc));
3387 desc.buflen = mdrcnt;
3389 if (init_package(&desc,1,0)) {
3390 PACKS(&desc,"B13","lp0");
3393 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3395 *rdata_len = desc.usedlen;
3398 *rparam = REALLOC(*rparam,*rparam_len);
3399 SSVALS(*rparam,0,desc.errcode);
3401 SSVAL(*rparam,4,succnt);
3404 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3408 /****************************************************************************
3409 The buffer was too small
3410 ****************************************************************************/
3412 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3413 int mdrcnt,int mprcnt,
3414 char **rdata,char **rparam,
3415 int *rdata_len,int *rparam_len)
3417 *rparam_len = MIN(*rparam_len,mprcnt);
3418 *rparam = REALLOC(*rparam,*rparam_len);
3422 SSVAL(*rparam,0,NERR_BufTooSmall);
3424 DEBUG(3,("Supplied buffer too small in API command\n"));
3430 /****************************************************************************
3431 The request is not supported
3432 ****************************************************************************/
3434 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3435 int mdrcnt,int mprcnt,
3436 char **rdata,char **rparam,
3437 int *rdata_len,int *rparam_len)
3440 *rparam = REALLOC(*rparam,*rparam_len);
3444 SSVAL(*rparam,0,NERR_notsupported);
3445 SSVAL(*rparam,2,0); /* converter word */
3447 DEBUG(3,("Unsupported API command\n"));
3459 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3460 int,int,char **,char **,int *,int *);
3462 } api_commands[] = {
3463 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum,0},
3464 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo,0},
3465 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd,0},
3466 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo,0},
3467 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum,0},
3468 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers,0},
3469 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum,0},
3470 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo,0},
3471 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups,0},
3472 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo,0},
3473 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum,0},
3474 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo,0},
3475 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl,0},
3476 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl,0},
3477 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate,0},
3478 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo,0},
3479 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel,0},
3480 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel,0},
3481 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel,0},
3482 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum,0},
3483 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo,0},
3484 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD,0},
3485 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl,0},
3486 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum,0},
3487 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms,0},
3488 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword,0},
3489 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon,0},
3490 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo,0},
3491 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum,0},
3492 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum,0},
3493 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum,0},
3494 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword,0},
3495 {NULL, -1, api_Unsupported,0}};
3498 /****************************************************************************
3499 Handle remote api calls
3500 ****************************************************************************/
3502 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3503 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3507 char *rparam = NULL;
3514 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3518 api_command = SVAL(params,0);
3520 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3523 skip_string(params+2,1),
3524 tdscnt,tpscnt,mdrcnt,mprcnt));
3526 for (i=0;api_commands[i].name;i++) {
3527 if (api_commands[i].id == api_command && api_commands[i].fn) {
3528 DEBUG(3,("Doing %s\n",api_commands[i].name));
3533 rdata = (char *)malloc(1024);
3535 memset(rdata,'\0',1024);
3537 rparam = (char *)malloc(1024);
3539 memset(rparam,'\0',1024);
3541 if(!rdata || !rparam) {
3542 DEBUG(0,("api_reply: malloc fail !\n"));
3546 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3547 &rdata,&rparam,&rdata_len,&rparam_len);
3550 if (rdata_len > mdrcnt ||
3551 rparam_len > mprcnt) {
3552 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3553 &rdata,&rparam,&rdata_len,&rparam_len);
3556 /* if we get False back then it's actually unsupported */
3558 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3559 &rdata,&rparam,&rdata_len,&rparam_len);
3561 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);