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));
956 /****************************************************************************
957 View list of all print jobs on all queues.
958 ****************************************************************************/
960 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
961 int mdrcnt, int mprcnt,
962 char **rdata, char** rparam,
963 int *rdata_len, int *rparam_len)
965 char *param_format = param+2;
966 char *output_format1 = skip_string(param_format,1);
967 char *p = skip_string(output_format1,1);
968 int uLevel = SVAL(p,0);
969 char *output_format2 = p + 4;
970 int services = lp_numservices();
972 struct pack_desc desc;
973 print_queue_struct **queue = NULL;
974 print_status_struct *status = NULL;
975 int* subcntarr = NULL;
976 int queuecnt, subcnt=0, succnt=0;
978 memset((char *)&desc,'\0',sizeof(desc));
980 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
982 if (!prefix_ok(param_format,"WrLeh")) return False;
983 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
985 * Patch from Scott Moomaw <scott@bridgewater.edu>
986 * to return the 'invalid info level' error if an
987 * unknown level was requested.
991 *rparam = REALLOC(*rparam,*rparam_len);
992 SSVALS(*rparam,0,ERRunknownlevel);
999 for (i = 0; i < services; i++)
1000 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
1003 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
1004 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1007 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1008 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
1009 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1012 memset(status,0,queuecnt*sizeof(print_status_struct));
1013 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
1014 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1019 for (i = 0; i < services; i++)
1020 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1021 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1022 subcnt += subcntarr[n];
1026 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
1028 desc.buflen = mdrcnt;
1030 if (init_package(&desc,queuecnt,subcnt)) {
1033 for (i = 0; i < services; i++)
1034 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1035 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1037 if (desc.errcode == NERR_Success) succnt = n;
1041 if (subcntarr) free(subcntarr);
1043 *rdata_len = desc.usedlen;
1045 *rparam = REALLOC(*rparam,*rparam_len);
1046 SSVALS(*rparam,0,desc.errcode);
1048 SSVAL(*rparam,4,succnt);
1049 SSVAL(*rparam,6,queuecnt);
1051 for (i = 0; i < queuecnt; i++) {
1052 if (queue && queue[i]) free(queue[i]);
1055 if (queue) free(queue);
1056 if (status) free(status);
1061 /****************************************************************************
1062 get info level for a server list query
1063 ****************************************************************************/
1064 static BOOL check_server_info(int uLevel, char* id)
1068 if (strcmp(id,"B16") != 0) return False;
1071 if (strcmp(id,"B16BBDz") != 0) return False;
1079 struct srv_info_struct
1089 /*******************************************************************
1090 get server info lists from the files saved by nmbd. Return the
1092 ******************************************************************/
1093 static int get_server_info(uint32 servertype,
1094 struct srv_info_struct **servers,
1100 BOOL local_list_only;
1103 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
1105 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1109 /* request for everything is code for request all servers */
1110 if (servertype == SV_TYPE_ALL)
1111 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1113 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1115 DEBUG(4,("Servertype search: %8x\n",servertype));
1117 for (i=0;lines[i];i++) {
1119 struct srv_info_struct *s;
1120 char *ptr = lines[i];
1123 if (!*ptr) continue;
1125 if (count == alloced) {
1126 struct srv_info_struct *ts;
1129 ts = (struct srv_info_struct *)
1130 Realloc(*servers,sizeof(**servers)*alloced);
1132 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1136 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1138 s = &(*servers)[count];
1140 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1141 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1142 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1143 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1144 /* this allows us to cope with an old nmbd */
1145 pstrcpy(s->domain,global_myworkgroup);
1148 if (sscanf(stype,"%X",&s->type) != 1) {
1149 DEBUG(4,("r:host file "));
1153 /* Filter the servers/domains we return based on what was asked for. */
1155 /* Check to see if we are being asked for a local list only. */
1156 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1157 DEBUG(4,("r: local list only"));
1161 /* doesn't match up: don't want it */
1162 if (!(servertype & s->type)) {
1163 DEBUG(4,("r:serv type "));
1167 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1168 (s->type & SV_TYPE_DOMAIN_ENUM))
1170 DEBUG(4,("s: dom mismatch "));
1174 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1179 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1180 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1184 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1185 s->name, s->type, s->comment, s->domain));
1187 s->server_added = True;
1192 DEBUG(4,("%20s %8x %25s %15s\n",
1193 s->name, s->type, s->comment, s->domain));
1197 file_lines_free(lines);
1202 /*******************************************************************
1203 fill in a server info structure
1204 ******************************************************************/
1205 static int fill_srv_info(struct srv_info_struct *service,
1206 int uLevel, char **buf, int *buflen,
1207 char **stringbuf, int *stringspace, char *baseaddr)
1216 case 0: struct_len = 16; break;
1217 case 1: struct_len = 26; break;
1227 len = strlen(service->comment)+1;
1231 if (buflen) *buflen = struct_len;
1232 if (stringspace) *stringspace = len;
1233 return struct_len + len;
1238 if (*buflen < struct_len) return -1;
1246 p2 = p + struct_len;
1247 l2 = *buflen - struct_len;
1249 if (!baseaddr) baseaddr = p;
1254 push_ascii(p,service->name, 15, STR_TERMINATE);
1258 push_ascii(p,service->name,15, STR_TERMINATE);
1259 SIVAL(p,18,service->type);
1260 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1261 len += CopyAndAdvance(&p2,service->comment,&l2);
1267 *buf = p + struct_len;
1268 *buflen -= struct_len;
1281 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1283 return(strcmp(s1->name,s2->name));
1286 /****************************************************************************
1287 view list of servers available (or possibly domains). The info is
1288 extracted from lists saved by nmbd on the local host
1289 ****************************************************************************/
1290 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1291 int mdrcnt, int mprcnt, char **rdata,
1292 char **rparam, int *rdata_len, int *rparam_len)
1294 char *str1 = param+2;
1295 char *str2 = skip_string(str1,1);
1296 char *p = skip_string(str2,1);
1297 int uLevel = SVAL(p,0);
1298 int buf_len = SVAL(p,2);
1299 uint32 servertype = IVAL(p,4);
1301 int data_len, fixed_len, string_len;
1302 int f_len = 0, s_len = 0;
1303 struct srv_info_struct *servers=NULL;
1304 int counted=0,total=0;
1307 BOOL domain_request;
1310 /* If someone sets all the bits they don't really mean to set
1311 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1314 if (servertype == SV_TYPE_ALL)
1315 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1317 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1318 any other bit (they may just set this bit on it's own) they
1319 want all the locally seen servers. However this bit can be
1320 set on its own so set the requested servers to be
1321 ALL - DOMAIN_ENUM. */
1323 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1324 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1326 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1327 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1331 if (!prefix_ok(str1,"WrLehD")) return False;
1332 if (!check_server_info(uLevel,str2)) return False;
1334 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1335 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1336 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1338 if (strcmp(str1, "WrLehDz") == 0) {
1339 pull_ascii_fstring(domain, p);
1341 fstrcpy(domain, global_myworkgroup);
1344 if (lp_browse_list())
1345 total = get_server_info(servertype,&servers,domain);
1347 data_len = fixed_len = string_len = 0;
1351 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1354 char *lastname=NULL;
1356 for (i=0;i<total;i++)
1358 struct srv_info_struct *s = &servers[i];
1359 if (lastname && strequal(lastname,s->name)) continue;
1361 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1362 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1363 s->name, s->type, s->comment, s->domain));
1365 if (data_len <= buf_len) {
1368 string_len += s_len;
1375 *rdata_len = fixed_len + string_len;
1376 *rdata = REALLOC(*rdata,*rdata_len);
1377 memset(*rdata,'\0',*rdata_len);
1379 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1385 char *lastname=NULL;
1386 int count2 = counted;
1387 for (i = 0; i < total && count2;i++)
1389 struct srv_info_struct *s = &servers[i];
1390 if (lastname && strequal(lastname,s->name)) continue;
1392 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1393 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1394 s->name, s->type, s->comment, s->domain));
1400 *rparam = REALLOC(*rparam,*rparam_len);
1401 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1403 SSVAL(*rparam,4,counted);
1404 SSVAL(*rparam,6,counted+missed);
1406 if (servers) free(servers);
1408 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1409 domain,uLevel,counted,counted+missed));
1414 /****************************************************************************
1415 command 0x34 - suspected of being a "Lookup Names" stub api
1416 ****************************************************************************/
1417 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1418 int mdrcnt, int mprcnt, char **rdata,
1419 char **rparam, int *rdata_len, int *rparam_len)
1421 char *str1 = param+2;
1422 char *str2 = skip_string(str1,1);
1423 char *p = skip_string(str2,1);
1424 int uLevel = SVAL(p,0);
1425 int buf_len = SVAL(p,2);
1429 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1430 str1, str2, p, uLevel, buf_len));
1432 if (!prefix_ok(str1,"zWrLeh")) return False;
1437 *rparam = REALLOC(*rparam,*rparam_len);
1439 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1441 SSVAL(*rparam,4,counted);
1442 SSVAL(*rparam,6,counted+missed);
1447 /****************************************************************************
1448 get info about a share
1449 ****************************************************************************/
1450 static BOOL check_share_info(int uLevel, char* id)
1454 if (strcmp(id,"B13") != 0) return False;
1457 if (strcmp(id,"B13BWz") != 0) return False;
1460 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1463 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1465 default: return False;
1470 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1471 char** buf, int* buflen,
1472 char** stringbuf, int* stringspace, char* baseaddr)
1481 case 0: struct_len = 13; break;
1482 case 1: struct_len = 20; break;
1483 case 2: struct_len = 40; break;
1484 case 91: struct_len = 68; break;
1492 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1493 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1494 if (buflen) *buflen = struct_len;
1495 if (stringspace) *stringspace = len;
1496 return struct_len + len;
1501 if ((*buflen) < struct_len) return -1;
1509 p2 = p + struct_len;
1510 l2 = (*buflen) - struct_len;
1512 if (!baseaddr) baseaddr = p;
1514 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1520 type = STYPE_DISKTREE;
1521 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1522 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1523 SSVAL(p,14,type); /* device type */
1524 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1525 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1530 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1531 SSVALS(p,22,-1); /* max uses */
1532 SSVAL(p,24,1); /* current uses */
1533 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1534 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1535 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1540 memset(p+40,0,SHPWLEN+2);
1552 (*buf) = p + struct_len;
1553 (*buflen) -= struct_len;
1555 (*stringspace) = l2;
1565 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1566 int mdrcnt,int mprcnt,
1567 char **rdata,char **rparam,
1568 int *rdata_len,int *rparam_len)
1570 char *str1 = param+2;
1571 char *str2 = skip_string(str1,1);
1572 char *netname = skip_string(str2,1);
1573 char *p = skip_string(netname,1);
1574 int uLevel = SVAL(p,0);
1575 int snum = find_service(netname);
1577 if (snum < 0) return False;
1579 /* check it's a supported varient */
1580 if (!prefix_ok(str1,"zWrLh")) return False;
1581 if (!check_share_info(uLevel,str2)) return False;
1583 *rdata = REALLOC(*rdata,mdrcnt);
1585 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1586 if (*rdata_len < 0) return False;
1589 *rparam = REALLOC(*rparam,*rparam_len);
1590 SSVAL(*rparam,0,NERR_Success);
1591 SSVAL(*rparam,2,0); /* converter word */
1592 SSVAL(*rparam,4,*rdata_len);
1597 /****************************************************************************
1598 view list of shares available
1599 ****************************************************************************/
1600 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1601 int mdrcnt,int mprcnt,
1602 char **rdata,char **rparam,
1603 int *rdata_len,int *rparam_len)
1605 char *str1 = param+2;
1606 char *str2 = skip_string(str1,1);
1607 char *p = skip_string(str2,1);
1608 int uLevel = SVAL(p,0);
1609 int buf_len = SVAL(p,2);
1611 int count=lp_numservices();
1612 int total=0,counted=0;
1613 BOOL missed = False;
1615 int data_len, fixed_len, string_len;
1616 int f_len = 0, s_len = 0;
1618 if (!prefix_ok(str1,"WrLeh")) return False;
1619 if (!check_share_info(uLevel,str2)) return False;
1621 data_len = fixed_len = string_len = 0;
1622 for (i=0;i<count;i++)
1623 if (lp_browseable(i) && lp_snum_ok(i))
1626 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1627 if (data_len <= buf_len)
1631 string_len += s_len;
1636 *rdata_len = fixed_len + string_len;
1637 *rdata = REALLOC(*rdata,*rdata_len);
1638 memset(*rdata,0,*rdata_len);
1640 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1644 for (i = 0; i < count;i++)
1645 if (lp_browseable(i) && lp_snum_ok(i))
1646 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1650 *rparam = REALLOC(*rparam,*rparam_len);
1651 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1653 SSVAL(*rparam,4,counted);
1654 SSVAL(*rparam,6,total);
1656 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1657 counted,total,uLevel,
1658 buf_len,*rdata_len,mdrcnt));
1663 /****************************************************************************
1664 view list of groups available
1665 ****************************************************************************/
1666 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1667 int mdrcnt,int mprcnt,
1668 char **rdata,char **rparam,
1669 int *rdata_len,int *rparam_len)
1671 char *str1 = param+2;
1672 char *str2 = skip_string(str1,1);
1673 char *p = skip_string(str2,1);
1674 int uLevel = SVAL(p,0);
1678 if (!prefix_ok(str1,"WrLeh")) return False;
1680 /* check it's a supported variant */
1690 if (strcmp(p2,str2) != 0) return False;
1692 *rdata_len = mdrcnt + 1024;
1693 *rdata = REALLOC(*rdata,*rdata_len);
1695 SSVAL(*rparam,0,NERR_Success);
1696 SSVAL(*rparam,2,0); /* converter word */
1700 /* XXXX we need a real SAM database some day */
1701 pstrcpy(p,"Users"); p += 21; count++;
1702 pstrcpy(p,"Domain Users"); p += 21; count++;
1703 pstrcpy(p,"Guests"); p += 21; count++;
1704 pstrcpy(p,"Domain Guests"); p += 21; count++;
1706 *rdata_len = PTR_DIFF(p,*rdata);
1709 *rparam = REALLOC(*rparam,*rparam_len);
1711 SSVAL(*rparam,4,count); /* is this right?? */
1712 SSVAL(*rparam,6,count); /* is this right?? */
1714 DEBUG(3,("api_RNetGroupEnum gave %d entries\n", count));
1719 /****************************************************************************
1720 view list of groups available
1721 ****************************************************************************/
1722 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1723 int mdrcnt,int mprcnt,
1724 char **rdata,char **rparam,
1725 int *rdata_len,int *rparam_len)
1727 char *str1 = param+2;
1728 char *str2 = skip_string(str1,1);
1729 char *p = skip_string(str2,1);
1730 int uLevel = SVAL(p,0);
1734 if (!prefix_ok(str1,"WrLeh")) return False;
1736 /* check it's a supported variant */
1746 if (strcmp(p2,str2) != 0) return False;
1748 *rdata_len = mdrcnt + 1024;
1749 *rdata = REALLOC(*rdata,*rdata_len);
1751 SSVAL(*rparam,0,NERR_Success);
1752 SSVAL(*rparam,2,0); /* converter word */
1756 /* XXXX we need a real SAM database some day */
1757 pstrcpy(p,"Users"); p += 21; count++;
1758 pstrcpy(p,"Domain Users"); p += 21; count++;
1759 pstrcpy(p,"Guests"); p += 21; count++;
1760 pstrcpy(p,"Domain Guests"); p += 21; count++;
1762 *rdata_len = PTR_DIFF(p,*rdata);
1765 *rparam = REALLOC(*rparam,*rparam_len);
1767 SSVAL(*rparam,4,count); /* is this right?? */
1768 SSVAL(*rparam,6,count); /* is this right?? */
1770 DEBUG(3,("api_RNetUserEnum gave %d entries\n", count));
1777 /****************************************************************************
1778 get the time of day info
1779 ****************************************************************************/
1780 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1781 int mdrcnt,int mprcnt,
1782 char **rdata,char **rparam,
1783 int *rdata_len,int *rparam_len)
1787 *rparam = REALLOC(*rparam,*rparam_len);
1790 *rdata = REALLOC(*rdata,*rdata_len);
1792 SSVAL(*rparam,0,NERR_Success);
1793 SSVAL(*rparam,2,0); /* converter word */
1799 time_t unixdate = time(NULL);
1801 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1802 by NT in a "net time" operation,
1803 it seems to ignore the one below */
1805 /* the client expects to get localtime, not GMT, in this bit
1806 (I think, this needs testing) */
1807 t = LocalTime(&unixdate);
1809 SIVAL(p,4,0); /* msecs ? */
1810 CVAL(p,8) = t->tm_hour;
1811 CVAL(p,9) = t->tm_min;
1812 CVAL(p,10) = t->tm_sec;
1813 CVAL(p,11) = 0; /* hundredths of seconds */
1814 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1815 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1816 CVAL(p,16) = t->tm_mday;
1817 CVAL(p,17) = t->tm_mon + 1;
1818 SSVAL(p,18,1900+t->tm_year);
1819 CVAL(p,20) = t->tm_wday;
1826 /****************************************************************************
1827 Set the user password.
1828 *****************************************************************************/
1830 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1831 int mdrcnt,int mprcnt,
1832 char **rdata,char **rparam,
1833 int *rdata_len,int *rparam_len)
1835 char *p = skip_string(param+2,2);
1837 fstring pass1,pass2;
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 (void)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,False))
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 (password_ok(user, pass1,strlen(pass1)) &&
1912 chgpasswd(user,pass1,pass2,False))
1914 SSVAL(*rparam,0,NERR_Success);
1919 * If the plaintext change failed, attempt
1920 * the old encrypted method. NT will generate this
1921 * after trying the samr method. Note that this
1922 * method is done as a last resort as this
1923 * password change method loses the NT password hash
1924 * and cannot change the UNIX password as no plaintext
1928 if(SVAL(*rparam,0) != NERR_Success)
1930 SAM_ACCOUNT *hnd = NULL;
1932 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) &&
1933 change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2))
1935 SSVAL(*rparam,0,NERR_Success);
1941 memset((char *)pass1,'\0',sizeof(fstring));
1942 memset((char *)pass2,'\0',sizeof(fstring));
1947 /****************************************************************************
1948 Set the user password (SamOEM version - gets plaintext).
1949 ****************************************************************************/
1951 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1952 int mdrcnt,int mprcnt,
1953 char **rdata,char **rparam,
1954 int *rdata_len,int *rparam_len)
1957 char *p = param + 2;
1959 *rparam = REALLOC(*rparam,*rparam_len);
1963 SSVAL(*rparam,0,NERR_badpass);
1966 * Check the parameter definition is correct.
1968 if(!strequal(param + 2, "zsT")) {
1969 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1972 p = skip_string(p, 1);
1974 if(!strequal(p, "B516B16")) {
1975 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1978 p = skip_string(p,1);
1980 p += pull_ascii_fstring(user,p);
1982 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1985 * Pass the user through the NT -> unix user mapping
1989 (void)map_username(user);
1992 * Do any UNIX username case mangling.
1994 (void)Get_Pwnam( user, True);
1996 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1998 SSVAL(*rparam,0,NERR_Success);
2004 /****************************************************************************
2007 ****************************************************************************/
2008 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2009 int mdrcnt,int mprcnt,
2010 char **rdata,char **rparam,
2011 int *rdata_len,int *rparam_len)
2013 int function = SVAL(param,0);
2014 char *str1 = param+2;
2015 char *str2 = skip_string(str1,1);
2016 char *p = skip_string(str2,1);
2018 extern struct current_user current_user;
2019 WERROR werr = WERR_OK;
2023 /* check it's a supported varient */
2024 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2028 *rparam = REALLOC(*rparam,*rparam_len);
2031 if (!print_job_exists(jobid)) {
2032 errcode = NERR_JobNotFound;
2036 errcode = NERR_notsupported;
2039 case 81: /* delete */
2040 if (print_job_delete(¤t_user, jobid, &werr))
2041 errcode = NERR_Success;
2043 case 82: /* pause */
2044 if (print_job_pause(¤t_user, jobid, &werr))
2045 errcode = NERR_Success;
2047 case 83: /* resume */
2048 if (print_job_resume(¤t_user, jobid, &werr))
2049 errcode = NERR_Success;
2053 if (!W_ERROR_IS_OK(werr))
2054 errcode = W_ERROR_V(werr);
2057 SSVAL(*rparam,0,errcode);
2058 SSVAL(*rparam,2,0); /* converter word */
2063 /****************************************************************************
2064 Purge a print queue - or pause or resume it.
2065 ****************************************************************************/
2066 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2067 int mdrcnt,int mprcnt,
2068 char **rdata,char **rparam,
2069 int *rdata_len,int *rparam_len)
2071 int function = SVAL(param,0);
2072 char *str1 = param+2;
2073 char *str2 = skip_string(str1,1);
2074 char *QueueName = skip_string(str2,1);
2075 int errcode = NERR_notsupported;
2077 WERROR werr = WERR_OK;
2078 extern struct current_user current_user;
2080 /* check it's a supported varient */
2081 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2085 *rparam = REALLOC(*rparam,*rparam_len);
2088 snum = print_queue_snum(QueueName);
2091 errcode = NERR_JobNotFound;
2096 case 74: /* Pause queue */
2097 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success;
2099 case 75: /* Resume queue */
2100 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success;
2102 case 103: /* Purge */
2103 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success;
2107 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2110 SSVAL(*rparam,0,errcode);
2111 SSVAL(*rparam,2,0); /* converter word */
2117 /****************************************************************************
2118 set the property of a print job (undocumented?)
2119 ? function = 0xb -> set name of print job
2120 ? function = 0x6 -> move print job up/down
2121 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2122 or <WWsTP> <WB21BB16B10zWWzDDz>
2123 ****************************************************************************/
2124 static int check_printjob_info(struct pack_desc* desc,
2125 int uLevel, char* id)
2127 desc->subformat = NULL;
2129 case 0: desc->format = "W"; break;
2130 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2131 case 2: desc->format = "WWzWWDDzz"; break;
2132 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2133 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2134 default: return False;
2136 if (strcmp(desc->format,id) != 0) return False;
2140 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2141 int mdrcnt,int mprcnt,
2142 char **rdata,char **rparam,
2143 int *rdata_len,int *rparam_len)
2145 struct pack_desc desc;
2146 char *str1 = param+2;
2147 char *str2 = skip_string(str1,1);
2148 char *p = skip_string(str2,1);
2150 int uLevel = SVAL(p,2);
2151 int function = SVAL(p,4);
2156 *rparam = REALLOC(*rparam,*rparam_len);
2160 /* check it's a supported varient */
2161 if ((strcmp(str1,"WWsTP")) ||
2162 (!check_printjob_info(&desc,uLevel,str2)))
2165 if (!print_job_exists(jobid)) {
2166 errcode=NERR_JobNotFound;
2170 errcode = NERR_notsupported;
2174 /* change job place in the queue,
2175 data gives the new place */
2176 place = SVAL(data,0);
2177 if (print_job_set_place(jobid, place)) {
2178 errcode=NERR_Success;
2183 /* change print job name, data gives the name */
2184 if (print_job_set_name(jobid, data)) {
2185 errcode=NERR_Success;
2194 SSVALS(*rparam,0,errcode);
2195 SSVAL(*rparam,2,0); /* converter word */
2201 /****************************************************************************
2202 get info about the server
2203 ****************************************************************************/
2204 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2205 int mdrcnt,int mprcnt,
2206 char **rdata,char **rparam,
2207 int *rdata_len,int *rparam_len)
2209 char *str1 = param+2;
2210 char *str2 = skip_string(str1,1);
2211 char *p = skip_string(str2,1);
2212 int uLevel = SVAL(p,0);
2216 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2218 /* check it's a supported varient */
2219 if (!prefix_ok(str1,"WrLh")) return False;
2222 if (strcmp(str2,"B16") != 0) return False;
2226 if (strcmp(str2,"B16BBDz") != 0) return False;
2230 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2235 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2240 if (strcmp(str2,"DN") != 0) return False;
2244 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2247 default: return False;
2250 *rdata_len = mdrcnt;
2251 *rdata = REALLOC(*rdata,*rdata_len);
2254 p2 = p + struct_len;
2256 srvstr_push(NULL, p,local_machine,16,
2257 STR_ASCII|STR_UPPER|STR_TERMINATE);
2262 struct srv_info_struct *servers=NULL;
2265 uint32 servertype= lp_default_server_announce();
2267 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2269 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2270 for (i=0;i<count;i++)
2271 if (strequal(servers[i].name,local_machine))
2273 servertype = servers[i].type;
2274 pstrcpy(comment,servers[i].comment);
2277 if (servers) free(servers);
2279 SCVAL(p,0,lp_major_announce_version());
2280 SCVAL(p,1,lp_minor_announce_version());
2281 SIVAL(p,2,servertype);
2283 if (mdrcnt == struct_len) {
2286 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2287 standard_sub_conn(conn,comment);
2288 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2289 p2 = skip_string(p2,1);
2294 return False; /* not yet implemented */
2297 *rdata_len = PTR_DIFF(p2,*rdata);
2300 *rparam = REALLOC(*rparam,*rparam_len);
2301 SSVAL(*rparam,0,NERR_Success);
2302 SSVAL(*rparam,2,0); /* converter word */
2303 SSVAL(*rparam,4,*rdata_len);
2309 /****************************************************************************
2310 get info about the server
2311 ****************************************************************************/
2312 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2313 int mdrcnt,int mprcnt,
2314 char **rdata,char **rparam,
2315 int *rdata_len,int *rparam_len)
2317 char *str1 = param+2;
2318 char *str2 = skip_string(str1,1);
2319 char *p = skip_string(str2,1);
2321 extern userdom_struct current_user_info;
2322 int level = SVAL(p,0);
2324 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2327 *rparam = REALLOC(*rparam,*rparam_len);
2329 /* check it's a supported varient */
2330 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2333 *rdata_len = mdrcnt + 1024;
2334 *rdata = REALLOC(*rdata,*rdata_len);
2336 SSVAL(*rparam,0,NERR_Success);
2337 SSVAL(*rparam,2,0); /* converter word */
2343 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2344 pstrcpy(p2,local_machine);
2346 p2 = skip_string(p2,1);
2349 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2350 pstrcpy(p2,current_user_info.smb_name);
2351 p2 = skip_string(p2,1);
2354 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2355 pstrcpy(p2,global_myworkgroup);
2357 p2 = skip_string(p2,1);
2360 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2361 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2364 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2365 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2366 p2 = skip_string(p2,1);
2369 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2371 p2 = skip_string(p2,1);
2374 *rdata_len = PTR_DIFF(p2,*rdata);
2376 SSVAL(*rparam,4,*rdata_len);
2381 /****************************************************************************
2382 get info about a user
2384 struct user_info_11 {
2385 char usri11_name[21]; 0-20
2387 char *usri11_comment; 22-25
2388 char *usri11_usr_comment; 26-29
2389 unsigned short usri11_priv; 30-31
2390 unsigned long usri11_auth_flags; 32-35
2391 long usri11_password_age; 36-39
2392 char *usri11_homedir; 40-43
2393 char *usri11_parms; 44-47
2394 long usri11_last_logon; 48-51
2395 long usri11_last_logoff; 52-55
2396 unsigned short usri11_bad_pw_count; 56-57
2397 unsigned short usri11_num_logons; 58-59
2398 char *usri11_logon_server; 60-63
2399 unsigned short usri11_country_code; 64-65
2400 char *usri11_workstations; 66-69
2401 unsigned long usri11_max_storage; 70-73
2402 unsigned short usri11_units_per_week; 74-75
2403 unsigned char *usri11_logon_hours; 76-79
2404 unsigned short usri11_code_page; 80-81
2409 usri11_name specifies the user name for which information is retireved
2411 usri11_pad aligns the next data structure element to a word boundary
2413 usri11_comment is a null terminated ASCII comment
2415 usri11_user_comment is a null terminated ASCII comment about the user
2417 usri11_priv specifies the level of the privilege assigned to the user.
2418 The possible values are:
2420 Name Value Description
2421 USER_PRIV_GUEST 0 Guest privilege
2422 USER_PRIV_USER 1 User privilege
2423 USER_PRV_ADMIN 2 Administrator privilege
2425 usri11_auth_flags specifies the account operator privileges. The
2426 possible values are:
2428 Name Value Description
2429 AF_OP_PRINT 0 Print operator
2432 Leach, Naik [Page 28]
2436 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2439 AF_OP_COMM 1 Communications operator
2440 AF_OP_SERVER 2 Server operator
2441 AF_OP_ACCOUNTS 3 Accounts operator
2444 usri11_password_age specifies how many seconds have elapsed since the
2445 password was last changed.
2447 usri11_home_dir points to a null terminated ASCII string that contains
2448 the path name of the user's home directory.
2450 usri11_parms points to a null terminated ASCII string that is set
2451 aside for use by applications.
2453 usri11_last_logon specifies the time when the user last logged on.
2454 This value is stored as the number of seconds elapsed since
2455 00:00:00, January 1, 1970.
2457 usri11_last_logoff specifies the time when the user last logged off.
2458 This value is stored as the number of seconds elapsed since
2459 00:00:00, January 1, 1970. A value of 0 means the last logoff
2462 usri11_bad_pw_count specifies the number of incorrect passwords
2463 entered since the last successful logon.
2465 usri11_log1_num_logons specifies the number of times this user has
2466 logged on. A value of -1 means the number of logons is unknown.
2468 usri11_logon_server points to a null terminated ASCII string that
2469 contains the name of the server to which logon requests are sent.
2470 A null string indicates logon requests should be sent to the
2473 usri11_country_code specifies the country code for the user's language
2476 usri11_workstations points to a null terminated ASCII string that
2477 contains the names of workstations the user may log on from.
2478 There may be up to 8 workstations, with the names separated by
2479 commas. A null strings indicates there are no restrictions.
2481 usri11_max_storage specifies the maximum amount of disk space the user
2482 can occupy. A value of 0xffffffff indicates there are no
2485 usri11_units_per_week specifies the equal number of time units into
2486 which a week is divided. This value must be equal to 168.
2488 usri11_logon_hours points to a 21 byte (168 bits) string that
2489 specifies the time during which the user can log on. Each bit
2490 represents one unique hour in a week. The first bit (bit 0, word
2491 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2495 Leach, Naik [Page 29]
2499 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2502 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2503 are no restrictions.
2505 usri11_code_page specifies the code page for the user's language of
2508 All of the pointers in this data structure need to be treated
2509 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2510 to be ignored. The converter word returned in the parameters section
2511 needs to be subtracted from the lower 16 bits to calculate an offset
2512 into the return buffer where this ASCII string resides.
2514 There is no auxiliary data in the response.
2516 ****************************************************************************/
2518 #define usri11_name 0
2519 #define usri11_pad 21
2520 #define usri11_comment 22
2521 #define usri11_usr_comment 26
2522 #define usri11_full_name 30
2523 #define usri11_priv 34
2524 #define usri11_auth_flags 36
2525 #define usri11_password_age 40
2526 #define usri11_homedir 44
2527 #define usri11_parms 48
2528 #define usri11_last_logon 52
2529 #define usri11_last_logoff 56
2530 #define usri11_bad_pw_count 60
2531 #define usri11_num_logons 62
2532 #define usri11_logon_server 64
2533 #define usri11_country_code 68
2534 #define usri11_workstations 70
2535 #define usri11_max_storage 74
2536 #define usri11_units_per_week 78
2537 #define usri11_logon_hours 80
2538 #define usri11_code_page 84
2539 #define usri11_end 86
2541 #define USER_PRIV_GUEST 0
2542 #define USER_PRIV_USER 1
2543 #define USER_PRIV_ADMIN 2
2545 #define AF_OP_PRINT 0
2546 #define AF_OP_COMM 1
2547 #define AF_OP_SERVER 2
2548 #define AF_OP_ACCOUNTS 3
2551 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2552 int mdrcnt,int mprcnt,
2553 char **rdata,char **rparam,
2554 int *rdata_len,int *rparam_len)
2556 char *str1 = param+2;
2557 char *str2 = skip_string(str1,1);
2558 char *UserName = skip_string(str2,1);
2559 char *p = skip_string(UserName,1);
2560 int uLevel = SVAL(p,0);
2563 /* get NIS home of a previously validated user - simeon */
2564 /* With share level security vuid will always be zero.
2565 Don't depend on vuser being non-null !!. JRA */
2566 user_struct *vuser = get_valid_user_struct(vuid);
2568 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2569 vuser->user.unix_name));
2572 *rparam = REALLOC(*rparam,*rparam_len);
2574 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2576 /* check it's a supported variant */
2577 if (strcmp(str1,"zWrLh") != 0) return False;
2580 case 0: p2 = "B21"; break;
2581 case 1: p2 = "B21BB16DWzzWz"; break;
2582 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2583 case 10: p2 = "B21Bzzz"; break;
2584 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2585 default: return False;
2588 if (strcmp(p2,str2) != 0) return False;
2590 *rdata_len = mdrcnt + 1024;
2591 *rdata = REALLOC(*rdata,*rdata_len);
2593 SSVAL(*rparam,0,NERR_Success);
2594 SSVAL(*rparam,2,0); /* converter word */
2597 p2 = p + usri11_end;
2600 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2604 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2609 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2610 pstrcpy(p2,"Comment");
2611 p2 = skip_string(p2,1);
2613 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2614 pstrcpy(p2,"UserComment");
2615 p2 = skip_string(p2,1);
2617 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2618 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2619 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2620 p2 = skip_string(p2,1);
2623 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2625 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2626 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2627 SIVALS(p,usri11_password_age,-1); /* password age */
2628 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2629 pstrcpy(p2, lp_logon_home());
2630 standard_sub_conn(conn, p2);
2631 p2 = skip_string(p2,1);
2632 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2634 p2 = skip_string(p2,1);
2635 SIVAL(p,usri11_last_logon,0); /* last logon */
2636 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2637 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2638 SSVALS(p,usri11_num_logons,-1); /* num logons */
2639 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2640 pstrcpy(p2,"\\\\*");
2641 p2 = skip_string(p2,1);
2642 SSVAL(p,usri11_country_code,0); /* country code */
2644 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2646 p2 = skip_string(p2,1);
2648 SIVALS(p,usri11_max_storage,-1); /* max storage */
2649 SSVAL(p,usri11_units_per_week,168); /* units per week */
2650 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2652 /* a simple way to get logon hours at all times. */
2654 SCVAL(p2,21,0); /* fix zero termination */
2655 p2 = skip_string(p2,1);
2657 SSVAL(p,usri11_code_page,0); /* code page */
2659 if (uLevel == 1 || uLevel == 2)
2661 memset(p+22,' ',16); /* password */
2662 SIVALS(p,38,-1); /* password age */
2664 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2665 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2666 pstrcpy(p2,lp_logon_home());
2667 standard_sub_conn(conn, p2);
2668 p2 = skip_string(p2,1);
2669 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2671 SSVAL(p,52,0); /* flags */
2672 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2673 pstrcpy(p2,lp_logon_script());
2674 standard_sub_conn( conn, p2 );
2675 p2 = skip_string(p2,1);
2678 SIVAL(p,60,0); /* auth_flags */
2679 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2680 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2681 p2 = skip_string(p2,1);
2682 SIVAL(p,68,0); /* urs_comment */
2683 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2685 p2 = skip_string(p2,1);
2686 SIVAL(p,76,0); /* workstations */
2687 SIVAL(p,80,0); /* last_logon */
2688 SIVAL(p,84,0); /* last_logoff */
2689 SIVALS(p,88,-1); /* acct_expires */
2690 SIVALS(p,92,-1); /* max_storage */
2691 SSVAL(p,96,168); /* units_per_week */
2692 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2695 SSVALS(p,102,-1); /* bad_pw_count */
2696 SSVALS(p,104,-1); /* num_logons */
2697 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2698 pstrcpy(p2,"\\\\%L");
2699 standard_sub_conn(conn, p2);
2700 p2 = skip_string(p2,1);
2701 SSVAL(p,110,49); /* country_code */
2702 SSVAL(p,112,860); /* code page */
2706 *rdata_len = PTR_DIFF(p2,*rdata);
2708 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2713 /*******************************************************************
2714 get groups that a user is a member of
2715 ******************************************************************/
2716 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2717 int mdrcnt,int mprcnt,
2718 char **rdata,char **rparam,
2719 int *rdata_len,int *rparam_len)
2721 char *str1 = param+2;
2722 char *str2 = skip_string(str1,1);
2723 char *UserName = skip_string(str2,1);
2724 char *p = skip_string(UserName,1);
2725 int uLevel = SVAL(p,0);
2730 *rparam = REALLOC(*rparam,*rparam_len);
2732 /* check it's a supported varient */
2733 if (strcmp(str1,"zWrLeh") != 0) return False;
2735 case 0: p2 = "B21"; break;
2736 default: return False;
2738 if (strcmp(p2,str2) != 0) return False;
2740 *rdata_len = mdrcnt + 1024;
2741 *rdata = REALLOC(*rdata,*rdata_len);
2743 SSVAL(*rparam,0,NERR_Success);
2744 SSVAL(*rparam,2,0); /* converter word */
2748 /* XXXX we need a real SAM database some day */
2749 pstrcpy(p,"Users"); p += 21; count++;
2750 pstrcpy(p,"Domain Users"); p += 21; count++;
2751 pstrcpy(p,"Guests"); p += 21; count++;
2752 pstrcpy(p,"Domain Guests"); p += 21; count++;
2754 *rdata_len = PTR_DIFF(p,*rdata);
2756 SSVAL(*rparam,4,count); /* is this right?? */
2757 SSVAL(*rparam,6,count); /* is this right?? */
2763 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2764 int mdrcnt,int mprcnt,
2765 char **rdata,char **rparam,
2766 int *rdata_len,int *rparam_len)
2768 char *str1 = param+2;
2769 char *str2 = skip_string(str1,1);
2770 char *p = skip_string(str2,1);
2772 struct pack_desc desc;
2778 memset((char *)&desc,'\0',sizeof(desc));
2780 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2782 /* check it's a supported varient */
2783 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2784 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2785 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2787 desc.buflen = mdrcnt;
2788 desc.subformat = NULL;
2791 if (init_package(&desc,1,0))
2793 PACKI(&desc,"W",0); /* code */
2794 PACKS(&desc,"B21",name); /* eff. name */
2795 PACKS(&desc,"B",""); /* pad */
2797 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2798 PACKI(&desc,"D",0); /* auth flags XXX */
2799 PACKI(&desc,"W",0); /* num logons */
2800 PACKI(&desc,"W",0); /* bad pw count */
2801 PACKI(&desc,"D",0); /* last logon */
2802 PACKI(&desc,"D",-1); /* last logoff */
2803 PACKI(&desc,"D",-1); /* logoff time */
2804 PACKI(&desc,"D",-1); /* kickoff time */
2805 PACKI(&desc,"D",0); /* password age */
2806 PACKI(&desc,"D",0); /* password can change */
2807 PACKI(&desc,"D",-1); /* password must change */
2810 fstrcpy(mypath,"\\\\");
2811 fstrcat(mypath,local_machine);
2813 PACKS(&desc,"z",mypath); /* computer */
2815 PACKS(&desc,"z",global_myworkgroup);/* domain */
2817 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2818 /* made sure all macros are fully substituted and available */
2820 pstring logon_script;
2821 pstrcpy(logon_script,lp_logon_script());
2822 standard_sub_conn( conn, logon_script );
2823 PACKS(&desc,"z", logon_script); /* script path */
2825 /* End of JHT mods */
2827 PACKI(&desc,"D",0x00000000); /* reserved */
2830 *rdata_len = desc.usedlen;
2832 *rparam = REALLOC(*rparam,*rparam_len);
2833 SSVALS(*rparam,0,desc.errcode);
2835 SSVAL(*rparam,4,desc.neededlen);
2837 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2842 /****************************************************************************
2843 api_WAccessGetUserPerms
2844 ****************************************************************************/
2845 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2846 int mdrcnt,int mprcnt,
2847 char **rdata,char **rparam,
2848 int *rdata_len,int *rparam_len)
2850 char *str1 = param+2;
2851 char *str2 = skip_string(str1,1);
2852 char *user = skip_string(str2,1);
2853 char *resource = skip_string(user,1);
2855 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2857 /* check it's a supported varient */
2858 if (strcmp(str1,"zzh") != 0) return False;
2859 if (strcmp(str2,"") != 0) return False;
2862 *rparam = REALLOC(*rparam,*rparam_len);
2863 SSVALS(*rparam,0,0); /* errorcode */
2864 SSVAL(*rparam,2,0); /* converter word */
2865 SSVAL(*rparam,4,0x7f); /* permission flags */
2870 /****************************************************************************
2871 api_WPrintJobEnumerate
2872 ****************************************************************************/
2873 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2874 int mdrcnt,int mprcnt,
2875 char **rdata,char **rparam,
2876 int *rdata_len,int *rparam_len)
2878 char *str1 = param+2;
2879 char *str2 = skip_string(str1,1);
2880 char *p = skip_string(str2,1);
2886 struct pack_desc desc;
2887 print_queue_struct *queue=NULL;
2888 print_status_struct status;
2893 memset((char *)&desc,'\0',sizeof(desc));
2894 memset((char *)&status,'\0',sizeof(status));
2896 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2898 /* check it's a supported varient */
2899 if (strcmp(str1,"WWrLh") != 0) return False;
2900 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2903 snum = print_job_snum(job);
2905 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2907 count = print_queue_status(snum,&queue,&status);
2908 for (i = 0; i < count; i++) {
2909 if (queue[i].job == job) break;
2913 *rdata = REALLOC(*rdata,mdrcnt);
2915 desc.buflen = mdrcnt;
2918 * Don't return data but need to get correct length
2919 * init_package will return wrong size if buflen=0
2921 desc.buflen = getlen(desc.format);
2922 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2925 if (init_package(&desc,1,0)) {
2927 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2928 *rdata_len = desc.usedlen;
2931 desc.errcode = NERR_JobNotFound;
2937 *rparam = REALLOC(*rparam,*rparam_len);
2938 SSVALS(*rparam,0,desc.errcode);
2940 SSVAL(*rparam,4,desc.neededlen);
2942 if (queue) free(queue);
2943 if (tmpdata) free(tmpdata);
2945 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2949 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2950 int mdrcnt,int mprcnt,
2951 char **rdata,char **rparam,
2952 int *rdata_len,int *rparam_len)
2954 char *str1 = param+2;
2955 char *str2 = skip_string(str1,1);
2956 char *p = skip_string(str2,1);
2962 struct pack_desc desc;
2963 print_queue_struct *queue=NULL;
2964 print_status_struct status;
2966 memset((char *)&desc,'\0',sizeof(desc));
2967 memset((char *)&status,'\0',sizeof(status));
2969 p = skip_string(p,1);
2972 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2974 /* check it's a supported varient */
2975 if (strcmp(str1,"zWrLeh") != 0) return False;
2976 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2977 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2979 snum = lp_servicenumber(name);
2980 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2981 int pnum = lp_servicenumber(PRINTERS_NAME);
2983 lp_add_printer(name,pnum);
2984 snum = lp_servicenumber(name);
2988 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2990 count = print_queue_status(snum,&queue,&status);
2991 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2993 desc.buflen = mdrcnt;
2995 if (init_package(&desc,count,0)) {
2997 for (i = 0; i < count; i++) {
2998 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2999 if (desc.errcode == NERR_Success) succnt = i+1;
3003 *rdata_len = desc.usedlen;
3006 *rparam = REALLOC(*rparam,*rparam_len);
3007 SSVALS(*rparam,0,desc.errcode);
3009 SSVAL(*rparam,4,succnt);
3010 SSVAL(*rparam,6,count);
3012 if (queue) free(queue);
3014 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3018 static int check_printdest_info(struct pack_desc* desc,
3019 int uLevel, char* id)
3021 desc->subformat = NULL;
3023 case 0: desc->format = "B9"; break;
3024 case 1: desc->format = "B9B21WWzW"; break;
3025 case 2: desc->format = "z"; break;
3026 case 3: desc->format = "zzzWWzzzWW"; break;
3027 default: return False;
3029 if (strcmp(desc->format,id) != 0) return False;
3033 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3034 struct pack_desc* desc)
3037 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3038 buf[sizeof(buf)-1] = 0;
3041 PACKS(desc,"B9",buf); /* szName */
3043 PACKS(desc,"B21",""); /* szUserName */
3044 PACKI(desc,"W",0); /* uJobId */
3045 PACKI(desc,"W",0); /* fsStatus */
3046 PACKS(desc,"z",""); /* pszStatus */
3047 PACKI(desc,"W",0); /* time */
3050 if (uLevel == 2 || uLevel == 3) {
3051 PACKS(desc,"z",buf); /* pszPrinterName */
3053 PACKS(desc,"z",""); /* pszUserName */
3054 PACKS(desc,"z",""); /* pszLogAddr */
3055 PACKI(desc,"W",0); /* uJobId */
3056 PACKI(desc,"W",0); /* fsStatus */
3057 PACKS(desc,"z",""); /* pszStatus */
3058 PACKS(desc,"z",""); /* pszComment */
3059 PACKS(desc,"z","NULL"); /* pszDrivers */
3060 PACKI(desc,"W",0); /* time */
3061 PACKI(desc,"W",0); /* pad1 */
3066 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3067 int mdrcnt,int mprcnt,
3068 char **rdata,char **rparam,
3069 int *rdata_len,int *rparam_len)
3071 char *str1 = param+2;
3072 char *str2 = skip_string(str1,1);
3073 char *p = skip_string(str2,1);
3074 char* PrinterName = p;
3076 struct pack_desc desc;
3080 memset((char *)&desc,'\0',sizeof(desc));
3082 p = skip_string(p,1);
3085 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3087 /* check it's a supported varient */
3088 if (strcmp(str1,"zWrLh") != 0) return False;
3089 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3091 snum = lp_servicenumber(PrinterName);
3092 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3093 int pnum = lp_servicenumber(PRINTERS_NAME);
3095 lp_add_printer(PrinterName,pnum);
3096 snum = lp_servicenumber(PrinterName);
3102 desc.errcode = NERR_DestNotFound;
3107 *rdata = REALLOC(*rdata,mdrcnt);
3109 desc.buflen = mdrcnt;
3112 * Don't return data but need to get correct length
3113 * init_package will return wrong size if buflen=0
3115 desc.buflen = getlen(desc.format);
3116 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3118 if (init_package(&desc,1,0)) {
3119 fill_printdest_info(conn,snum,uLevel,&desc);
3121 *rdata_len = desc.usedlen;
3125 *rparam = REALLOC(*rparam,*rparam_len);
3126 SSVALS(*rparam,0,desc.errcode);
3128 SSVAL(*rparam,4,desc.neededlen);
3130 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3131 if (tmpdata) free (tmpdata);
3135 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3136 int mdrcnt,int mprcnt,
3137 char **rdata,char **rparam,
3138 int *rdata_len,int *rparam_len)
3140 char *str1 = param+2;
3141 char *str2 = skip_string(str1,1);
3142 char *p = skip_string(str2,1);
3146 struct pack_desc desc;
3147 int services = lp_numservices();
3149 memset((char *)&desc,'\0',sizeof(desc));
3153 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3155 /* check it's a supported varient */
3156 if (strcmp(str1,"WrLeh") != 0) return False;
3157 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3160 for (i = 0; i < services; i++)
3161 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3164 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3166 desc.buflen = mdrcnt;
3167 if (init_package(&desc,queuecnt,0)) {
3170 for (i = 0; i < services; i++) {
3171 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3172 fill_printdest_info(conn,i,uLevel,&desc);
3174 if (desc.errcode == NERR_Success) succnt = n;
3179 *rdata_len = desc.usedlen;
3182 *rparam = REALLOC(*rparam,*rparam_len);
3183 SSVALS(*rparam,0,desc.errcode);
3185 SSVAL(*rparam,4,succnt);
3186 SSVAL(*rparam,6,queuecnt);
3188 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3192 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3193 int mdrcnt,int mprcnt,
3194 char **rdata,char **rparam,
3195 int *rdata_len,int *rparam_len)
3197 char *str1 = param+2;
3198 char *str2 = skip_string(str1,1);
3199 char *p = skip_string(str2,1);
3202 struct pack_desc desc;
3204 memset((char *)&desc,'\0',sizeof(desc));
3208 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3210 /* check it's a supported varient */
3211 if (strcmp(str1,"WrLeh") != 0) return False;
3212 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3214 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3216 desc.buflen = mdrcnt;
3217 if (init_package(&desc,1,0)) {
3218 PACKS(&desc,"B41","NULL");
3221 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3223 *rdata_len = desc.usedlen;
3226 *rparam = REALLOC(*rparam,*rparam_len);
3227 SSVALS(*rparam,0,desc.errcode);
3229 SSVAL(*rparam,4,succnt);
3232 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3236 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3237 int mdrcnt,int mprcnt,
3238 char **rdata,char **rparam,
3239 int *rdata_len,int *rparam_len)
3241 char *str1 = param+2;
3242 char *str2 = skip_string(str1,1);
3243 char *p = skip_string(str2,1);
3246 struct pack_desc desc;
3248 memset((char *)&desc,'\0',sizeof(desc));
3252 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3254 /* check it's a supported varient */
3255 if (strcmp(str1,"WrLeh") != 0) return False;
3256 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3258 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3260 desc.buflen = mdrcnt;
3262 if (init_package(&desc,1,0)) {
3263 PACKS(&desc,"B13","lpd");
3266 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3268 *rdata_len = desc.usedlen;
3271 *rparam = REALLOC(*rparam,*rparam_len);
3272 SSVALS(*rparam,0,desc.errcode);
3274 SSVAL(*rparam,4,succnt);
3277 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3281 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3282 int mdrcnt,int mprcnt,
3283 char **rdata,char **rparam,
3284 int *rdata_len,int *rparam_len)
3286 char *str1 = param+2;
3287 char *str2 = skip_string(str1,1);
3288 char *p = skip_string(str2,1);
3291 struct pack_desc desc;
3293 memset((char *)&desc,'\0',sizeof(desc));
3297 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3299 /* check it's a supported varient */
3300 if (strcmp(str1,"WrLeh") != 0) return False;
3301 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3303 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3304 memset((char *)&desc,'\0',sizeof(desc));
3306 desc.buflen = mdrcnt;
3308 if (init_package(&desc,1,0)) {
3309 PACKS(&desc,"B13","lp0");
3312 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3314 *rdata_len = desc.usedlen;
3317 *rparam = REALLOC(*rparam,*rparam_len);
3318 SSVALS(*rparam,0,desc.errcode);
3320 SSVAL(*rparam,4,succnt);
3323 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3327 /****************************************************************************
3328 The buffer was too small
3329 ****************************************************************************/
3331 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3332 int mdrcnt,int mprcnt,
3333 char **rdata,char **rparam,
3334 int *rdata_len,int *rparam_len)
3336 *rparam_len = MIN(*rparam_len,mprcnt);
3337 *rparam = REALLOC(*rparam,*rparam_len);
3341 SSVAL(*rparam,0,NERR_BufTooSmall);
3343 DEBUG(3,("Supplied buffer too small in API command\n"));
3349 /****************************************************************************
3350 The request is not supported
3351 ****************************************************************************/
3353 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3354 int mdrcnt,int mprcnt,
3355 char **rdata,char **rparam,
3356 int *rdata_len,int *rparam_len)
3359 *rparam = REALLOC(*rparam,*rparam_len);
3363 SSVAL(*rparam,0,NERR_notsupported);
3364 SSVAL(*rparam,2,0); /* converter word */
3366 DEBUG(3,("Unsupported API command\n"));
3378 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3379 int,int,char **,char **,int *,int *);
3381 } api_commands[] = {
3382 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3383 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3384 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3385 {"RNetGroupEnum", 47, api_RNetGroupEnum,0},
3386 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3387 {"RNetUserEnum", 53, api_RNetUserEnum,0},
3388 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3389 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3390 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3391 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3392 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3393 {"WPrintQueuePause", 74, api_WPrintQueueCtrl,0},
3394 {"WPrintQueueResume", 75, api_WPrintQueueCtrl,0},
3395 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3396 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3397 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3398 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3399 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3400 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3401 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3402 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3403 {"WPrintQueuePurge", 103, api_WPrintQueueCtrl,0},
3404 {"NetServerEnum", 104, api_RNetServerEnum,0},
3405 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3406 {"SetUserPassword", 115, api_SetUserPassword,0},
3407 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3408 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3409 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3410 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3411 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3412 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3413 {NULL, -1, api_Unsupported,0}};
3416 /****************************************************************************
3417 Handle remote api calls
3418 ****************************************************************************/
3420 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3421 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3425 char *rparam = NULL;
3432 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3436 api_command = SVAL(params,0);
3438 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3441 skip_string(params+2,1),
3442 tdscnt,tpscnt,mdrcnt,mprcnt));
3444 for (i=0;api_commands[i].name;i++) {
3445 if (api_commands[i].id == api_command && api_commands[i].fn) {
3446 DEBUG(3,("Doing %s\n",api_commands[i].name));
3451 rdata = (char *)malloc(1024);
3453 memset(rdata,'\0',1024);
3455 rparam = (char *)malloc(1024);
3457 memset(rparam,'\0',1024);
3459 if(!rdata || !rparam) {
3460 DEBUG(0,("api_reply: malloc fail !\n"));
3464 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3465 &rdata,&rparam,&rdata_len,&rparam_len);
3468 if (rdata_len > mdrcnt ||
3469 rparam_len > mprcnt) {
3470 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3471 &rdata,&rparam,&rdata_len,&rparam_len);
3474 /* if we get False back then it's actually unsupported */
3476 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3477 &rdata,&rparam,&rdata_len,&rparam_len);
3479 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);