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 int DEBUGLEVEL;
38 extern fstring local_machine;
39 extern pstring global_myname;
40 extern fstring global_myworkgroup;
42 #define NERR_Success 0
43 #define NERR_badpass 86
44 #define NERR_notsupported 50
46 #define NERR_BASE (2100)
47 #define NERR_BufTooSmall (NERR_BASE+23)
48 #define NERR_JobNotFound (NERR_BASE+51)
49 #define NERR_DestNotFound (NERR_BASE+52)
51 #define ACCESS_READ 0x01
52 #define ACCESS_WRITE 0x02
53 #define ACCESS_CREATE 0x04
55 #define SHPWLEN 8 /* share password length */
57 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
58 int mdrcnt,int mprcnt,
59 char **rdata,char **rparam,
60 int *rdata_len,int *rparam_len);
61 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
62 int mdrcnt,int mprcnt,
63 char **rdata,char **rparam,
64 int *rdata_len,int *rparam_len);
67 static int CopyExpanded(connection_struct *conn,
68 int snum, char** dst, char* src, int* n)
73 if (!src || !dst || !n || !(*dst)) return(0);
75 StrnCpy(buf,src,sizeof(buf)/2);
76 pstring_sub(buf,"%S",lp_servicename(snum));
77 standard_sub_conn(conn,buf);
78 l = push_ascii(*dst,buf,*n-1, STR_TERMINATE);
84 static int CopyAndAdvance(char** dst, char* src, int* n)
87 if (!src || !dst || !n || !(*dst)) return(0);
88 l = push_ascii(*dst,src,*n-1, STR_TERMINATE);
94 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
98 StrnCpy(buf,s,sizeof(buf)/2);
99 pstring_sub(buf,"%S",lp_servicename(snum));
100 standard_sub_conn(conn,buf);
101 return strlen(buf) + 1;
104 static char* Expand(connection_struct *conn, int snum, char* s)
107 if (!s) return(NULL);
108 StrnCpy(buf,s,sizeof(buf)/2);
109 pstring_sub(buf,"%S",lp_servicename(snum));
110 standard_sub_conn(conn,buf);
114 /*******************************************************************
115 check a API string for validity when we only need to check the prefix
116 ******************************************************************/
117 static BOOL prefix_ok(char *str,char *prefix)
119 return(strncmp(str,prefix,strlen(prefix)) == 0);
123 char* format; /* formatstring for structure */
124 char* subformat; /* subformat for structure */
125 char* base; /* baseaddress of buffer */
126 int buflen; /* remaining size for fixed part; on init: length of base */
127 int subcount; /* count of substructures */
128 char* structbuf; /* pointer into buffer for remaining fixed part */
129 int stringlen; /* remaining size for variable part */
130 char* stringbuf; /* pointer into buffer for remaining variable part */
131 int neededlen; /* total needed size */
132 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
133 char* curpos; /* current position; pointer into format or subformat */
137 static int get_counter(char** p)
140 if (!p || !(*p)) return(1);
141 if (!isdigit((int)**p)) return 1;
145 n = 10 * n + (i - '0');
152 static int getlen(char* p)
158 case 'W': /* word (2 byte) */
161 case 'K': /* status word? (2 byte) */
164 case 'N': /* count of substructures (word) at end */
167 case 'D': /* double word (4 byte) */
168 case 'z': /* offset to zero terminated string (4 byte) */
169 case 'l': /* offset to user data (4 byte) */
172 case 'b': /* offset to data (with counter) (4 byte) */
176 case 'B': /* byte (with optional counter) */
177 n += get_counter(&p);
184 static BOOL init_package(struct pack_desc* p, int count, int subcount)
189 if (!p->format || !p->base) return(False);
191 i = count * getlen(p->format);
192 if (p->subformat) i += subcount * getlen(p->subformat);
193 p->structbuf = p->base;
197 p->curpos = p->format;
203 * This is the old error code we used. Aparently
204 * WinNT/2k systems return ERRbuftoosmall (2123) and
205 * OS/2 needs this. I'm leaving this here so we can revert
208 p->errcode = ERRmoredata;
210 p->errcode = ERRbuftoosmall;
214 p->errcode = NERR_Success;
217 p->stringbuf = p->base + i;
219 return(p->errcode == NERR_Success);
222 static int package(struct pack_desc* p, ...)
225 int needed=0, stringneeded;
227 int is_string=0, stringused;
234 p->curpos = p->format;
236 p->curpos = p->subformat;
241 str = va_arg(args,char*);
242 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
251 switch( *p->curpos++ ) {
252 case 'W': /* word (2 byte) */
254 temp = va_arg(args,int);
255 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
257 case 'K': /* status word? (2 byte) */
259 temp = va_arg(args,int);
260 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
262 case 'N': /* count of substructures (word) at end */
264 p->subcount = va_arg(args,int);
265 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
267 case 'D': /* double word (4 byte) */
269 temp = va_arg(args,int);
270 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
272 case 'B': /* byte (with optional counter) */
273 needed = get_counter(&p->curpos);
275 char *s = va_arg(args,char*);
276 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
279 case 'z': /* offset to zero terminated string (4 byte) */
280 str = va_arg(args,char*);
281 stringneeded = (str ? strlen(str)+1 : 0);
284 case 'l': /* offset to user data (4 byte) */
285 str = va_arg(args,char*);
286 stringneeded = va_arg(args,int);
289 case 'b': /* offset to data (with counter) (4 byte) */
290 str = va_arg(args,char*);
291 stringneeded = get_counter(&p->curpos);
296 if (stringneeded >= 0) {
298 if (p->buflen >= needed) {
299 stringused = stringneeded;
300 if (stringused > p->stringlen) {
301 stringused = (is_string ? p->stringlen : 0);
302 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
305 SIVAL(p->structbuf,0,0);
307 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
308 memcpy(p->stringbuf,str?str:"",stringused);
309 if (is_string) p->stringbuf[stringused-1] = '\0';
310 p->stringbuf += stringused;
311 p->stringlen -= stringused;
312 p->usedlen += stringused;
315 p->neededlen += stringneeded;
317 p->neededlen += needed;
318 if (p->buflen >= needed) {
319 p->structbuf += needed;
321 p->usedlen += needed;
324 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
330 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
331 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
333 #define PACK(desc,t,v) package(desc,v)
334 #define PACKl(desc,t,v,l) package(desc,v,l)
337 static void PACKI(struct pack_desc* desc,char *t,int v)
342 static void PACKS(struct pack_desc* desc,char *t,char *v)
348 /****************************************************************************
350 ****************************************************************************/
351 static void PackDriverData(struct pack_desc* desc)
353 char drivdata[4+4+32];
354 SIVAL(drivdata,0,sizeof drivdata); /* cb */
355 SIVAL(drivdata,4,1000); /* lVersion */
356 memset(drivdata+8,0,32); /* szDeviceName */
357 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
358 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
361 static int check_printq_info(struct pack_desc* desc,
362 int uLevel, char *id1, char *id2)
364 desc->subformat = NULL;
367 desc->format = "B13";
370 desc->format = "B13BWWWzzzzzWW";
373 desc->format = "B13BWWWzzzzzWN";
374 desc->subformat = "WB21BB16B10zWWzDDz";
377 desc->format = "zWWWWzzzzWWzzl";
380 desc->format = "zWWWWzzzzWNzzl";
381 desc->subformat = "WWzWWDDzz";
390 desc->format = "WzzzzzzzzN";
391 desc->subformat = "z";
393 default: return False;
395 if (strcmp(desc->format,id1) != 0) return False;
396 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
401 #define RAP_JOB_STATUS_QUEUED 0
402 #define RAP_JOB_STATUS_PAUSED 1
403 #define RAP_JOB_STATUS_SPOOLING 2
404 #define RAP_JOB_STATUS_PRINTING 3
405 #define RAP_JOB_STATUS_PRINTED 4
407 #define RAP_QUEUE_STATUS_PAUSED 1
408 #define RAP_QUEUE_STATUS_ERROR 2
410 /* turn a print job status into a on the wire status
412 static int printj_status(int v)
416 return RAP_JOB_STATUS_QUEUED;
418 return RAP_JOB_STATUS_PAUSED;
420 return RAP_JOB_STATUS_SPOOLING;
422 return RAP_JOB_STATUS_PRINTING;
427 /* turn a print queue status into a on the wire status
429 static int printq_status(int v)
435 return RAP_QUEUE_STATUS_PAUSED;
437 return RAP_QUEUE_STATUS_ERROR;
440 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
441 struct pack_desc* desc,
442 print_queue_struct* queue, int n)
444 time_t t = queue->time;
446 /* the client expects localtime */
449 PACKI(desc,"W",queue->job); /* uJobId */
451 PACKS(desc,"B21",queue->user); /* szUserName */
452 PACKS(desc,"B",""); /* pad */
453 PACKS(desc,"B16",""); /* szNotifyName */
454 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
455 PACKS(desc,"z",""); /* pszParms */
456 PACKI(desc,"W",n+1); /* uPosition */
457 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
458 PACKS(desc,"z",""); /* pszStatus */
459 PACKI(desc,"D",t); /* ulSubmitted */
460 PACKI(desc,"D",queue->size); /* ulSize */
461 PACKS(desc,"z",queue->file); /* pszComment */
463 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
464 PACKI(desc,"W",queue->priority); /* uPriority */
465 PACKS(desc,"z",queue->user); /* pszUserName */
466 PACKI(desc,"W",n+1); /* uPosition */
467 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
468 PACKI(desc,"D",t); /* ulSubmitted */
469 PACKI(desc,"D",queue->size); /* ulSize */
470 PACKS(desc,"z","Samba"); /* pszComment */
471 PACKS(desc,"z",queue->file); /* pszDocument */
473 PACKS(desc,"z",""); /* pszNotifyName */
474 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
475 PACKS(desc,"z",""); /* pszParms */
476 PACKS(desc,"z",""); /* pszStatus */
477 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
478 PACKS(desc,"z","lpd"); /* pszQProcName */
479 PACKS(desc,"z",""); /* pszQProcParms */
480 PACKS(desc,"z","NULL"); /* pszDriverName */
481 PackDriverData(desc); /* pDriverData */
482 PACKS(desc,"z",""); /* pszPrinterName */
483 } else if (uLevel == 4) { /* OS2 */
484 PACKS(desc,"z",""); /* pszSpoolFileName */
485 PACKS(desc,"z",""); /* pszPortName */
486 PACKS(desc,"z",""); /* pszStatus */
487 PACKI(desc,"D",0); /* ulPagesSpooled */
488 PACKI(desc,"D",0); /* ulPagesSent */
489 PACKI(desc,"D",0); /* ulPagesPrinted */
490 PACKI(desc,"D",0); /* ulTimePrinted */
491 PACKI(desc,"D",0); /* ulExtendJobStatus */
492 PACKI(desc,"D",0); /* ulStartPage */
493 PACKI(desc,"D",0); /* ulEndPage */
498 /********************************************************************
499 Return a driver name given an snum.
500 Looks in a tdb first. Returns True if from tdb, False otherwise.
501 ********************************************************************/
503 static BOOL get_driver_name(int snum, pstring drivername)
505 NT_PRINTER_INFO_LEVEL *info = NULL;
508 get_a_printer (&info, 2, lp_servicename(snum));
510 pstrcpy( drivername, info->info_2->drivername);
512 free_a_printer(&info, 2);
514 pstrcpy( drivername, lp_printerdriver(snum));
520 /********************************************************************
521 Respond to the DosPrintQInfo command with a level of 52
522 This is used to get printer driver information for Win9x clients
523 ********************************************************************/
524 static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
525 struct pack_desc* desc,
526 int count, print_queue_struct* queue,
527 print_status_struct* status)
531 pstring tok,driver,datafile,langmon,helpfile,datatype;
540 * Check in the tdb *first* before checking the legacy
541 * files. This allows an NT upload to take precedence over
542 * the existing fileset. JRA.
544 * we need to lookup the driver name prior to making the call
545 * to get_a_printer_driver_9x_compatible() and not rely on the
546 * 'print driver' parameter --jerry
550 if ((get_driver_name(snum,drivername)) &&
551 ((ok = get_a_printer_driver_9x_compatible(gen_line, drivername)) == True))
555 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line));
559 /* didn't find driver in tdb */
561 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
562 snum, drivername, lp_driverfile(snum)));
564 lines = file_lines_load(lp_driverfile(snum),NULL);
567 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),
569 desc->errcode=NERR_notsupported;
573 /* lookup the long printer driver name in the file description */
574 for (i=0;lines[i] && !ok;i++)
577 if (next_token(&p,tok,":",sizeof(tok)) &&
578 (strlen(drivername) == strlen(tok)) &&
579 (!strncmp(tok,drivername,strlen(drivername))))
588 /* driver file name */
589 if (!next_token(&p,driver,":",sizeof(driver)))
593 if (!next_token(&p,datafile,":",sizeof(datafile)))
597 * for the next tokens - which may be empty - I have
598 * to check for empty tokens first because the
599 * next_token function will skip all empty token
608 else if (!next_token(&p,helpfile,":",sizeof(helpfile)))
611 /* language monitor */
617 else if (!next_token(&p,langmon,":",sizeof(langmon)))
620 /* default data type */
621 if (!next_token(&p,datatype,":",sizeof(datatype)))
624 PACKI(desc,"W",0x0400); /* don't know */
625 PACKS(desc,"z",drivername); /* long printer name */
626 PACKS(desc,"z",driver); /* Driverfile Name */
627 PACKS(desc,"z",datafile); /* Datafile name */
628 PACKS(desc,"z",langmon); /* language monitor */
631 fstrcpy(location, "\\\\");
632 fstrcat(location, global_myname);
633 fstrcat(location, "\\print$\\WIN40\\0");
634 PACKS(desc,"z",location); /* share to retrieve files */
638 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
640 PACKS(desc,"z",datatype); /* default data type */
641 PACKS(desc,"z",helpfile); /* helpfile name */
642 PACKS(desc,"z",driver); /* driver name */
644 DEBUG(3,("printerdriver:%s:\n",drivername));
645 DEBUG(3,("Driver:%s:\n",driver));
646 DEBUG(3,("Data File:%s:\n",datafile));
647 DEBUG(3,("Language Monitor:%s:\n",langmon));
649 DEBUG(3,("lp_driverlocation:%s:\n",location));
651 DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum)));
652 DEBUG(3,("Data Type:%s:\n",datatype));
653 DEBUG(3,("Help File:%s:\n",helpfile));
654 PACKI(desc,"N",count); /* number of files to copy */
656 for (i=0;i<count;i++)
658 /* no need to check return value here
659 * - it was already tested in
660 * get_printerdrivernumber */
661 next_token(&p,tok,",",sizeof(tok));
662 PACKS(desc,"z",tok); /* driver files to copy */
663 DEBUG(3,("file:%s:\n",tok));
666 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
667 SERVICE(snum),count));
669 desc->errcode=NERR_Success;
675 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
676 desc->errcode=NERR_notsupported;
679 file_lines_free(lines);
683 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
684 struct pack_desc* desc,
685 int count, print_queue_struct* queue,
686 print_status_struct* status)
691 PACKS(desc,"B13",SERVICE(snum));
696 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
699 PACKI(desc,"K",printq_status(status->status));
703 if (uLevel == 1 || uLevel == 2) {
704 PACKS(desc,"B",""); /* alignment */
705 PACKI(desc,"W",5); /* priority */
706 PACKI(desc,"W",0); /* start time */
707 PACKI(desc,"W",0); /* until time */
708 PACKS(desc,"z",""); /* pSepFile */
709 PACKS(desc,"z","lpd"); /* pPrProc */
710 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
711 PACKS(desc,"z",""); /* pParms */
713 PACKS(desc,"z","UNKNOWN PRINTER");
714 PACKI(desc,"W",LPSTAT_ERROR);
716 else if (!status || !status->message[0]) {
717 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
718 PACKI(desc,"W",LPSTAT_OK); /* status */
720 PACKS(desc,"z",status->message);
721 PACKI(desc,"W",printq_status(status->status)); /* status */
723 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
726 if (uLevel == 3 || uLevel == 4) {
729 PACKI(desc,"W",5); /* uPriority */
730 PACKI(desc,"W",0); /* uStarttime */
731 PACKI(desc,"W",0); /* uUntiltime */
732 PACKI(desc,"W",5); /* pad1 */
733 PACKS(desc,"z",""); /* pszSepFile */
734 PACKS(desc,"z","WinPrint"); /* pszPrProc */
735 PACKS(desc,"z",NULL); /* pszParms */
736 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
737 /* "don't ask" that it's done this way to fix corrupted
738 Win9X/ME printer comments. */
740 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
742 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
744 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
745 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
746 get_driver_name(snum,drivername);
747 PACKS(desc,"z",drivername); /* pszDriverName */
748 PackDriverData(desc); /* pDriverData */
751 if (uLevel == 2 || uLevel == 4) {
753 for (i=0;i<count;i++)
754 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
758 fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status);
762 /* This function returns the number of files for a given driver */
763 static int get_printerdrivernumber(int snum)
774 * Check in the tdb *first* before checking the legacy
775 * files. This allows an NT upload to take precedence over
776 * the existing fileset. JRA.
778 * we need to lookup the driver name prior to making the call
779 * to get_a_printer_driver_9x_compatible() and not rely on the
780 * 'print driver' parameter --jerry
783 if ((get_driver_name(snum,drivername)) &&
784 (ok = get_a_printer_driver_9x_compatible(gen_line, drivername) == True))
787 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line));
791 /* didn't find driver in tdb */
793 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
794 snum, drivername, lp_driverfile(snum)));
796 lines = file_lines_load(lp_driverfile(snum), NULL);
799 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
803 /* lookup the long printer driver name in the file description */
804 for (i=0;lines[i] && !ok;i++)
807 if (next_token(&p,tok,":",sizeof(tok)) &&
808 (strlen(drivername) == strlen(tok)) &&
809 (!strncmp(tok,drivername,strlen(drivername))))
821 if (*p++ == ':') i--;
824 DEBUG(3,("Can't determine number of printer driver files\n"));
828 /* count the number of files */
829 while (next_token(&p,tok,",",sizeof(tok)))
837 file_lines_free(lines);
842 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
843 uint16 vuid, char *param,char *data,
844 int mdrcnt,int mprcnt,
845 char **rdata,char **rparam,
846 int *rdata_len,int *rparam_len)
848 char *str1 = param+2;
849 char *str2 = skip_string(str1,1);
850 char *p = skip_string(str2,1);
856 struct pack_desc desc;
857 print_queue_struct *queue=NULL;
858 print_status_struct status;
861 memset((char *)&status,'\0',sizeof(status));
862 memset((char *)&desc,'\0',sizeof(desc));
864 p = skip_string(p,1);
868 /* remove any trailing username */
869 if ((p = strchr_m(QueueName,'%')))
872 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
874 /* check it's a supported varient */
875 if (!prefix_ok(str1,"zWrLh"))
877 if (!check_printq_info(&desc,uLevel,str2,str3)) {
879 * Patch from Scott Moomaw <scott@bridgewater.edu>
880 * to return the 'invalid info level' error if an
881 * unknown level was requested.
885 *rparam = REALLOC(*rparam,*rparam_len);
886 SSVALS(*rparam,0,ERRunknownlevel);
892 snum = lp_servicenumber(QueueName);
893 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
894 int pnum = lp_servicenumber(PRINTERS_NAME);
896 lp_add_printer(QueueName,pnum);
897 snum = lp_servicenumber(QueueName);
901 if (snum < 0 || !VALID_SNUM(snum))
905 count = get_printerdrivernumber(snum);
906 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
908 count = print_queue_status(snum, &queue,&status);
912 *rdata = REALLOC(*rdata,mdrcnt);
914 desc.buflen = mdrcnt;
917 * Don't return data but need to get correct length
918 * init_package will return wrong size if buflen=0
920 desc.buflen = getlen(desc.format);
921 desc.base = tmpdata = (char *) malloc (desc.buflen);
924 if (init_package(&desc,1,count)) {
925 desc.subcount = count;
926 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
929 *rdata_len = desc.usedlen;
932 * We must set the return code to ERRbuftoosmall
933 * in order to support lanman style printing with Win NT/2k
936 if (!mdrcnt && lp_disable_spoolss())
937 desc.errcode = ERRbuftoosmall;
939 *rdata_len = desc.usedlen;
941 *rparam = REALLOC(*rparam,*rparam_len);
942 SSVALS(*rparam,0,desc.errcode);
944 SSVAL(*rparam,4,desc.neededlen);
946 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
954 /****************************************************************************
955 View list of all print jobs on all queues.
956 ****************************************************************************/
958 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
959 int mdrcnt, int mprcnt,
960 char **rdata, char** rparam,
961 int *rdata_len, int *rparam_len)
963 char *param_format = param+2;
964 char *output_format1 = skip_string(param_format,1);
965 char *p = skip_string(output_format1,1);
966 int uLevel = SVAL(p,0);
967 char *output_format2 = p + 4;
968 int services = lp_numservices();
970 struct pack_desc desc;
971 print_queue_struct **queue = NULL;
972 print_status_struct *status = NULL;
973 int* subcntarr = NULL;
974 int queuecnt, subcnt=0, succnt=0;
976 memset((char *)&desc,'\0',sizeof(desc));
978 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
980 if (!prefix_ok(param_format,"WrLeh")) return False;
981 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
983 * Patch from Scott Moomaw <scott@bridgewater.edu>
984 * to return the 'invalid info level' error if an
985 * unknown level was requested.
989 *rparam = REALLOC(*rparam,*rparam_len);
990 SSVALS(*rparam,0,ERRunknownlevel);
997 for (i = 0; i < services; i++)
998 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
1001 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
1002 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1005 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1006 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
1007 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1010 memset(status,0,queuecnt*sizeof(print_status_struct));
1011 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
1012 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1017 for (i = 0; i < services; i++)
1018 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1019 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1020 subcnt += subcntarr[n];
1024 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
1026 desc.buflen = mdrcnt;
1028 if (init_package(&desc,queuecnt,subcnt)) {
1031 for (i = 0; i < services; i++)
1032 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1033 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1035 if (desc.errcode == NERR_Success) succnt = n;
1039 SAFE_FREE(subcntarr);
1041 *rdata_len = desc.usedlen;
1043 *rparam = REALLOC(*rparam,*rparam_len);
1044 SSVALS(*rparam,0,desc.errcode);
1046 SSVAL(*rparam,4,succnt);
1047 SSVAL(*rparam,6,queuecnt);
1049 for (i = 0; i < queuecnt; i++) {
1050 if (queue) SAFE_FREE(queue[i]);
1059 /****************************************************************************
1060 get info level for a server list query
1061 ****************************************************************************/
1062 static BOOL check_server_info(int uLevel, char* id)
1066 if (strcmp(id,"B16") != 0) return False;
1069 if (strcmp(id,"B16BBDz") != 0) return False;
1077 struct srv_info_struct
1087 /*******************************************************************
1088 get server info lists from the files saved by nmbd. Return the
1090 ******************************************************************/
1091 static int get_server_info(uint32 servertype,
1092 struct srv_info_struct **servers,
1098 BOOL local_list_only;
1101 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
1103 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1107 /* request for everything is code for request all servers */
1108 if (servertype == SV_TYPE_ALL)
1109 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1111 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1113 DEBUG(4,("Servertype search: %8x\n",servertype));
1115 for (i=0;lines[i];i++) {
1117 struct srv_info_struct *s;
1118 char *ptr = lines[i];
1121 if (!*ptr) continue;
1123 if (count == alloced) {
1124 struct srv_info_struct *ts;
1127 ts = (struct srv_info_struct *)
1128 Realloc(*servers,sizeof(**servers)*alloced);
1130 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1134 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1136 s = &(*servers)[count];
1138 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1139 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1140 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1141 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1142 /* this allows us to cope with an old nmbd */
1143 pstrcpy(s->domain,global_myworkgroup);
1146 if (sscanf(stype,"%X",&s->type) != 1) {
1147 DEBUG(4,("r:host file "));
1151 /* Filter the servers/domains we return based on what was asked for. */
1153 /* Check to see if we are being asked for a local list only. */
1154 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1155 DEBUG(4,("r: local list only"));
1159 /* doesn't match up: don't want it */
1160 if (!(servertype & s->type)) {
1161 DEBUG(4,("r:serv type "));
1165 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1166 (s->type & SV_TYPE_DOMAIN_ENUM))
1168 DEBUG(4,("s: dom mismatch "));
1172 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1177 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1178 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1182 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1183 s->name, s->type, s->comment, s->domain));
1185 s->server_added = True;
1190 DEBUG(4,("%20s %8x %25s %15s\n",
1191 s->name, s->type, s->comment, s->domain));
1195 file_lines_free(lines);
1200 /*******************************************************************
1201 fill in a server info structure
1202 ******************************************************************/
1203 static int fill_srv_info(struct srv_info_struct *service,
1204 int uLevel, char **buf, int *buflen,
1205 char **stringbuf, int *stringspace, char *baseaddr)
1214 case 0: struct_len = 16; break;
1215 case 1: struct_len = 26; break;
1225 len = strlen(service->comment)+1;
1229 if (buflen) *buflen = struct_len;
1230 if (stringspace) *stringspace = len;
1231 return struct_len + len;
1236 if (*buflen < struct_len) return -1;
1244 p2 = p + struct_len;
1245 l2 = *buflen - struct_len;
1247 if (!baseaddr) baseaddr = p;
1252 push_ascii(p,service->name, 15, STR_TERMINATE);
1256 push_ascii(p,service->name,15, STR_TERMINATE);
1257 SIVAL(p,18,service->type);
1258 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1259 len += CopyAndAdvance(&p2,service->comment,&l2);
1265 *buf = p + struct_len;
1266 *buflen -= struct_len;
1279 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1281 return(strcmp(s1->name,s2->name));
1284 /****************************************************************************
1285 view list of servers available (or possibly domains). The info is
1286 extracted from lists saved by nmbd on the local host
1287 ****************************************************************************/
1288 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1289 int mdrcnt, int mprcnt, char **rdata,
1290 char **rparam, int *rdata_len, int *rparam_len)
1292 char *str1 = param+2;
1293 char *str2 = skip_string(str1,1);
1294 char *p = skip_string(str2,1);
1295 int uLevel = SVAL(p,0);
1296 int buf_len = SVAL(p,2);
1297 uint32 servertype = IVAL(p,4);
1299 int data_len, fixed_len, string_len;
1300 int f_len = 0, s_len = 0;
1301 struct srv_info_struct *servers=NULL;
1302 int counted=0,total=0;
1305 BOOL domain_request;
1308 /* If someone sets all the bits they don't really mean to set
1309 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1312 if (servertype == SV_TYPE_ALL)
1313 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1315 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1316 any other bit (they may just set this bit on it's own) they
1317 want all the locally seen servers. However this bit can be
1318 set on its own so set the requested servers to be
1319 ALL - DOMAIN_ENUM. */
1321 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1322 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1324 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1325 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1329 if (!prefix_ok(str1,"WrLehD")) return False;
1330 if (!check_server_info(uLevel,str2)) return False;
1332 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1333 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1334 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1336 if (strcmp(str1, "WrLehDz") == 0) {
1337 pull_ascii_fstring(domain, p);
1339 fstrcpy(domain, global_myworkgroup);
1342 if (lp_browse_list())
1343 total = get_server_info(servertype,&servers,domain);
1345 data_len = fixed_len = string_len = 0;
1349 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1352 char *lastname=NULL;
1354 for (i=0;i<total;i++)
1356 struct srv_info_struct *s = &servers[i];
1357 if (lastname && strequal(lastname,s->name)) continue;
1359 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1360 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1361 s->name, s->type, s->comment, s->domain));
1363 if (data_len <= buf_len) {
1366 string_len += s_len;
1373 *rdata_len = fixed_len + string_len;
1374 *rdata = REALLOC(*rdata,*rdata_len);
1375 memset(*rdata,'\0',*rdata_len);
1377 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1383 char *lastname=NULL;
1384 int count2 = counted;
1385 for (i = 0; i < total && count2;i++)
1387 struct srv_info_struct *s = &servers[i];
1388 if (lastname && strequal(lastname,s->name)) continue;
1390 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1391 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1392 s->name, s->type, s->comment, s->domain));
1398 *rparam = REALLOC(*rparam,*rparam_len);
1399 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1401 SSVAL(*rparam,4,counted);
1402 SSVAL(*rparam,6,counted+missed);
1406 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1407 domain,uLevel,counted,counted+missed));
1412 /****************************************************************************
1413 command 0x34 - suspected of being a "Lookup Names" stub api
1414 ****************************************************************************/
1415 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1416 int mdrcnt, int mprcnt, char **rdata,
1417 char **rparam, int *rdata_len, int *rparam_len)
1419 char *str1 = param+2;
1420 char *str2 = skip_string(str1,1);
1421 char *p = skip_string(str2,1);
1422 int uLevel = SVAL(p,0);
1423 int buf_len = SVAL(p,2);
1427 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1428 str1, str2, p, uLevel, buf_len));
1430 if (!prefix_ok(str1,"zWrLeh")) return False;
1435 *rparam = REALLOC(*rparam,*rparam_len);
1437 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1439 SSVAL(*rparam,4,counted);
1440 SSVAL(*rparam,6,counted+missed);
1445 /****************************************************************************
1446 get info about a share
1447 ****************************************************************************/
1448 static BOOL check_share_info(int uLevel, char* id)
1452 if (strcmp(id,"B13") != 0) return False;
1455 if (strcmp(id,"B13BWz") != 0) return False;
1458 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1461 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1463 default: return False;
1468 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1469 char** buf, int* buflen,
1470 char** stringbuf, int* stringspace, char* baseaddr)
1479 case 0: struct_len = 13; break;
1480 case 1: struct_len = 20; break;
1481 case 2: struct_len = 40; break;
1482 case 91: struct_len = 68; break;
1490 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1491 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1492 if (buflen) *buflen = struct_len;
1493 if (stringspace) *stringspace = len;
1494 return struct_len + len;
1499 if ((*buflen) < struct_len) return -1;
1507 p2 = p + struct_len;
1508 l2 = (*buflen) - struct_len;
1510 if (!baseaddr) baseaddr = p;
1512 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1518 type = STYPE_DISKTREE;
1519 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1520 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1521 SSVAL(p,14,type); /* device type */
1522 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1523 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1528 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1529 SSVALS(p,22,-1); /* max uses */
1530 SSVAL(p,24,1); /* current uses */
1531 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1532 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1533 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1538 memset(p+40,0,SHPWLEN+2);
1550 (*buf) = p + struct_len;
1551 (*buflen) -= struct_len;
1553 (*stringspace) = l2;
1563 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1564 int mdrcnt,int mprcnt,
1565 char **rdata,char **rparam,
1566 int *rdata_len,int *rparam_len)
1568 char *str1 = param+2;
1569 char *str2 = skip_string(str1,1);
1570 char *netname = skip_string(str2,1);
1571 char *p = skip_string(netname,1);
1572 int uLevel = SVAL(p,0);
1573 int snum = find_service(netname);
1575 if (snum < 0) return False;
1577 /* check it's a supported varient */
1578 if (!prefix_ok(str1,"zWrLh")) return False;
1579 if (!check_share_info(uLevel,str2)) return False;
1581 *rdata = REALLOC(*rdata,mdrcnt);
1583 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1584 if (*rdata_len < 0) return False;
1587 *rparam = REALLOC(*rparam,*rparam_len);
1588 SSVAL(*rparam,0,NERR_Success);
1589 SSVAL(*rparam,2,0); /* converter word */
1590 SSVAL(*rparam,4,*rdata_len);
1595 /****************************************************************************
1596 view list of shares available
1597 ****************************************************************************/
1598 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1599 int mdrcnt,int mprcnt,
1600 char **rdata,char **rparam,
1601 int *rdata_len,int *rparam_len)
1603 char *str1 = param+2;
1604 char *str2 = skip_string(str1,1);
1605 char *p = skip_string(str2,1);
1606 int uLevel = SVAL(p,0);
1607 int buf_len = SVAL(p,2);
1609 int count=lp_numservices();
1610 int total=0,counted=0;
1611 BOOL missed = False;
1613 int data_len, fixed_len, string_len;
1614 int f_len = 0, s_len = 0;
1616 if (!prefix_ok(str1,"WrLeh")) return False;
1617 if (!check_share_info(uLevel,str2)) return False;
1619 data_len = fixed_len = string_len = 0;
1620 for (i=0;i<count;i++)
1621 if (lp_browseable(i) && lp_snum_ok(i))
1624 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1625 if (data_len <= buf_len)
1629 string_len += s_len;
1634 *rdata_len = fixed_len + string_len;
1635 *rdata = REALLOC(*rdata,*rdata_len);
1636 memset(*rdata,0,*rdata_len);
1638 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1642 for (i = 0; i < count;i++)
1643 if (lp_browseable(i) && lp_snum_ok(i))
1644 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1648 *rparam = REALLOC(*rparam,*rparam_len);
1649 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1651 SSVAL(*rparam,4,counted);
1652 SSVAL(*rparam,6,total);
1654 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1655 counted,total,uLevel,
1656 buf_len,*rdata_len,mdrcnt));
1661 /****************************************************************************
1662 view list of groups available
1663 ****************************************************************************/
1664 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1665 int mdrcnt,int mprcnt,
1666 char **rdata,char **rparam,
1667 int *rdata_len,int *rparam_len)
1669 char *str1 = param+2;
1670 char *str2 = skip_string(str1,1);
1671 char *p = skip_string(str2,1);
1672 int uLevel = SVAL(p,0);
1676 if (!prefix_ok(str1,"WrLeh")) return False;
1678 /* check it's a supported variant */
1688 if (strcmp(p2,str2) != 0) return False;
1690 *rdata_len = mdrcnt + 1024;
1691 *rdata = REALLOC(*rdata,*rdata_len);
1693 SSVAL(*rparam,0,NERR_Success);
1694 SSVAL(*rparam,2,0); /* converter word */
1698 /* XXXX we need a real SAM database some day */
1699 pstrcpy(p,"Users"); p += 21; count++;
1700 pstrcpy(p,"Domain Users"); p += 21; count++;
1701 pstrcpy(p,"Guests"); p += 21; count++;
1702 pstrcpy(p,"Domain Guests"); p += 21; count++;
1704 *rdata_len = PTR_DIFF(p,*rdata);
1707 *rparam = REALLOC(*rparam,*rparam_len);
1709 SSVAL(*rparam,4,count); /* is this right?? */
1710 SSVAL(*rparam,6,count); /* is this right?? */
1712 DEBUG(3,("api_RNetGroupEnum gave %d entries\n", count));
1717 /****************************************************************************
1718 view list of groups available
1719 ****************************************************************************/
1720 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1721 int mdrcnt,int mprcnt,
1722 char **rdata,char **rparam,
1723 int *rdata_len,int *rparam_len)
1725 char *str1 = param+2;
1726 char *str2 = skip_string(str1,1);
1727 char *p = skip_string(str2,1);
1728 int uLevel = SVAL(p,0);
1732 if (!prefix_ok(str1,"WrLeh")) return False;
1734 /* check it's a supported variant */
1744 if (strcmp(p2,str2) != 0) return False;
1746 *rdata_len = mdrcnt + 1024;
1747 *rdata = REALLOC(*rdata,*rdata_len);
1749 SSVAL(*rparam,0,NERR_Success);
1750 SSVAL(*rparam,2,0); /* converter word */
1754 /* XXXX we need a real SAM database some day */
1755 pstrcpy(p,"Users"); p += 21; count++;
1756 pstrcpy(p,"Domain Users"); p += 21; count++;
1757 pstrcpy(p,"Guests"); p += 21; count++;
1758 pstrcpy(p,"Domain Guests"); p += 21; count++;
1760 *rdata_len = PTR_DIFF(p,*rdata);
1763 *rparam = REALLOC(*rparam,*rparam_len);
1765 SSVAL(*rparam,4,count); /* is this right?? */
1766 SSVAL(*rparam,6,count); /* is this right?? */
1768 DEBUG(3,("api_RNetUserEnum gave %d entries\n", count));
1775 /****************************************************************************
1776 get the time of day info
1777 ****************************************************************************/
1778 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1779 int mdrcnt,int mprcnt,
1780 char **rdata,char **rparam,
1781 int *rdata_len,int *rparam_len)
1785 *rparam = REALLOC(*rparam,*rparam_len);
1788 *rdata = REALLOC(*rdata,*rdata_len);
1790 SSVAL(*rparam,0,NERR_Success);
1791 SSVAL(*rparam,2,0); /* converter word */
1797 time_t unixdate = time(NULL);
1799 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1800 by NT in a "net time" operation,
1801 it seems to ignore the one below */
1803 /* the client expects to get localtime, not GMT, in this bit
1804 (I think, this needs testing) */
1805 t = LocalTime(&unixdate);
1807 SIVAL(p,4,0); /* msecs ? */
1808 CVAL(p,8) = t->tm_hour;
1809 CVAL(p,9) = t->tm_min;
1810 CVAL(p,10) = t->tm_sec;
1811 CVAL(p,11) = 0; /* hundredths of seconds */
1812 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1813 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1814 CVAL(p,16) = t->tm_mday;
1815 CVAL(p,17) = t->tm_mon + 1;
1816 SSVAL(p,18,1900+t->tm_year);
1817 CVAL(p,20) = t->tm_wday;
1824 /****************************************************************************
1825 Set the user password.
1826 *****************************************************************************/
1828 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1829 int mdrcnt,int mprcnt,
1830 char **rdata,char **rparam,
1831 int *rdata_len,int *rparam_len)
1833 char *p = skip_string(param+2,2);
1835 fstring pass1,pass2;
1837 struct passwd *passwd;
1839 pull_ascii_fstring(user,p);
1841 p = skip_string(p,1);
1843 memset(pass1,'\0',sizeof(pass1));
1844 memset(pass2,'\0',sizeof(pass2));
1846 memcpy(pass2,p+16,16);
1849 *rparam = REALLOC(*rparam,*rparam_len);
1853 SSVAL(*rparam,0,NERR_badpass);
1854 SSVAL(*rparam,2,0); /* converter word */
1856 DEBUG(3,("Set password for <%s>\n",user));
1859 * Pass the user through the NT -> unix user mapping
1863 (void)map_username(user);
1866 * Do any UNIX username case mangling.
1868 passwd = Get_Pwnam( user, True);
1871 * Attempt to verify the old password against smbpasswd entries
1872 * Win98 clients send old and new password in plaintext for this call.
1876 fstring saved_pass2;
1877 SAM_ACCOUNT *sampass=NULL;
1880 * Save the new password as change_oem_password overwrites it
1884 fstrcpy(saved_pass2, pass2);
1886 if (check_plaintext_password(user,pass1,strlen(pass1),&sampass) &&
1887 change_oem_password(sampass,pass2))
1889 SSVAL(*rparam,0,NERR_Success);
1892 * If unix password sync was requested, attempt to change
1893 * the /etc/passwd database also. Return failure if this cannot
1897 if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
1898 SSVAL(*rparam,0,NERR_badpass);
1900 pdb_free_sam(&sampass);
1905 * If the above failed, attempt the plaintext password change.
1906 * This tests against the /etc/passwd database only.
1909 if(SVAL(*rparam,0) != NERR_Success)
1911 if NT_STATUS_IS_OK(pass_check(passwd, user, pass1,
1912 strlen(pass1), NULL, False))
1914 if (chgpasswd(user,pass1,pass2,False)) {
1915 SSVAL(*rparam,0,NERR_Success);
1921 * If the plaintext change failed, attempt
1922 * the old encrypted method. NT will generate this
1923 * after trying the samr method. Note that this
1924 * method is done as a last resort as this
1925 * password change method loses the NT password hash
1926 * and cannot change the UNIX password as no plaintext
1930 if(SVAL(*rparam,0) != NERR_Success)
1932 SAM_ACCOUNT *hnd = NULL;
1934 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) &&
1935 change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2))
1937 SSVAL(*rparam,0,NERR_Success);
1943 memset((char *)pass1,'\0',sizeof(fstring));
1944 memset((char *)pass2,'\0',sizeof(fstring));
1949 /****************************************************************************
1950 Set the user password (SamOEM version - gets plaintext).
1951 ****************************************************************************/
1953 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1954 int mdrcnt,int mprcnt,
1955 char **rdata,char **rparam,
1956 int *rdata_len,int *rparam_len)
1959 char *p = param + 2;
1961 *rparam = REALLOC(*rparam,*rparam_len);
1965 SSVAL(*rparam,0,NERR_badpass);
1968 * Check the parameter definition is correct.
1970 if(!strequal(param + 2, "zsT")) {
1971 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1974 p = skip_string(p, 1);
1976 if(!strequal(p, "B516B16")) {
1977 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1980 p = skip_string(p,1);
1982 p += pull_ascii_fstring(user,p);
1984 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1987 * Pass the user through the NT -> unix user mapping
1991 (void)map_username(user);
1994 * Do any UNIX username case mangling.
1996 (void)Get_Pwnam( user, True);
1998 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
2000 SSVAL(*rparam,0,NERR_Success);
2006 /****************************************************************************
2009 ****************************************************************************/
2010 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2011 int mdrcnt,int mprcnt,
2012 char **rdata,char **rparam,
2013 int *rdata_len,int *rparam_len)
2015 int function = SVAL(param,0);
2016 char *str1 = param+2;
2017 char *str2 = skip_string(str1,1);
2018 char *p = skip_string(str2,1);
2020 extern struct current_user current_user;
2021 WERROR werr = WERR_OK;
2025 /* check it's a supported varient */
2026 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2030 *rparam = REALLOC(*rparam,*rparam_len);
2033 if (!print_job_exists(jobid)) {
2034 errcode = NERR_JobNotFound;
2038 errcode = NERR_notsupported;
2041 case 81: /* delete */
2042 if (print_job_delete(¤t_user, jobid, &werr))
2043 errcode = NERR_Success;
2045 case 82: /* pause */
2046 if (print_job_pause(¤t_user, jobid, &werr))
2047 errcode = NERR_Success;
2049 case 83: /* resume */
2050 if (print_job_resume(¤t_user, jobid, &werr))
2051 errcode = NERR_Success;
2055 if (!W_ERROR_IS_OK(werr))
2056 errcode = W_ERROR_V(werr);
2059 SSVAL(*rparam,0,errcode);
2060 SSVAL(*rparam,2,0); /* converter word */
2065 /****************************************************************************
2066 Purge a print queue - or pause or resume it.
2067 ****************************************************************************/
2068 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2069 int mdrcnt,int mprcnt,
2070 char **rdata,char **rparam,
2071 int *rdata_len,int *rparam_len)
2073 int function = SVAL(param,0);
2074 char *str1 = param+2;
2075 char *str2 = skip_string(str1,1);
2076 char *QueueName = skip_string(str2,1);
2077 int errcode = NERR_notsupported;
2079 WERROR werr = WERR_OK;
2080 extern struct current_user current_user;
2082 /* check it's a supported varient */
2083 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2087 *rparam = REALLOC(*rparam,*rparam_len);
2090 snum = print_queue_snum(QueueName);
2093 errcode = NERR_JobNotFound;
2098 case 74: /* Pause queue */
2099 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2101 case 75: /* Resume queue */
2102 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2104 case 103: /* Purge */
2105 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2109 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2112 SSVAL(*rparam,0,errcode);
2113 SSVAL(*rparam,2,0); /* converter word */
2119 /****************************************************************************
2120 set the property of a print job (undocumented?)
2121 ? function = 0xb -> set name of print job
2122 ? function = 0x6 -> move print job up/down
2123 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2124 or <WWsTP> <WB21BB16B10zWWzDDz>
2125 ****************************************************************************/
2126 static int check_printjob_info(struct pack_desc* desc,
2127 int uLevel, char* id)
2129 desc->subformat = NULL;
2131 case 0: desc->format = "W"; break;
2132 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2133 case 2: desc->format = "WWzWWDDzz"; break;
2134 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2135 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2136 default: return False;
2138 if (strcmp(desc->format,id) != 0) return False;
2142 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2143 int mdrcnt,int mprcnt,
2144 char **rdata,char **rparam,
2145 int *rdata_len,int *rparam_len)
2147 struct pack_desc desc;
2148 char *str1 = param+2;
2149 char *str2 = skip_string(str1,1);
2150 char *p = skip_string(str2,1);
2152 int uLevel = SVAL(p,2);
2153 int function = SVAL(p,4);
2158 *rparam = REALLOC(*rparam,*rparam_len);
2162 /* check it's a supported varient */
2163 if ((strcmp(str1,"WWsTP")) ||
2164 (!check_printjob_info(&desc,uLevel,str2)))
2167 if (!print_job_exists(jobid)) {
2168 errcode=NERR_JobNotFound;
2172 errcode = NERR_notsupported;
2176 /* change job place in the queue,
2177 data gives the new place */
2178 place = SVAL(data,0);
2179 if (print_job_set_place(jobid, place)) {
2180 errcode=NERR_Success;
2185 /* change print job name, data gives the name */
2186 if (print_job_set_name(jobid, data)) {
2187 errcode=NERR_Success;
2196 SSVALS(*rparam,0,errcode);
2197 SSVAL(*rparam,2,0); /* converter word */
2203 /****************************************************************************
2204 get info about the server
2205 ****************************************************************************/
2206 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2207 int mdrcnt,int mprcnt,
2208 char **rdata,char **rparam,
2209 int *rdata_len,int *rparam_len)
2211 char *str1 = param+2;
2212 char *str2 = skip_string(str1,1);
2213 char *p = skip_string(str2,1);
2214 int uLevel = SVAL(p,0);
2218 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2220 /* check it's a supported varient */
2221 if (!prefix_ok(str1,"WrLh")) return False;
2224 if (strcmp(str2,"B16") != 0) return False;
2228 if (strcmp(str2,"B16BBDz") != 0) return False;
2232 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2237 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2242 if (strcmp(str2,"DN") != 0) return False;
2246 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2249 default: return False;
2252 *rdata_len = mdrcnt;
2253 *rdata = REALLOC(*rdata,*rdata_len);
2256 p2 = p + struct_len;
2258 srvstr_push(NULL, p,local_machine,16,
2259 STR_ASCII|STR_UPPER|STR_TERMINATE);
2264 struct srv_info_struct *servers=NULL;
2267 uint32 servertype= lp_default_server_announce();
2269 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2271 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2272 for (i=0;i<count;i++)
2273 if (strequal(servers[i].name,local_machine))
2275 servertype = servers[i].type;
2276 pstrcpy(comment,servers[i].comment);
2281 SCVAL(p,0,lp_major_announce_version());
2282 SCVAL(p,1,lp_minor_announce_version());
2283 SIVAL(p,2,servertype);
2285 if (mdrcnt == struct_len) {
2288 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2289 standard_sub_conn(conn,comment);
2290 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2291 p2 = skip_string(p2,1);
2296 return False; /* not yet implemented */
2299 *rdata_len = PTR_DIFF(p2,*rdata);
2302 *rparam = REALLOC(*rparam,*rparam_len);
2303 SSVAL(*rparam,0,NERR_Success);
2304 SSVAL(*rparam,2,0); /* converter word */
2305 SSVAL(*rparam,4,*rdata_len);
2311 /****************************************************************************
2312 get info about the server
2313 ****************************************************************************/
2314 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2315 int mdrcnt,int mprcnt,
2316 char **rdata,char **rparam,
2317 int *rdata_len,int *rparam_len)
2319 char *str1 = param+2;
2320 char *str2 = skip_string(str1,1);
2321 char *p = skip_string(str2,1);
2323 extern userdom_struct current_user_info;
2324 int level = SVAL(p,0);
2326 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2329 *rparam = REALLOC(*rparam,*rparam_len);
2331 /* check it's a supported varient */
2332 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2335 *rdata_len = mdrcnt + 1024;
2336 *rdata = REALLOC(*rdata,*rdata_len);
2338 SSVAL(*rparam,0,NERR_Success);
2339 SSVAL(*rparam,2,0); /* converter word */
2345 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2346 pstrcpy(p2,local_machine);
2348 p2 = skip_string(p2,1);
2351 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2352 pstrcpy(p2,current_user_info.smb_name);
2353 p2 = skip_string(p2,1);
2356 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2357 pstrcpy(p2,global_myworkgroup);
2359 p2 = skip_string(p2,1);
2362 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2363 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2366 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2367 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2368 p2 = skip_string(p2,1);
2371 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2373 p2 = skip_string(p2,1);
2376 *rdata_len = PTR_DIFF(p2,*rdata);
2378 SSVAL(*rparam,4,*rdata_len);
2383 /****************************************************************************
2384 get info about a user
2386 struct user_info_11 {
2387 char usri11_name[21]; 0-20
2389 char *usri11_comment; 22-25
2390 char *usri11_usr_comment; 26-29
2391 unsigned short usri11_priv; 30-31
2392 unsigned long usri11_auth_flags; 32-35
2393 long usri11_password_age; 36-39
2394 char *usri11_homedir; 40-43
2395 char *usri11_parms; 44-47
2396 long usri11_last_logon; 48-51
2397 long usri11_last_logoff; 52-55
2398 unsigned short usri11_bad_pw_count; 56-57
2399 unsigned short usri11_num_logons; 58-59
2400 char *usri11_logon_server; 60-63
2401 unsigned short usri11_country_code; 64-65
2402 char *usri11_workstations; 66-69
2403 unsigned long usri11_max_storage; 70-73
2404 unsigned short usri11_units_per_week; 74-75
2405 unsigned char *usri11_logon_hours; 76-79
2406 unsigned short usri11_code_page; 80-81
2411 usri11_name specifies the user name for which information is retireved
2413 usri11_pad aligns the next data structure element to a word boundary
2415 usri11_comment is a null terminated ASCII comment
2417 usri11_user_comment is a null terminated ASCII comment about the user
2419 usri11_priv specifies the level of the privilege assigned to the user.
2420 The possible values are:
2422 Name Value Description
2423 USER_PRIV_GUEST 0 Guest privilege
2424 USER_PRIV_USER 1 User privilege
2425 USER_PRV_ADMIN 2 Administrator privilege
2427 usri11_auth_flags specifies the account operator privileges. The
2428 possible values are:
2430 Name Value Description
2431 AF_OP_PRINT 0 Print operator
2434 Leach, Naik [Page 28]
2438 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2441 AF_OP_COMM 1 Communications operator
2442 AF_OP_SERVER 2 Server operator
2443 AF_OP_ACCOUNTS 3 Accounts operator
2446 usri11_password_age specifies how many seconds have elapsed since the
2447 password was last changed.
2449 usri11_home_dir points to a null terminated ASCII string that contains
2450 the path name of the user's home directory.
2452 usri11_parms points to a null terminated ASCII string that is set
2453 aside for use by applications.
2455 usri11_last_logon specifies the time when the user last logged on.
2456 This value is stored as the number of seconds elapsed since
2457 00:00:00, January 1, 1970.
2459 usri11_last_logoff specifies the time when the user last logged off.
2460 This value is stored as the number of seconds elapsed since
2461 00:00:00, January 1, 1970. A value of 0 means the last logoff
2464 usri11_bad_pw_count specifies the number of incorrect passwords
2465 entered since the last successful logon.
2467 usri11_log1_num_logons specifies the number of times this user has
2468 logged on. A value of -1 means the number of logons is unknown.
2470 usri11_logon_server points to a null terminated ASCII string that
2471 contains the name of the server to which logon requests are sent.
2472 A null string indicates logon requests should be sent to the
2475 usri11_country_code specifies the country code for the user's language
2478 usri11_workstations points to a null terminated ASCII string that
2479 contains the names of workstations the user may log on from.
2480 There may be up to 8 workstations, with the names separated by
2481 commas. A null strings indicates there are no restrictions.
2483 usri11_max_storage specifies the maximum amount of disk space the user
2484 can occupy. A value of 0xffffffff indicates there are no
2487 usri11_units_per_week specifies the equal number of time units into
2488 which a week is divided. This value must be equal to 168.
2490 usri11_logon_hours points to a 21 byte (168 bits) string that
2491 specifies the time during which the user can log on. Each bit
2492 represents one unique hour in a week. The first bit (bit 0, word
2493 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2497 Leach, Naik [Page 29]
2501 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2504 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2505 are no restrictions.
2507 usri11_code_page specifies the code page for the user's language of
2510 All of the pointers in this data structure need to be treated
2511 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2512 to be ignored. The converter word returned in the parameters section
2513 needs to be subtracted from the lower 16 bits to calculate an offset
2514 into the return buffer where this ASCII string resides.
2516 There is no auxiliary data in the response.
2518 ****************************************************************************/
2520 #define usri11_name 0
2521 #define usri11_pad 21
2522 #define usri11_comment 22
2523 #define usri11_usr_comment 26
2524 #define usri11_full_name 30
2525 #define usri11_priv 34
2526 #define usri11_auth_flags 36
2527 #define usri11_password_age 40
2528 #define usri11_homedir 44
2529 #define usri11_parms 48
2530 #define usri11_last_logon 52
2531 #define usri11_last_logoff 56
2532 #define usri11_bad_pw_count 60
2533 #define usri11_num_logons 62
2534 #define usri11_logon_server 64
2535 #define usri11_country_code 68
2536 #define usri11_workstations 70
2537 #define usri11_max_storage 74
2538 #define usri11_units_per_week 78
2539 #define usri11_logon_hours 80
2540 #define usri11_code_page 84
2541 #define usri11_end 86
2543 #define USER_PRIV_GUEST 0
2544 #define USER_PRIV_USER 1
2545 #define USER_PRIV_ADMIN 2
2547 #define AF_OP_PRINT 0
2548 #define AF_OP_COMM 1
2549 #define AF_OP_SERVER 2
2550 #define AF_OP_ACCOUNTS 3
2553 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2554 int mdrcnt,int mprcnt,
2555 char **rdata,char **rparam,
2556 int *rdata_len,int *rparam_len)
2558 char *str1 = param+2;
2559 char *str2 = skip_string(str1,1);
2560 char *UserName = skip_string(str2,1);
2561 char *p = skip_string(UserName,1);
2562 int uLevel = SVAL(p,0);
2565 /* get NIS home of a previously validated user - simeon */
2566 /* With share level security vuid will always be zero.
2567 Don't depend on vuser being non-null !!. JRA */
2568 user_struct *vuser = get_valid_user_struct(vuid);
2570 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2571 vuser->user.unix_name));
2574 *rparam = REALLOC(*rparam,*rparam_len);
2576 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2578 /* check it's a supported variant */
2579 if (strcmp(str1,"zWrLh") != 0) return False;
2582 case 0: p2 = "B21"; break;
2583 case 1: p2 = "B21BB16DWzzWz"; break;
2584 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2585 case 10: p2 = "B21Bzzz"; break;
2586 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2587 default: return False;
2590 if (strcmp(p2,str2) != 0) return False;
2592 *rdata_len = mdrcnt + 1024;
2593 *rdata = REALLOC(*rdata,*rdata_len);
2595 SSVAL(*rparam,0,NERR_Success);
2596 SSVAL(*rparam,2,0); /* converter word */
2599 p2 = p + usri11_end;
2602 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2606 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2611 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2612 pstrcpy(p2,"Comment");
2613 p2 = skip_string(p2,1);
2615 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2616 pstrcpy(p2,"UserComment");
2617 p2 = skip_string(p2,1);
2619 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2620 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2621 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2622 p2 = skip_string(p2,1);
2625 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2627 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2628 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2629 SIVALS(p,usri11_password_age,-1); /* password age */
2630 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2631 pstrcpy(p2, lp_logon_home());
2632 standard_sub_conn(conn, p2);
2633 p2 = skip_string(p2,1);
2634 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2636 p2 = skip_string(p2,1);
2637 SIVAL(p,usri11_last_logon,0); /* last logon */
2638 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2639 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2640 SSVALS(p,usri11_num_logons,-1); /* num logons */
2641 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2642 pstrcpy(p2,"\\\\*");
2643 p2 = skip_string(p2,1);
2644 SSVAL(p,usri11_country_code,0); /* country code */
2646 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2648 p2 = skip_string(p2,1);
2650 SIVALS(p,usri11_max_storage,-1); /* max storage */
2651 SSVAL(p,usri11_units_per_week,168); /* units per week */
2652 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2654 /* a simple way to get logon hours at all times. */
2656 SCVAL(p2,21,0); /* fix zero termination */
2657 p2 = skip_string(p2,1);
2659 SSVAL(p,usri11_code_page,0); /* code page */
2661 if (uLevel == 1 || uLevel == 2)
2663 memset(p+22,' ',16); /* password */
2664 SIVALS(p,38,-1); /* password age */
2666 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2667 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2668 pstrcpy(p2,lp_logon_home());
2669 standard_sub_conn(conn, p2);
2670 p2 = skip_string(p2,1);
2671 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2673 SSVAL(p,52,0); /* flags */
2674 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2675 pstrcpy(p2,lp_logon_script());
2676 standard_sub_conn( conn, p2 );
2677 p2 = skip_string(p2,1);
2680 SIVAL(p,60,0); /* auth_flags */
2681 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2682 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2683 p2 = skip_string(p2,1);
2684 SIVAL(p,68,0); /* urs_comment */
2685 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2687 p2 = skip_string(p2,1);
2688 SIVAL(p,76,0); /* workstations */
2689 SIVAL(p,80,0); /* last_logon */
2690 SIVAL(p,84,0); /* last_logoff */
2691 SIVALS(p,88,-1); /* acct_expires */
2692 SIVALS(p,92,-1); /* max_storage */
2693 SSVAL(p,96,168); /* units_per_week */
2694 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2697 SSVALS(p,102,-1); /* bad_pw_count */
2698 SSVALS(p,104,-1); /* num_logons */
2699 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2700 pstrcpy(p2,"\\\\%L");
2701 standard_sub_conn(conn, p2);
2702 p2 = skip_string(p2,1);
2703 SSVAL(p,110,49); /* country_code */
2704 SSVAL(p,112,860); /* code page */
2708 *rdata_len = PTR_DIFF(p2,*rdata);
2710 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2715 /*******************************************************************
2716 get groups that a user is a member of
2717 ******************************************************************/
2718 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2719 int mdrcnt,int mprcnt,
2720 char **rdata,char **rparam,
2721 int *rdata_len,int *rparam_len)
2723 char *str1 = param+2;
2724 char *str2 = skip_string(str1,1);
2725 char *UserName = skip_string(str2,1);
2726 char *p = skip_string(UserName,1);
2727 int uLevel = SVAL(p,0);
2732 *rparam = REALLOC(*rparam,*rparam_len);
2734 /* check it's a supported varient */
2735 if (strcmp(str1,"zWrLeh") != 0) return False;
2737 case 0: p2 = "B21"; break;
2738 default: return False;
2740 if (strcmp(p2,str2) != 0) return False;
2742 *rdata_len = mdrcnt + 1024;
2743 *rdata = REALLOC(*rdata,*rdata_len);
2745 SSVAL(*rparam,0,NERR_Success);
2746 SSVAL(*rparam,2,0); /* converter word */
2750 /* XXXX we need a real SAM database some day */
2751 pstrcpy(p,"Users"); p += 21; count++;
2752 pstrcpy(p,"Domain Users"); p += 21; count++;
2753 pstrcpy(p,"Guests"); p += 21; count++;
2754 pstrcpy(p,"Domain Guests"); p += 21; count++;
2756 *rdata_len = PTR_DIFF(p,*rdata);
2758 SSVAL(*rparam,4,count); /* is this right?? */
2759 SSVAL(*rparam,6,count); /* is this right?? */
2765 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2766 int mdrcnt,int mprcnt,
2767 char **rdata,char **rparam,
2768 int *rdata_len,int *rparam_len)
2770 char *str1 = param+2;
2771 char *str2 = skip_string(str1,1);
2772 char *p = skip_string(str2,1);
2774 struct pack_desc desc;
2780 memset((char *)&desc,'\0',sizeof(desc));
2782 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2784 /* check it's a supported varient */
2785 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2786 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2787 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2789 desc.buflen = mdrcnt;
2790 desc.subformat = NULL;
2793 if (init_package(&desc,1,0))
2795 PACKI(&desc,"W",0); /* code */
2796 PACKS(&desc,"B21",name); /* eff. name */
2797 PACKS(&desc,"B",""); /* pad */
2799 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2800 PACKI(&desc,"D",0); /* auth flags XXX */
2801 PACKI(&desc,"W",0); /* num logons */
2802 PACKI(&desc,"W",0); /* bad pw count */
2803 PACKI(&desc,"D",0); /* last logon */
2804 PACKI(&desc,"D",-1); /* last logoff */
2805 PACKI(&desc,"D",-1); /* logoff time */
2806 PACKI(&desc,"D",-1); /* kickoff time */
2807 PACKI(&desc,"D",0); /* password age */
2808 PACKI(&desc,"D",0); /* password can change */
2809 PACKI(&desc,"D",-1); /* password must change */
2812 fstrcpy(mypath,"\\\\");
2813 fstrcat(mypath,local_machine);
2815 PACKS(&desc,"z",mypath); /* computer */
2817 PACKS(&desc,"z",global_myworkgroup);/* domain */
2819 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2820 /* made sure all macros are fully substituted and available */
2822 pstring logon_script;
2823 pstrcpy(logon_script,lp_logon_script());
2824 standard_sub_conn( conn, logon_script );
2825 PACKS(&desc,"z", logon_script); /* script path */
2827 /* End of JHT mods */
2829 PACKI(&desc,"D",0x00000000); /* reserved */
2832 *rdata_len = desc.usedlen;
2834 *rparam = REALLOC(*rparam,*rparam_len);
2835 SSVALS(*rparam,0,desc.errcode);
2837 SSVAL(*rparam,4,desc.neededlen);
2839 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2844 /****************************************************************************
2845 api_WAccessGetUserPerms
2846 ****************************************************************************/
2847 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2848 int mdrcnt,int mprcnt,
2849 char **rdata,char **rparam,
2850 int *rdata_len,int *rparam_len)
2852 char *str1 = param+2;
2853 char *str2 = skip_string(str1,1);
2854 char *user = skip_string(str2,1);
2855 char *resource = skip_string(user,1);
2857 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2859 /* check it's a supported varient */
2860 if (strcmp(str1,"zzh") != 0) return False;
2861 if (strcmp(str2,"") != 0) return False;
2864 *rparam = REALLOC(*rparam,*rparam_len);
2865 SSVALS(*rparam,0,0); /* errorcode */
2866 SSVAL(*rparam,2,0); /* converter word */
2867 SSVAL(*rparam,4,0x7f); /* permission flags */
2872 /****************************************************************************
2873 api_WPrintJobEnumerate
2874 ****************************************************************************/
2875 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2876 int mdrcnt,int mprcnt,
2877 char **rdata,char **rparam,
2878 int *rdata_len,int *rparam_len)
2880 char *str1 = param+2;
2881 char *str2 = skip_string(str1,1);
2882 char *p = skip_string(str2,1);
2888 struct pack_desc desc;
2889 print_queue_struct *queue=NULL;
2890 print_status_struct status;
2895 memset((char *)&desc,'\0',sizeof(desc));
2896 memset((char *)&status,'\0',sizeof(status));
2898 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2900 /* check it's a supported varient */
2901 if (strcmp(str1,"WWrLh") != 0) return False;
2902 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2905 snum = print_job_snum(job);
2907 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2909 count = print_queue_status(snum,&queue,&status);
2910 for (i = 0; i < count; i++) {
2911 if (queue[i].job == job) break;
2915 *rdata = REALLOC(*rdata,mdrcnt);
2917 desc.buflen = mdrcnt;
2920 * Don't return data but need to get correct length
2921 * init_package will return wrong size if buflen=0
2923 desc.buflen = getlen(desc.format);
2924 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2927 if (init_package(&desc,1,0)) {
2929 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2930 *rdata_len = desc.usedlen;
2933 desc.errcode = NERR_JobNotFound;
2939 *rparam = REALLOC(*rparam,*rparam_len);
2940 SSVALS(*rparam,0,desc.errcode);
2942 SSVAL(*rparam,4,desc.neededlen);
2947 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2951 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2952 int mdrcnt,int mprcnt,
2953 char **rdata,char **rparam,
2954 int *rdata_len,int *rparam_len)
2956 char *str1 = param+2;
2957 char *str2 = skip_string(str1,1);
2958 char *p = skip_string(str2,1);
2964 struct pack_desc desc;
2965 print_queue_struct *queue=NULL;
2966 print_status_struct status;
2968 memset((char *)&desc,'\0',sizeof(desc));
2969 memset((char *)&status,'\0',sizeof(status));
2971 p = skip_string(p,1);
2974 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2976 /* check it's a supported varient */
2977 if (strcmp(str1,"zWrLeh") != 0) return False;
2978 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2979 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2981 snum = lp_servicenumber(name);
2982 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2983 int pnum = lp_servicenumber(PRINTERS_NAME);
2985 lp_add_printer(name,pnum);
2986 snum = lp_servicenumber(name);
2990 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2992 count = print_queue_status(snum,&queue,&status);
2993 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2995 desc.buflen = mdrcnt;
2997 if (init_package(&desc,count,0)) {
2999 for (i = 0; i < count; i++) {
3000 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3001 if (desc.errcode == NERR_Success) succnt = i+1;
3005 *rdata_len = desc.usedlen;
3008 *rparam = REALLOC(*rparam,*rparam_len);
3009 SSVALS(*rparam,0,desc.errcode);
3011 SSVAL(*rparam,4,succnt);
3012 SSVAL(*rparam,6,count);
3016 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3020 static int check_printdest_info(struct pack_desc* desc,
3021 int uLevel, char* id)
3023 desc->subformat = NULL;
3025 case 0: desc->format = "B9"; break;
3026 case 1: desc->format = "B9B21WWzW"; break;
3027 case 2: desc->format = "z"; break;
3028 case 3: desc->format = "zzzWWzzzWW"; break;
3029 default: return False;
3031 if (strcmp(desc->format,id) != 0) return False;
3035 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3036 struct pack_desc* desc)
3039 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3040 buf[sizeof(buf)-1] = 0;
3043 PACKS(desc,"B9",buf); /* szName */
3045 PACKS(desc,"B21",""); /* szUserName */
3046 PACKI(desc,"W",0); /* uJobId */
3047 PACKI(desc,"W",0); /* fsStatus */
3048 PACKS(desc,"z",""); /* pszStatus */
3049 PACKI(desc,"W",0); /* time */
3052 if (uLevel == 2 || uLevel == 3) {
3053 PACKS(desc,"z",buf); /* pszPrinterName */
3055 PACKS(desc,"z",""); /* pszUserName */
3056 PACKS(desc,"z",""); /* pszLogAddr */
3057 PACKI(desc,"W",0); /* uJobId */
3058 PACKI(desc,"W",0); /* fsStatus */
3059 PACKS(desc,"z",""); /* pszStatus */
3060 PACKS(desc,"z",""); /* pszComment */
3061 PACKS(desc,"z","NULL"); /* pszDrivers */
3062 PACKI(desc,"W",0); /* time */
3063 PACKI(desc,"W",0); /* pad1 */
3068 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3069 int mdrcnt,int mprcnt,
3070 char **rdata,char **rparam,
3071 int *rdata_len,int *rparam_len)
3073 char *str1 = param+2;
3074 char *str2 = skip_string(str1,1);
3075 char *p = skip_string(str2,1);
3076 char* PrinterName = p;
3078 struct pack_desc desc;
3082 memset((char *)&desc,'\0',sizeof(desc));
3084 p = skip_string(p,1);
3087 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3089 /* check it's a supported varient */
3090 if (strcmp(str1,"zWrLh") != 0) return False;
3091 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3093 snum = lp_servicenumber(PrinterName);
3094 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3095 int pnum = lp_servicenumber(PRINTERS_NAME);
3097 lp_add_printer(PrinterName,pnum);
3098 snum = lp_servicenumber(PrinterName);
3104 desc.errcode = NERR_DestNotFound;
3109 *rdata = REALLOC(*rdata,mdrcnt);
3111 desc.buflen = mdrcnt;
3114 * Don't return data but need to get correct length
3115 * init_package will return wrong size if buflen=0
3117 desc.buflen = getlen(desc.format);
3118 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3120 if (init_package(&desc,1,0)) {
3121 fill_printdest_info(conn,snum,uLevel,&desc);
3123 *rdata_len = desc.usedlen;
3127 *rparam = REALLOC(*rparam,*rparam_len);
3128 SSVALS(*rparam,0,desc.errcode);
3130 SSVAL(*rparam,4,desc.neededlen);
3132 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3137 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3138 int mdrcnt,int mprcnt,
3139 char **rdata,char **rparam,
3140 int *rdata_len,int *rparam_len)
3142 char *str1 = param+2;
3143 char *str2 = skip_string(str1,1);
3144 char *p = skip_string(str2,1);
3148 struct pack_desc desc;
3149 int services = lp_numservices();
3151 memset((char *)&desc,'\0',sizeof(desc));
3155 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3157 /* check it's a supported varient */
3158 if (strcmp(str1,"WrLeh") != 0) return False;
3159 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3162 for (i = 0; i < services; i++)
3163 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3166 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3168 desc.buflen = mdrcnt;
3169 if (init_package(&desc,queuecnt,0)) {
3172 for (i = 0; i < services; i++) {
3173 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3174 fill_printdest_info(conn,i,uLevel,&desc);
3176 if (desc.errcode == NERR_Success) succnt = n;
3181 *rdata_len = desc.usedlen;
3184 *rparam = REALLOC(*rparam,*rparam_len);
3185 SSVALS(*rparam,0,desc.errcode);
3187 SSVAL(*rparam,4,succnt);
3188 SSVAL(*rparam,6,queuecnt);
3190 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3194 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3195 int mdrcnt,int mprcnt,
3196 char **rdata,char **rparam,
3197 int *rdata_len,int *rparam_len)
3199 char *str1 = param+2;
3200 char *str2 = skip_string(str1,1);
3201 char *p = skip_string(str2,1);
3204 struct pack_desc desc;
3206 memset((char *)&desc,'\0',sizeof(desc));
3210 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3212 /* check it's a supported varient */
3213 if (strcmp(str1,"WrLeh") != 0) return False;
3214 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3216 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3218 desc.buflen = mdrcnt;
3219 if (init_package(&desc,1,0)) {
3220 PACKS(&desc,"B41","NULL");
3223 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3225 *rdata_len = desc.usedlen;
3228 *rparam = REALLOC(*rparam,*rparam_len);
3229 SSVALS(*rparam,0,desc.errcode);
3231 SSVAL(*rparam,4,succnt);
3234 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3238 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3239 int mdrcnt,int mprcnt,
3240 char **rdata,char **rparam,
3241 int *rdata_len,int *rparam_len)
3243 char *str1 = param+2;
3244 char *str2 = skip_string(str1,1);
3245 char *p = skip_string(str2,1);
3248 struct pack_desc desc;
3250 memset((char *)&desc,'\0',sizeof(desc));
3254 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3256 /* check it's a supported varient */
3257 if (strcmp(str1,"WrLeh") != 0) return False;
3258 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3260 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3262 desc.buflen = mdrcnt;
3264 if (init_package(&desc,1,0)) {
3265 PACKS(&desc,"B13","lpd");
3268 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3270 *rdata_len = desc.usedlen;
3273 *rparam = REALLOC(*rparam,*rparam_len);
3274 SSVALS(*rparam,0,desc.errcode);
3276 SSVAL(*rparam,4,succnt);
3279 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3283 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3284 int mdrcnt,int mprcnt,
3285 char **rdata,char **rparam,
3286 int *rdata_len,int *rparam_len)
3288 char *str1 = param+2;
3289 char *str2 = skip_string(str1,1);
3290 char *p = skip_string(str2,1);
3293 struct pack_desc desc;
3295 memset((char *)&desc,'\0',sizeof(desc));
3299 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3301 /* check it's a supported varient */
3302 if (strcmp(str1,"WrLeh") != 0) return False;
3303 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3305 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3306 memset((char *)&desc,'\0',sizeof(desc));
3308 desc.buflen = mdrcnt;
3310 if (init_package(&desc,1,0)) {
3311 PACKS(&desc,"B13","lp0");
3314 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3316 *rdata_len = desc.usedlen;
3319 *rparam = REALLOC(*rparam,*rparam_len);
3320 SSVALS(*rparam,0,desc.errcode);
3322 SSVAL(*rparam,4,succnt);
3325 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3329 /****************************************************************************
3330 The buffer was too small
3331 ****************************************************************************/
3333 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3334 int mdrcnt,int mprcnt,
3335 char **rdata,char **rparam,
3336 int *rdata_len,int *rparam_len)
3338 *rparam_len = MIN(*rparam_len,mprcnt);
3339 *rparam = REALLOC(*rparam,*rparam_len);
3343 SSVAL(*rparam,0,NERR_BufTooSmall);
3345 DEBUG(3,("Supplied buffer too small in API command\n"));
3351 /****************************************************************************
3352 The request is not supported
3353 ****************************************************************************/
3355 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3356 int mdrcnt,int mprcnt,
3357 char **rdata,char **rparam,
3358 int *rdata_len,int *rparam_len)
3361 *rparam = REALLOC(*rparam,*rparam_len);
3365 SSVAL(*rparam,0,NERR_notsupported);
3366 SSVAL(*rparam,2,0); /* converter word */
3368 DEBUG(3,("Unsupported API command\n"));
3380 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3381 int,int,char **,char **,int *,int *);
3383 } api_commands[] = {
3384 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3385 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3386 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3387 {"RNetGroupEnum", 47, api_RNetGroupEnum,0},
3388 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3389 {"RNetUserEnum", 53, api_RNetUserEnum,0},
3390 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3391 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3392 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3393 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3394 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3395 {"WPrintQueuePause", 74, api_WPrintQueueCtrl,0},
3396 {"WPrintQueueResume", 75, api_WPrintQueueCtrl,0},
3397 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3398 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3399 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3400 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3401 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3402 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3403 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3404 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3405 {"WPrintQueuePurge", 103, api_WPrintQueueCtrl,0},
3406 {"NetServerEnum", 104, api_RNetServerEnum,0},
3407 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3408 {"SetUserPassword", 115, api_SetUserPassword,0},
3409 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3410 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3411 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3412 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3413 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3414 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3415 {NULL, -1, api_Unsupported,0}};
3418 /****************************************************************************
3419 Handle remote api calls
3420 ****************************************************************************/
3422 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3423 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3427 char *rparam = NULL;
3434 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3438 api_command = SVAL(params,0);
3440 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3443 skip_string(params+2,1),
3444 tdscnt,tpscnt,mdrcnt,mprcnt));
3446 for (i=0;api_commands[i].name;i++) {
3447 if (api_commands[i].id == api_command && api_commands[i].fn) {
3448 DEBUG(3,("Doing %s\n",api_commands[i].name));
3453 rdata = (char *)malloc(1024);
3455 memset(rdata,'\0',1024);
3457 rparam = (char *)malloc(1024);
3459 memset(rparam,'\0',1024);
3461 if(!rdata || !rparam) {
3462 DEBUG(0,("api_reply: malloc fail !\n"));
3466 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3467 &rdata,&rparam,&rdata_len,&rparam_len);
3470 if (rdata_len > mdrcnt ||
3471 rparam_len > mprcnt) {
3472 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3473 &rdata,&rparam,&rdata_len,&rparam_len);
3476 /* if we get False back then it's actually unsupported */
3478 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3479 &rdata,&rparam,&rdata_len,&rparam_len);
3481 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);