2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1998
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
36 extern fstring local_machine
;
37 extern pstring global_myname
;
38 extern fstring global_myworkgroup
;
40 #define NERR_Success 0
41 #define NERR_badpass 86
42 #define NERR_notsupported 50
44 #define NERR_BASE (2100)
45 #define NERR_BufTooSmall (NERR_BASE+23)
46 #define NERR_JobNotFound (NERR_BASE+51)
47 #define NERR_DestNotFound (NERR_BASE+52)
49 #define ACCESS_READ 0x01
50 #define ACCESS_WRITE 0x02
51 #define ACCESS_CREATE 0x04
53 #define SHPWLEN 8 /* share password length */
55 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
56 int mdrcnt
,int mprcnt
,
57 char **rdata
,char **rparam
,
58 int *rdata_len
,int *rparam_len
);
59 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
60 int mdrcnt
,int mprcnt
,
61 char **rdata
,char **rparam
,
62 int *rdata_len
,int *rparam_len
);
65 static int CopyExpanded(connection_struct
*conn
,
66 int snum
, char** dst
, char* src
, int* n
)
71 if (!src
|| !dst
|| !n
|| !(*dst
)) return(0);
73 StrnCpy(buf
,src
,sizeof(buf
)/2);
74 pstring_sub(buf
,"%S",lp_servicename(snum
));
75 standard_sub_conn(conn
,buf
,sizeof(buf
));
76 StrnCpy(*dst
,buf
,*n
-1);
83 static int CopyAndAdvance(char** dst
, char* src
, int* n
)
86 if (!src
|| !dst
|| !n
|| !(*dst
)) return(0);
87 StrnCpy(*dst
,src
,*n
-1);
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
,sizeof(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
,sizeof(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
);
223 static int package(struct pack_desc
* p
, ...)
226 static int package(va_alist
)
232 int needed
=0, stringneeded
;
234 int is_string
=0, stringused
;
241 p
= va_arg(args
,struct pack_desc
*);
246 p
->curpos
= p
->format
;
248 p
->curpos
= p
->subformat
;
253 str
= va_arg(args
,char*);
254 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
263 switch( *p
->curpos
++ ) {
264 case 'W': /* word (2 byte) */
266 temp
= va_arg(args
,int);
267 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,temp
);
269 case 'K': /* status word? (2 byte) */
271 temp
= va_arg(args
,int);
272 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,temp
);
274 case 'N': /* count of substructures (word) at end */
276 p
->subcount
= va_arg(args
,int);
277 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,p
->subcount
);
279 case 'D': /* double word (4 byte) */
281 temp
= va_arg(args
,int);
282 if (p
->buflen
>= needed
) SIVAL(p
->structbuf
,0,temp
);
284 case 'B': /* byte (with optional counter) */
285 needed
= get_counter(&p
->curpos
);
287 char *s
= va_arg(args
,char*);
288 if (p
->buflen
>= needed
) StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
291 case 'z': /* offset to zero terminated string (4 byte) */
292 str
= va_arg(args
,char*);
293 stringneeded
= (str
? strlen(str
)+1 : 0);
296 case 'l': /* offset to user data (4 byte) */
297 str
= va_arg(args
,char*);
298 stringneeded
= va_arg(args
,int);
301 case 'b': /* offset to data (with counter) (4 byte) */
302 str
= va_arg(args
,char*);
303 stringneeded
= get_counter(&p
->curpos
);
308 if (stringneeded
>= 0) {
310 if (p
->buflen
>= needed
) {
311 stringused
= stringneeded
;
312 if (stringused
> p
->stringlen
) {
313 stringused
= (is_string
? p
->stringlen
: 0);
314 if (p
->errcode
== NERR_Success
) p
->errcode
= ERRmoredata
;
317 SIVAL(p
->structbuf
,0,0);
319 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
320 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
321 if (is_string
) p
->stringbuf
[stringused
-1] = '\0';
322 p
->stringbuf
+= stringused
;
323 p
->stringlen
-= stringused
;
324 p
->usedlen
+= stringused
;
327 p
->neededlen
+= stringneeded
;
329 p
->neededlen
+= needed
;
330 if (p
->buflen
>= needed
) {
331 p
->structbuf
+= needed
;
333 p
->usedlen
+= needed
;
336 if (p
->errcode
== NERR_Success
) p
->errcode
= ERRmoredata
;
342 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
343 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
345 #define PACK(desc,t,v) package(desc,v)
346 #define PACKl(desc,t,v,l) package(desc,v,l)
349 static void PACKI(struct pack_desc
* desc
,char *t
,int v
)
354 static void PACKS(struct pack_desc
* desc
,char *t
,char *v
)
360 /****************************************************************************
362 ****************************************************************************/
363 static void PackDriverData(struct pack_desc
* desc
)
365 char drivdata
[4+4+32];
366 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
367 SIVAL(drivdata
,4,1000); /* lVersion */
368 memset(drivdata
+8,0,32); /* szDeviceName */
369 pstrcpy(drivdata
+8,"NULL");
370 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
373 static int check_printq_info(struct pack_desc
* desc
,
374 int uLevel
, char *id1
, char *id2
)
376 desc
->subformat
= NULL
;
379 desc
->format
= "B13";
382 desc
->format
= "B13BWWWzzzzzWW";
385 desc
->format
= "B13BWWWzzzzzWN";
386 desc
->subformat
= "WB21BB16B10zWWzDDz";
389 desc
->format
= "zWWWWzzzzWWzzl";
392 desc
->format
= "zWWWWzzzzWNzzl";
393 desc
->subformat
= "WWzWWDDzz";
402 desc
->format
= "WzzzzzzzzN";
403 desc
->subformat
= "z";
405 default: return False
;
407 if (strcmp(desc
->format
,id1
) != 0) return False
;
408 if (desc
->subformat
&& strcmp(desc
->subformat
,id2
) != 0) return False
;
413 #define RAP_JOB_STATUS_QUEUED 0
414 #define RAP_JOB_STATUS_PAUSED 1
415 #define RAP_JOB_STATUS_SPOOLING 2
416 #define RAP_JOB_STATUS_PRINTING 3
417 #define RAP_JOB_STATUS_PRINTED 4
419 #define RAP_QUEUE_STATUS_PAUSED 1
420 #define RAP_QUEUE_STATUS_ERROR 2
422 /* turn a print job status into a on the wire status
424 static int printj_status(int v
)
428 return RAP_JOB_STATUS_QUEUED
;
430 return RAP_JOB_STATUS_PAUSED
;
432 return RAP_JOB_STATUS_SPOOLING
;
434 return RAP_JOB_STATUS_PRINTING
;
439 /* turn a print queue status into a on the wire status
441 static int printq_status(int v
)
447 return RAP_QUEUE_STATUS_PAUSED
;
449 return RAP_QUEUE_STATUS_ERROR
;
452 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
453 struct pack_desc
* desc
,
454 print_queue_struct
* queue
, int n
)
456 time_t t
= queue
->time
;
458 /* the client expects localtime */
461 PACKI(desc
,"W",queue
->job
); /* uJobId */
463 PACKS(desc
,"B21",dos_to_unix_static(queue
->fs_user
)); /* szUserName */
464 PACKS(desc
,"B",""); /* pad */
465 PACKS(desc
,"B16",""); /* szNotifyName */
466 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
467 PACKS(desc
,"z",""); /* pszParms */
468 PACKI(desc
,"W",n
+1); /* uPosition */
469 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
470 PACKS(desc
,"z",""); /* pszStatus */
471 PACKI(desc
,"D",t
); /* ulSubmitted */
472 PACKI(desc
,"D",queue
->size
); /* ulSize */
473 PACKS(desc
,"z",dos_to_unix_static(queue
->fs_file
)); /* pszComment */
475 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
476 PACKI(desc
,"W",queue
->priority
); /* uPriority */
477 PACKS(desc
,"z",dos_to_unix_static(queue
->fs_user
)); /* pszUserName */
478 PACKI(desc
,"W",n
+1); /* uPosition */
479 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
480 PACKI(desc
,"D",t
); /* ulSubmitted */
481 PACKI(desc
,"D",queue
->size
); /* ulSize */
482 PACKS(desc
,"z","Samba"); /* pszComment */
483 PACKS(desc
,"z",dos_to_unix_static(queue
->fs_file
)); /* pszDocument */
485 PACKS(desc
,"z",""); /* pszNotifyName */
486 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
487 PACKS(desc
,"z",""); /* pszParms */
488 PACKS(desc
,"z",""); /* pszStatus */
489 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
490 PACKS(desc
,"z","lpd"); /* pszQProcName */
491 PACKS(desc
,"z",""); /* pszQProcParms */
492 PACKS(desc
,"z","NULL"); /* pszDriverName */
493 PackDriverData(desc
); /* pDriverData */
494 PACKS(desc
,"z",""); /* pszPrinterName */
495 } else if (uLevel
== 4) { /* OS2 */
496 PACKS(desc
,"z",""); /* pszSpoolFileName */
497 PACKS(desc
,"z",""); /* pszPortName */
498 PACKS(desc
,"z",""); /* pszStatus */
499 PACKI(desc
,"D",0); /* ulPagesSpooled */
500 PACKI(desc
,"D",0); /* ulPagesSent */
501 PACKI(desc
,"D",0); /* ulPagesPrinted */
502 PACKI(desc
,"D",0); /* ulTimePrinted */
503 PACKI(desc
,"D",0); /* ulExtendJobStatus */
504 PACKI(desc
,"D",0); /* ulStartPage */
505 PACKI(desc
,"D",0); /* ulEndPage */
510 /********************************************************************
511 Return a driver name given an snum.
512 Looks in a tdb first. Returns True if from tdb, False otherwise.
513 ********************************************************************/
515 static BOOL
get_driver_name(int snum
, pstring drivername
)
517 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
520 get_a_printer (&info
, 2, lp_servicename(snum
));
522 pstrcpy( drivername
, info
->info_2
->drivername
);
524 free_a_printer(&info
, 2);
526 pstrcpy( drivername
, lp_printerdriver(snum
));
532 /********************************************************************
533 Respond to the DosPrintQInfo command with a level of 52
534 This is used to get printer driver information for Win9x clients
535 ********************************************************************/
536 static void fill_printq_info_52(connection_struct
*conn
, int snum
, int uLevel
,
537 struct pack_desc
* desc
,
538 int count
, print_queue_struct
* queue
,
539 print_status_struct
* status
)
543 pstring tok
,driver
,datafile
,langmon
,helpfile
,datatype
;
552 * Check in the tdb *first* before checking the legacy
553 * files. This allows an NT upload to take precedence over
554 * the existing fileset. JRA.
556 * we need to lookup the driver name prior to making the call
557 * to get_a_printer_driver_9x_compatible() and not rely on the
558 * 'print driver' parameter --jerry
562 if ((get_driver_name(snum
,drivername
)) &&
563 ((ok
= get_a_printer_driver_9x_compatible(gen_line
, drivername
)) == True
))
567 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername
, gen_line
));
571 /* didn't find driver in tdb */
573 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
574 snum
, drivername
, lp_driverfile(snum
)));
576 lines
= file_lines_load(lp_driverfile(snum
),NULL
, False
);
579 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum
),
581 desc
->errcode
=NERR_notsupported
;
585 /* lookup the long printer driver name in the file description */
586 for (i
=0;lines
[i
] && !ok
;i
++)
589 if (next_token(&p
,tok
,":",sizeof(tok
)) &&
590 (strlen(drivername
) == strlen(tok
)) &&
591 (!strncmp(tok
,drivername
,strlen(drivername
))))
600 /* driver file name */
601 if (!next_token(&p
,driver
,":",sizeof(driver
)))
605 if (!next_token(&p
,datafile
,":",sizeof(datafile
)))
609 * for the next tokens - which may be empty - I have
610 * to check for empty tokens first because the
611 * next_token function will skip all empty token
620 else if (!next_token(&p
,helpfile
,":",sizeof(helpfile
)))
623 /* language monitor */
629 else if (!next_token(&p
,langmon
,":",sizeof(langmon
)))
632 /* default data type */
633 if (!next_token(&p
,datatype
,":",sizeof(datatype
)))
636 PACKI(desc
,"W",0x0400); /* don't know */
637 PACKS(desc
,"z",drivername
); /* long printer name */
638 PACKS(desc
,"z",driver
); /* Driverfile Name */
639 PACKS(desc
,"z",datafile
); /* Datafile name */
640 PACKS(desc
,"z",langmon
); /* language monitor */
643 fstrcpy(location
, "\\\\");
644 fstrcat(location
, global_myname
);
645 fstrcat(location
, "\\print$\\WIN40\\0");
646 PACKS(desc
,"z",location
); /* share to retrieve files */
650 PACKS(desc
,"z",lp_driverlocation(snum
)); /* share to retrieve files */
652 PACKS(desc
,"z",datatype
); /* default data type */
653 PACKS(desc
,"z",helpfile
); /* helpfile name */
654 PACKS(desc
,"z",driver
); /* driver name */
656 DEBUG(3,("printerdriver:%s:\n",drivername
));
657 DEBUG(3,("Driver:%s:\n",driver
));
658 DEBUG(3,("Data File:%s:\n",datafile
));
659 DEBUG(3,("Language Monitor:%s:\n",langmon
));
661 DEBUG(3,("lp_driverlocation:%s:\n",location
));
663 DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum
)));
664 DEBUG(3,("Data Type:%s:\n",datatype
));
665 DEBUG(3,("Help File:%s:\n",helpfile
));
666 PACKI(desc
,"N",count
); /* number of files to copy */
668 for (i
=0;i
<count
;i
++)
670 /* no need to check return value here
671 * - it was already tested in
672 * get_printerdrivernumber */
673 next_token(&p
,tok
,",",sizeof(tok
));
674 PACKS(desc
,"z",tok
); /* driver files to copy */
675 DEBUG(3,("file:%s:\n",tok
));
678 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
679 SERVICE(snum
),count
));
681 desc
->errcode
=NERR_Success
;
687 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
688 desc
->errcode
=NERR_notsupported
;
691 file_lines_free(lines
);
695 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
696 struct pack_desc
* desc
,
697 int count
, print_queue_struct
* queue
,
698 print_status_struct
* status
)
703 PACKS(desc
,"B13",SERVICE(snum
));
708 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
711 PACKI(desc
,"K",printq_status(status
->status
));
715 if (uLevel
== 1 || uLevel
== 2) {
716 PACKS(desc
,"B",""); /* alignment */
717 PACKI(desc
,"W",5); /* priority */
718 PACKI(desc
,"W",0); /* start time */
719 PACKI(desc
,"W",0); /* until time */
720 PACKS(desc
,"z",""); /* pSepFile */
721 PACKS(desc
,"z","lpd"); /* pPrProc */
722 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
723 PACKS(desc
,"z",""); /* pParms */
725 PACKS(desc
,"z","UNKNOWN PRINTER");
726 PACKI(desc
,"W",LPSTAT_ERROR
);
728 else if (!status
|| !status
->message
[0]) {
729 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
730 PACKI(desc
,"W",LPSTAT_OK
); /* status */
732 PACKS(desc
,"z",status
->message
);
733 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
735 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
738 if (uLevel
== 3 || uLevel
== 4) {
741 PACKI(desc
,"W",5); /* uPriority */
742 PACKI(desc
,"W",0); /* uStarttime */
743 PACKI(desc
,"W",0); /* uUntiltime */
744 PACKI(desc
,"W",5); /* pad1 */
745 PACKS(desc
,"z",""); /* pszSepFile */
746 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
747 PACKS(desc
,"z",NULL
); /* pszParms */
748 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
749 /* "don't ask" that it's done this way to fix corrupted
750 Win9X/ME printer comments. */
752 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
754 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
756 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
757 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
758 get_driver_name(snum
,drivername
);
759 PACKS(desc
,"z",drivername
); /* pszDriverName */
760 PackDriverData(desc
); /* pDriverData */
763 if (uLevel
== 2 || uLevel
== 4) {
765 for (i
=0;i
<count
;i
++)
766 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
770 fill_printq_info_52(conn
, snum
, uLevel
, desc
, count
, queue
, status
);
774 /* This function returns the number of files for a given driver */
775 static int get_printerdrivernumber(int snum
)
786 * Check in the tdb *first* before checking the legacy
787 * files. This allows an NT upload to take precedence over
788 * the existing fileset. JRA.
790 * we need to lookup the driver name prior to making the call
791 * to get_a_printer_driver_9x_compatible() and not rely on the
792 * 'print driver' parameter --jerry
795 if ((get_driver_name(snum
,drivername
)) &&
796 (ok
= get_a_printer_driver_9x_compatible(gen_line
, drivername
) == True
))
799 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername
, gen_line
));
803 /* didn't find driver in tdb */
805 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
806 snum
, drivername
, lp_driverfile(snum
)));
808 lines
= file_lines_load(lp_driverfile(snum
), NULL
, False
);
811 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum
),strerror(errno
)));
815 /* lookup the long printer driver name in the file description */
816 for (i
=0;lines
[i
] && !ok
;i
++)
819 if (next_token(&p
,tok
,":",sizeof(tok
)) &&
820 (strlen(drivername
) == strlen(tok
)) &&
821 (!strncmp(tok
,drivername
,strlen(drivername
))))
833 if (*p
++ == ':') i
--;
836 DEBUG(3,("Can't determine number of printer driver files\n"));
840 /* count the number of files */
841 while (next_token(&p
,tok
,",",sizeof(tok
)))
849 file_lines_free(lines
);
854 static BOOL
api_DosPrintQGetInfo(connection_struct
*conn
,
855 uint16 vuid
, char *param
,char *data
,
856 int mdrcnt
,int mprcnt
,
857 char **rdata
,char **rparam
,
858 int *rdata_len
,int *rparam_len
)
860 char *str1
= param
+2;
861 char *str2
= skip_string(str1
,1);
862 char *p
= skip_string(str2
,1);
868 struct pack_desc desc
;
869 print_queue_struct
*queue
=NULL
;
870 print_status_struct status
;
873 memset((char *)&status
,'\0',sizeof(status
));
874 memset((char *)&desc
,'\0',sizeof(desc
));
876 p
= skip_string(p
,1);
880 /* remove any trailing username */
881 if ((p
= strchr(QueueName
,'%')))
884 DEBUG(3,("api_DosPrintQGetInfo: uLevel=%d name=%s\n",uLevel
,QueueName
));
886 /* check it's a supported varient */
887 if (!prefix_ok(str1
,"zWrLh"))
889 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
891 * Patch from Scott Moomaw <scott@bridgewater.edu>
892 * to return the 'invalid info level' error if an
893 * unknown level was requested.
897 *rparam
= REALLOC(*rparam
,*rparam_len
);
898 SSVALS(*rparam
,0,ERRunknownlevel
);
904 snum
= lp_servicenumber(QueueName
);
905 if (snum
< 0 && pcap_printername_ok(QueueName
,NULL
)) {
906 int pnum
= lp_servicenumber(PRINTERS_NAME
);
908 lp_add_printer(QueueName
,pnum
);
909 snum
= lp_servicenumber(QueueName
);
913 if (snum
< 0 || !VALID_SNUM(snum
))
917 count
= get_printerdrivernumber(snum
);
918 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
920 count
= print_queue_status(snum
, &queue
,&status
);
924 *rdata
= REALLOC(*rdata
,mdrcnt
);
926 desc
.buflen
= mdrcnt
;
929 * Don't return data but need to get correct length
930 * init_package will return wrong size if buflen=0
932 desc
.buflen
= getlen(desc
.format
);
933 desc
.base
= tmpdata
= (char *) malloc (desc
.buflen
);
936 if (init_package(&desc
,1,count
)) {
937 desc
.subcount
= count
;
938 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
942 * We must set the return code to ERRbuftoosmall
943 * in order to support lanman style printing with Win NT/2k
946 if (!mdrcnt
&& lp_disable_spoolss())
947 desc
.errcode
= ERRbuftoosmall
;
949 *rdata_len
= desc
.usedlen
;
952 *rparam
= REALLOC(*rparam
,*rparam_len
);
953 SSVALS(*rparam
,0,desc
.errcode
);
955 SSVAL(*rparam
,4,desc
.neededlen
);
957 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
965 /****************************************************************************
966 View list of all print jobs on all queues.
967 ****************************************************************************/
969 static BOOL
api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
, char* param
, char* data
,
970 int mdrcnt
, int mprcnt
,
971 char **rdata
, char** rparam
,
972 int *rdata_len
, int *rparam_len
)
974 char *param_format
= param
+2;
975 char *output_format1
= skip_string(param_format
,1);
976 char *p
= skip_string(output_format1
,1);
977 int uLevel
= SVAL(p
,0);
978 char *output_format2
= p
+ 4;
979 int services
= lp_numservices();
981 struct pack_desc desc
;
982 print_queue_struct
**queue
= NULL
;
983 print_status_struct
*status
= NULL
;
984 int* subcntarr
= NULL
;
985 int queuecnt
, subcnt
=0, succnt
=0;
987 memset((char *)&desc
,'\0',sizeof(desc
));
989 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
991 if (!prefix_ok(param_format
,"WrLeh")) return False
;
992 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
994 * Patch from Scott Moomaw <scott@bridgewater.edu>
995 * to return the 'invalid info level' error if an
996 * unknown level was requested.
1000 *rparam
= REALLOC(*rparam
,*rparam_len
);
1001 SSVALS(*rparam
,0,ERRunknownlevel
);
1008 for (i
= 0; i
< services
; i
++)
1009 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
1012 if((queue
= (print_queue_struct
**)malloc(queuecnt
*sizeof(print_queue_struct
*))) == NULL
) {
1013 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1016 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
1017 if((status
= (print_status_struct
*)malloc(queuecnt
*sizeof(print_status_struct
))) == NULL
) {
1018 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1021 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
1022 if((subcntarr
= (int*)malloc(queuecnt
*sizeof(int))) == NULL
) {
1023 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1028 for (i
= 0; i
< services
; i
++)
1029 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1030 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
1031 subcnt
+= subcntarr
[n
];
1035 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
1037 desc
.buflen
= mdrcnt
;
1039 if (init_package(&desc
,queuecnt
,subcnt
)) {
1042 for (i
= 0; i
< services
; i
++)
1043 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1044 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
1046 if (desc
.errcode
== NERR_Success
) succnt
= n
;
1050 SAFE_FREE(subcntarr
);
1052 *rdata_len
= desc
.usedlen
;
1054 *rparam
= REALLOC(*rparam
,*rparam_len
);
1055 SSVALS(*rparam
,0,desc
.errcode
);
1057 SSVAL(*rparam
,4,succnt
);
1058 SSVAL(*rparam
,6,queuecnt
);
1060 for (i
= 0; i
< queuecnt
; i
++) {
1061 if (queue
) SAFE_FREE(queue
[i
]);
1070 /****************************************************************************
1071 get info level for a server list query
1072 ****************************************************************************/
1073 static BOOL
check_server_info(int uLevel
, char* id
)
1077 if (strcmp(id
,"B16") != 0) return False
;
1080 if (strcmp(id
,"B16BBDz") != 0) return False
;
1088 struct srv_info_struct
1098 /*******************************************************************
1099 get server info lists from the files saved by nmbd. Return the
1101 ******************************************************************/
1102 static int get_server_info(uint32 servertype
,
1103 struct srv_info_struct
**servers
,
1109 BOOL local_list_only
;
1112 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
, False
);
1114 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
1118 /* request for everything is code for request all servers */
1119 if (servertype
== SV_TYPE_ALL
)
1120 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1122 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1124 DEBUG(4,("Servertype search: %8x\n",servertype
));
1126 for (i
=0;lines
[i
];i
++) {
1128 struct srv_info_struct
*s
;
1129 char *ptr
= lines
[i
];
1132 if (!*ptr
) continue;
1134 if (count
== alloced
) {
1135 struct srv_info_struct
*ts
;
1138 ts
= (struct srv_info_struct
*)
1139 Realloc(*servers
,sizeof(**servers
)*alloced
);
1141 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1145 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1147 s
= &(*servers
)[count
];
1149 if (!next_token(&ptr
,s
->name
, NULL
, sizeof(s
->name
))) continue;
1150 if (!next_token(&ptr
,stype
, NULL
, sizeof(stype
))) continue;
1151 if (!next_token(&ptr
,s
->comment
, NULL
, sizeof(s
->comment
))) continue;
1152 if (!next_token(&ptr
,s
->domain
, NULL
, sizeof(s
->domain
))) {
1153 /* this allows us to cope with an old nmbd */
1154 pstrcpy(s
->domain
,global_myworkgroup
);
1157 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1158 DEBUG(4,("r:host file "));
1162 /* Filter the servers/domains we return based on what was asked for. */
1164 /* Check to see if we are being asked for a local list only. */
1165 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1166 DEBUG(4,("r: local list only"));
1170 /* doesn't match up: don't want it */
1171 if (!(servertype
& s
->type
)) {
1172 DEBUG(4,("r:serv type "));
1176 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1177 (s
->type
& SV_TYPE_DOMAIN_ENUM
))
1179 DEBUG(4,("s: dom mismatch "));
1183 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1188 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1189 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1193 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1194 s
->name
, s
->type
, s
->comment
, s
->domain
));
1196 s
->server_added
= True
;
1201 DEBUG(4,("%20s %8x %25s %15s\n",
1202 s
->name
, s
->type
, s
->comment
, s
->domain
));
1206 file_lines_free(lines
);
1211 /*******************************************************************
1212 fill in a server info structure
1213 ******************************************************************/
1214 static int fill_srv_info(struct srv_info_struct
*service
,
1215 int uLevel
, char **buf
, int *buflen
,
1216 char **stringbuf
, int *stringspace
, char *baseaddr
)
1225 case 0: struct_len
= 16; break;
1226 case 1: struct_len
= 26; break;
1236 len
= strlen(service
->comment
)+1;
1240 if (buflen
) *buflen
= struct_len
;
1241 if (stringspace
) *stringspace
= len
;
1242 return struct_len
+ len
;
1247 if (*buflen
< struct_len
) return -1;
1255 p2
= p
+ struct_len
;
1256 l2
= *buflen
- struct_len
;
1258 if (!baseaddr
) baseaddr
= p
;
1263 StrnCpy(p
,service
->name
,15);
1267 StrnCpy(p
,service
->name
,15);
1268 SIVAL(p
,18,service
->type
);
1269 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1270 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1276 *buf
= p
+ struct_len
;
1277 *buflen
-= struct_len
;
1290 static BOOL
srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1292 return(strcmp(s1
->name
,s2
->name
));
1295 /****************************************************************************
1296 view list of servers available (or possibly domains). The info is
1297 extracted from lists saved by nmbd on the local host
1298 ****************************************************************************/
1299 static BOOL
api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1300 int mdrcnt
, int mprcnt
, char **rdata
,
1301 char **rparam
, int *rdata_len
, int *rparam_len
)
1303 char *str1
= param
+2;
1304 char *str2
= skip_string(str1
,1);
1305 char *p
= skip_string(str2
,1);
1306 int uLevel
= SVAL(p
,0);
1307 int buf_len
= SVAL(p
,2);
1308 uint32 servertype
= IVAL(p
,4);
1310 int data_len
, fixed_len
, string_len
;
1311 int f_len
= 0, s_len
= 0;
1312 struct srv_info_struct
*servers
=NULL
;
1313 int counted
=0,total
=0;
1316 BOOL domain_request
;
1319 /* If someone sets all the bits they don't really mean to set
1320 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1323 if (servertype
== SV_TYPE_ALL
)
1324 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1326 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1327 any other bit (they may just set this bit on it's own) they
1328 want all the locally seen servers. However this bit can be
1329 set on its own so set the requested servers to be
1330 ALL - DOMAIN_ENUM. */
1332 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1333 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1335 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1336 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1340 if (!prefix_ok(str1
,"WrLehD")) return False
;
1341 if (!check_server_info(uLevel
,str2
)) return False
;
1343 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1344 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1345 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1347 if (strcmp(str1
, "WrLehDz") == 0) {
1348 StrnCpy(domain
, p
, sizeof(fstring
)-1);
1350 StrnCpy(domain
, global_myworkgroup
, sizeof(fstring
)-1);
1353 if (lp_browse_list())
1354 total
= get_server_info(servertype
,&servers
,domain
);
1356 data_len
= fixed_len
= string_len
= 0;
1360 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1363 char *lastname
=NULL
;
1365 for (i
=0;i
<total
;i
++)
1367 struct srv_info_struct
*s
= &servers
[i
];
1368 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1370 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1371 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1372 s
->name
, s
->type
, s
->comment
, s
->domain
));
1374 if (data_len
<= buf_len
) {
1377 string_len
+= s_len
;
1384 *rdata_len
= fixed_len
+ string_len
;
1385 *rdata
= REALLOC(*rdata
,*rdata_len
);
1386 memset(*rdata
,'\0',*rdata_len
);
1388 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1394 char *lastname
=NULL
;
1395 int count2
= counted
;
1396 for (i
= 0; i
< total
&& count2
;i
++)
1398 struct srv_info_struct
*s
= &servers
[i
];
1399 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1401 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1402 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1403 s
->name
, s
->type
, s
->comment
, s
->domain
));
1409 *rparam
= REALLOC(*rparam
,*rparam_len
);
1410 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1412 SSVAL(*rparam
,4,counted
);
1413 SSVAL(*rparam
,6,counted
+missed
);
1417 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1418 domain
,uLevel
,counted
,counted
+missed
));
1423 /****************************************************************************
1424 command 0x34 - suspected of being a "Lookup Names" stub api
1425 ****************************************************************************/
1426 static BOOL
api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1427 int mdrcnt
, int mprcnt
, char **rdata
,
1428 char **rparam
, int *rdata_len
, int *rparam_len
)
1430 char *str1
= param
+2;
1431 char *str2
= skip_string(str1
,1);
1432 char *p
= skip_string(str2
,1);
1433 int uLevel
= SVAL(p
,0);
1434 int buf_len
= SVAL(p
,2);
1438 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1439 str1
, str2
, p
, uLevel
, buf_len
));
1441 if (!prefix_ok(str1
,"zWrLeh")) return False
;
1446 *rparam
= REALLOC(*rparam
,*rparam_len
);
1448 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1450 SSVAL(*rparam
,4,counted
);
1451 SSVAL(*rparam
,6,counted
+missed
);
1456 /****************************************************************************
1457 get info about a share
1458 ****************************************************************************/
1459 static BOOL
check_share_info(int uLevel
, char* id
)
1463 if (strcmp(id
,"B13") != 0) return False
;
1466 if (strcmp(id
,"B13BWz") != 0) return False
;
1469 if (strcmp(id
,"B13BWzWWWzB9B") != 0) return False
;
1472 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False
;
1474 default: return False
;
1479 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1480 char** buf
, int* buflen
,
1481 char** stringbuf
, int* stringspace
, char* baseaddr
)
1490 case 0: struct_len
= 13; break;
1491 case 1: struct_len
= 20; break;
1492 case 2: struct_len
= 40; break;
1493 case 91: struct_len
= 68; break;
1501 if (uLevel
> 0) len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1502 if (uLevel
> 1) len
+= strlen(lp_pathname(snum
)) + 1;
1503 if (buflen
) *buflen
= struct_len
;
1504 if (stringspace
) *stringspace
= len
;
1505 return struct_len
+ len
;
1510 if ((*buflen
) < struct_len
) return -1;
1518 p2
= p
+ struct_len
;
1519 l2
= (*buflen
) - struct_len
;
1521 if (!baseaddr
) baseaddr
= p
;
1523 StrnCpy(p
,lp_servicename(snum
),13);
1529 type
= STYPE_DISKTREE
;
1530 if (lp_print_ok(snum
)) type
= STYPE_PRINTQ
;
1531 if (strequal("IPC$",lp_servicename(snum
))) type
= STYPE_IPC
;
1532 SSVAL(p
,14,type
); /* device type */
1533 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1534 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1539 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1540 SSVALS(p
,22,-1); /* max uses */
1541 SSVAL(p
,24,1); /* current uses */
1542 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1543 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1544 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1549 memset(p
+40,0,SHPWLEN
+2);
1561 (*buf
) = p
+ struct_len
;
1562 (*buflen
) -= struct_len
;
1564 (*stringspace
) = l2
;
1574 static BOOL
api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1575 int mdrcnt
,int mprcnt
,
1576 char **rdata
,char **rparam
,
1577 int *rdata_len
,int *rparam_len
)
1579 char *str1
= param
+2;
1580 char *str2
= skip_string(str1
,1);
1581 char *netname
= skip_string(str2
,1);
1582 char *p
= skip_string(netname
,1);
1583 int uLevel
= SVAL(p
,0);
1584 int snum
= find_service(netname
);
1586 if (snum
< 0) return False
;
1588 /* check it's a supported varient */
1589 if (!prefix_ok(str1
,"zWrLh")) return False
;
1590 if (!check_share_info(uLevel
,str2
)) return False
;
1592 *rdata
= REALLOC(*rdata
,mdrcnt
);
1594 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1595 if (*rdata_len
< 0) return False
;
1598 *rparam
= REALLOC(*rparam
,*rparam_len
);
1599 SSVAL(*rparam
,0,NERR_Success
);
1600 SSVAL(*rparam
,2,0); /* converter word */
1601 SSVAL(*rparam
,4,*rdata_len
);
1606 /****************************************************************************
1607 view list of shares available
1608 ****************************************************************************/
1609 static BOOL
api_RNetShareEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1610 int mdrcnt
,int mprcnt
,
1611 char **rdata
,char **rparam
,
1612 int *rdata_len
,int *rparam_len
)
1614 char *str1
= param
+2;
1615 char *str2
= skip_string(str1
,1);
1616 char *p
= skip_string(str2
,1);
1617 int uLevel
= SVAL(p
,0);
1618 int buf_len
= SVAL(p
,2);
1620 int count
=lp_numservices();
1621 int total
=0,counted
=0;
1622 BOOL missed
= False
;
1624 int data_len
, fixed_len
, string_len
;
1625 int f_len
= 0, s_len
= 0;
1627 if (!prefix_ok(str1
,"WrLeh")) return False
;
1628 if (!check_share_info(uLevel
,str2
)) return False
;
1630 data_len
= fixed_len
= string_len
= 0;
1631 for (i
=0;i
<count
;i
++)
1632 if (lp_browseable(i
) && lp_snum_ok(i
))
1635 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1636 if (data_len
<= buf_len
)
1640 string_len
+= s_len
;
1645 *rdata_len
= fixed_len
+ string_len
;
1646 *rdata
= REALLOC(*rdata
,*rdata_len
);
1647 memset(*rdata
,0,*rdata_len
);
1649 p2
= (*rdata
) + fixed_len
; /* auxillery data (strings) will go here */
1653 for (i
= 0; i
< count
;i
++)
1654 if (lp_browseable(i
) && lp_snum_ok(i
))
1655 if (fill_share_info(conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0)
1659 *rparam
= REALLOC(*rparam
,*rparam_len
);
1660 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1662 SSVAL(*rparam
,4,counted
);
1663 SSVAL(*rparam
,6,total
);
1665 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1666 counted
,total
,uLevel
,
1667 buf_len
,*rdata_len
,mdrcnt
));
1673 /****************************************************************************
1674 get the time of day info
1675 ****************************************************************************/
1676 static BOOL
api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1677 int mdrcnt
,int mprcnt
,
1678 char **rdata
,char **rparam
,
1679 int *rdata_len
,int *rparam_len
)
1683 *rparam
= REALLOC(*rparam
,*rparam_len
);
1686 *rdata
= REALLOC(*rdata
,*rdata_len
);
1688 SSVAL(*rparam
,0,NERR_Success
);
1689 SSVAL(*rparam
,2,0); /* converter word */
1695 time_t unixdate
= time(NULL
);
1697 put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
1698 by NT in a "net time" operation,
1699 it seems to ignore the one below */
1701 /* the client expects to get localtime, not GMT, in this bit
1702 (I think, this needs testing) */
1703 t
= LocalTime(&unixdate
);
1705 SIVAL(p
,4,0); /* msecs ? */
1706 SCVAL(p
,8,t
->tm_hour
);
1707 SCVAL(p
,9,t
->tm_min
);
1708 SCVAL(p
,10,t
->tm_sec
);
1709 SCVAL(p
,11,0); /* hundredths of seconds */
1710 SSVALS(p
,12,TimeDiff(unixdate
)/60); /* timezone in minutes from GMT */
1711 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
1712 SCVAL(p
,16,t
->tm_mday
);
1713 SCVAL(p
,17,t
->tm_mon
+ 1);
1714 SSVAL(p
,18,1900+t
->tm_year
);
1715 SCVAL(p
,20,t
->tm_wday
);
1722 /****************************************************************************
1723 Set the user password.
1724 *****************************************************************************/
1726 static BOOL
api_SetUserPassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1727 int mdrcnt
,int mprcnt
,
1728 char **rdata
,char **rparam
,
1729 int *rdata_len
,int *rparam_len
)
1731 char *p
= skip_string(param
+2,2);
1733 fstring pass1
,pass2
;
1737 p
= skip_string(p
,1);
1739 memset(pass1
,'\0',sizeof(pass1
));
1740 memset(pass2
,'\0',sizeof(pass2
));
1742 memcpy(pass2
,p
+16,16);
1745 *rparam
= REALLOC(*rparam
,*rparam_len
);
1749 SSVAL(*rparam
,0,NERR_badpass
);
1750 SSVAL(*rparam
,2,0); /* converter word */
1752 DEBUG(3,("Set password for <%s>\n",user
));
1755 * Pass the user through the NT -> unix user mapping
1759 (void)map_username(user
);
1762 * Do any UNIX username case mangling.
1764 (void)Get_Pwnam( user
, True
);
1767 * Attempt to verify the old password against smbpasswd entries
1768 * Win98 clients send old and new password in plaintext for this call.
1772 fstring saved_pass2
;
1773 SAM_ACCOUNT
*sampass
= NULL
;
1776 * Save the new password as change_oem_password overwrites it
1780 fstrcpy(saved_pass2
, pass2
);
1782 if (check_plaintext_password(user
,pass1
,strlen(pass1
),&sampass
) &&
1783 change_oem_password(sampass
,pass2
,False
))
1785 SSVAL(*rparam
,0,NERR_Success
);
1788 * If unix password sync was requested, attempt to change
1789 * the /etc/passwd database also. Return failure if this cannot
1793 if(lp_unix_password_sync() && !chgpasswd(user
,pass1
,saved_pass2
,False
))
1794 SSVAL(*rparam
,0,NERR_badpass
);
1798 pdb_free_sam(sampass
);
1802 * If the above failed, attempt the plaintext password change.
1803 * This tests against the /etc/passwd database only.
1806 if(SVAL(*rparam
,0) != NERR_Success
)
1808 if (password_ok(user
, pass1
,strlen(pass1
),NULL
) &&
1809 chgpasswd(user
,pass1
,pass2
,False
))
1811 SSVAL(*rparam
,0,NERR_Success
);
1816 * If the plaintext change failed, attempt
1817 * the old encrypted method. NT will generate this
1818 * after trying the samr method. Note that this
1819 * method is done as a last resort as this
1820 * password change method loses the NT password hash
1821 * and cannot change the UNIX password as no plaintext
1825 if(SVAL(*rparam
,0) != NERR_Success
)
1827 SAM_ACCOUNT
*sampass
= NULL
;
1829 if(check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &sampass
) &&
1830 change_lanman_password(sampass
,(unsigned char *)pass1
,(unsigned char *)pass2
))
1832 SSVAL(*rparam
,0,NERR_Success
);
1834 pdb_free_sam(sampass
);
1837 memset((char *)pass1
,'\0',sizeof(fstring
));
1838 memset((char *)pass2
,'\0',sizeof(fstring
));
1843 /****************************************************************************
1844 Set the user password (SamOEM version - gets plaintext).
1845 ****************************************************************************/
1847 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1848 int mdrcnt
,int mprcnt
,
1849 char **rdata
,char **rparam
,
1850 int *rdata_len
,int *rparam_len
)
1853 char *p
= param
+ 2;
1855 *rparam
= REALLOC(*rparam
,*rparam_len
);
1859 SSVAL(*rparam
,0,NERR_badpass
);
1862 * Check the parameter definition is correct.
1864 if(!strequal(param
+ 2, "zsT")) {
1865 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param
+ 2));
1868 p
= skip_string(p
, 1);
1870 if(!strequal(p
, "B516B16")) {
1871 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
1874 p
= skip_string(p
,1);
1877 p
= skip_string(p
,1);
1879 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
1882 * Pass the user through the NT -> unix user mapping
1886 (void)map_username(user
);
1889 * Do any UNIX username case mangling.
1891 (void)Get_Pwnam( user
, True
);
1893 if (pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
))
1895 SSVAL(*rparam
,0,NERR_Success
);
1901 /****************************************************************************
1904 ****************************************************************************/
1905 static BOOL
api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1906 int mdrcnt
,int mprcnt
,
1907 char **rdata
,char **rparam
,
1908 int *rdata_len
,int *rparam_len
)
1910 int function
= SVAL(param
,0);
1911 char *str1
= param
+2;
1912 char *str2
= skip_string(str1
,1);
1913 char *p
= skip_string(str2
,1);
1915 extern struct current_user current_user
;
1916 WERROR werr
= WERR_OK
;
1920 /* check it's a supported varient */
1921 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
1925 *rparam
= REALLOC(*rparam
,*rparam_len
);
1928 if (!print_job_exists(jobid
)) {
1929 errcode
= NERR_JobNotFound
;
1933 errcode
= NERR_notsupported
;
1936 case 81: /* delete */
1937 if (print_job_delete(¤t_user
, jobid
, &werr
))
1938 errcode
= NERR_Success
;
1940 case 82: /* pause */
1941 if (print_job_pause(¤t_user
, jobid
, &werr
))
1942 errcode
= NERR_Success
;
1944 case 83: /* resume */
1945 if (print_job_resume(¤t_user
, jobid
, &werr
))
1946 errcode
= NERR_Success
;
1950 if (!W_ERROR_IS_OK(werr
))
1951 errcode
= W_ERROR_V(werr
);
1954 SSVAL(*rparam
,0,errcode
);
1955 SSVAL(*rparam
,2,0); /* converter word */
1960 /****************************************************************************
1961 Purge a print queue - or pause or resume it.
1962 ****************************************************************************/
1963 static BOOL
api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1964 int mdrcnt
,int mprcnt
,
1965 char **rdata
,char **rparam
,
1966 int *rdata_len
,int *rparam_len
)
1968 int function
= SVAL(param
,0);
1969 char *str1
= param
+2;
1970 char *str2
= skip_string(str1
,1);
1971 char *QueueName
= skip_string(str2
,1);
1972 int errcode
= NERR_notsupported
;
1974 WERROR werr
= WERR_OK
;
1975 extern struct current_user current_user
;
1977 /* check it's a supported varient */
1978 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
1982 *rparam
= REALLOC(*rparam
,*rparam_len
);
1985 snum
= print_queue_snum(QueueName
);
1988 errcode
= NERR_JobNotFound
;
1993 case 74: /* Pause queue */
1994 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
1996 case 75: /* Resume queue */
1997 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
1999 case 103: /* Purge */
2000 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2004 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2006 SSVAL(*rparam
,0,errcode
);
2007 SSVAL(*rparam
,2,0); /* converter word */
2013 /****************************************************************************
2014 set the property of a print job (undocumented?)
2015 ? function = 0xb -> set name of print job
2016 ? function = 0x6 -> move print job up/down
2017 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2018 or <WWsTP> <WB21BB16B10zWWzDDz>
2019 ****************************************************************************/
2020 static int check_printjob_info(struct pack_desc
* desc
,
2021 int uLevel
, char* id
)
2023 desc
->subformat
= NULL
;
2025 case 0: desc
->format
= "W"; break;
2026 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2027 case 2: desc
->format
= "WWzWWDDzz"; break;
2028 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2029 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2030 default: return False
;
2032 if (strcmp(desc
->format
,id
) != 0) return False
;
2036 static BOOL
api_PrintJobInfo(connection_struct
*conn
,uint16 vuid
,char *param
,char *data
,
2037 int mdrcnt
,int mprcnt
,
2038 char **rdata
,char **rparam
,
2039 int *rdata_len
,int *rparam_len
)
2041 struct pack_desc desc
;
2042 char *str1
= param
+2;
2043 char *str2
= skip_string(str1
,1);
2044 char *p
= skip_string(str2
,1);
2046 int uLevel
= SVAL(p
,2);
2047 int function
= SVAL(p
,4);
2052 *rparam
= REALLOC(*rparam
,*rparam_len
);
2056 /* check it's a supported varient */
2057 if ((strcmp(str1
,"WWsTP")) ||
2058 (!check_printjob_info(&desc
,uLevel
,str2
)))
2061 if (!print_job_exists(jobid
)) {
2062 errcode
=NERR_JobNotFound
;
2066 errcode
= NERR_notsupported
;
2070 /* change job place in the queue,
2071 data gives the new place */
2072 place
= SVAL(data
,0);
2073 if (print_job_set_place(jobid
, place
)) {
2074 errcode
=NERR_Success
;
2079 /* change print job name, data gives the name */
2080 if (print_job_set_name(jobid
, data
)) {
2081 errcode
=NERR_Success
;
2090 SSVALS(*rparam
,0,errcode
);
2091 SSVAL(*rparam
,2,0); /* converter word */
2097 /****************************************************************************
2098 get info about the server
2099 ****************************************************************************/
2100 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2101 int mdrcnt
,int mprcnt
,
2102 char **rdata
,char **rparam
,
2103 int *rdata_len
,int *rparam_len
)
2105 char *str1
= param
+2;
2106 char *str2
= skip_string(str1
,1);
2107 char *p
= skip_string(str2
,1);
2108 int uLevel
= SVAL(p
,0);
2112 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2114 /* check it's a supported varient */
2115 if (!prefix_ok(str1
,"WrLh")) return False
;
2118 if (strcmp(str2
,"B16") != 0) return False
;
2122 if (strcmp(str2
,"B16BBDz") != 0) return False
;
2126 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2131 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2136 if (strcmp(str2
,"DN") != 0) return False
;
2140 if (strcmp(str2
,"B16BBDzWWzzz") != 0) return False
;
2143 default: return False
;
2146 *rdata_len
= mdrcnt
;
2147 *rdata
= REALLOC(*rdata
,*rdata_len
);
2150 p2
= p
+ struct_len
;
2152 StrnCpy(p
,local_machine
,16);
2158 struct srv_info_struct
*servers
=NULL
;
2161 uint32 servertype
= lp_default_server_announce();
2163 pstrcpy(comment
,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH
));
2165 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,global_myworkgroup
))>0) {
2166 for (i
=0;i
<count
;i
++)
2167 if (strequal(servers
[i
].name
,local_machine
))
2169 servertype
= servers
[i
].type
;
2170 pstrcpy(comment
,servers
[i
].comment
);
2175 SCVAL(p
,0,lp_major_announce_version());
2176 SCVAL(p
,1,lp_minor_announce_version());
2177 SIVAL(p
,2,servertype
);
2179 if (mdrcnt
== struct_len
) {
2182 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2183 standard_sub_conn(conn
,comment
,sizeof(comment
));
2184 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2185 p2
= skip_string(p2
,1);
2190 return False
; /* not yet implemented */
2193 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2196 *rparam
= REALLOC(*rparam
,*rparam_len
);
2197 SSVAL(*rparam
,0,NERR_Success
);
2198 SSVAL(*rparam
,2,0); /* converter word */
2199 SSVAL(*rparam
,4,*rdata_len
);
2205 /****************************************************************************
2206 get info about the server
2207 ****************************************************************************/
2208 static BOOL
api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2209 int mdrcnt
,int mprcnt
,
2210 char **rdata
,char **rparam
,
2211 int *rdata_len
,int *rparam_len
)
2213 char *str1
= param
+2;
2214 char *str2
= skip_string(str1
,1);
2215 char *p
= skip_string(str2
,1);
2217 extern userdom_struct current_user_info
;
2218 int level
= SVAL(p
,0);
2220 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2223 *rparam
= REALLOC(*rparam
,*rparam_len
);
2225 /* check it's a supported varient */
2226 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz")))
2229 *rdata_len
= mdrcnt
+ 1024;
2230 *rdata
= REALLOC(*rdata
,*rdata_len
);
2232 SSVAL(*rparam
,0,NERR_Success
);
2233 SSVAL(*rparam
,2,0); /* converter word */
2239 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2240 pstrcpy(p2
,local_machine
);
2242 p2
= skip_string(p2
,1);
2245 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2246 pstrcpy(p2
,current_user_info
.smb_name
);
2247 p2
= skip_string(p2
,1);
2250 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2251 pstrcpy(p2
,global_myworkgroup
);
2253 p2
= skip_string(p2
,1);
2256 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2257 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2260 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2261 pstrcpy(p2
,global_myworkgroup
); /* don't know. login domain?? */
2262 p2
= skip_string(p2
,1);
2265 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
2267 p2
= skip_string(p2
,1);
2270 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2272 SSVAL(*rparam
,4,*rdata_len
);
2277 /****************************************************************************
2278 get info about a user
2280 struct user_info_11 {
2281 char usri11_name[21]; 0-20
2283 char *usri11_comment; 22-25
2284 char *usri11_usr_comment; 26-29
2285 unsigned short usri11_priv; 30-31
2286 unsigned long usri11_auth_flags; 32-35
2287 long usri11_password_age; 36-39
2288 char *usri11_homedir; 40-43
2289 char *usri11_parms; 44-47
2290 long usri11_last_logon; 48-51
2291 long usri11_last_logoff; 52-55
2292 unsigned short usri11_bad_pw_count; 56-57
2293 unsigned short usri11_num_logons; 58-59
2294 char *usri11_logon_server; 60-63
2295 unsigned short usri11_country_code; 64-65
2296 char *usri11_workstations; 66-69
2297 unsigned long usri11_max_storage; 70-73
2298 unsigned short usri11_units_per_week; 74-75
2299 unsigned char *usri11_logon_hours; 76-79
2300 unsigned short usri11_code_page; 80-81
2305 usri11_name specifies the user name for which information is retireved
2307 usri11_pad aligns the next data structure element to a word boundary
2309 usri11_comment is a null terminated ASCII comment
2311 usri11_user_comment is a null terminated ASCII comment about the user
2313 usri11_priv specifies the level of the privilege assigned to the user.
2314 The possible values are:
2316 Name Value Description
2317 USER_PRIV_GUEST 0 Guest privilege
2318 USER_PRIV_USER 1 User privilege
2319 USER_PRV_ADMIN 2 Administrator privilege
2321 usri11_auth_flags specifies the account operator privileges. The
2322 possible values are:
2324 Name Value Description
2325 AF_OP_PRINT 0 Print operator
2328 Leach, Naik [Page 28]
2332 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2335 AF_OP_COMM 1 Communications operator
2336 AF_OP_SERVER 2 Server operator
2337 AF_OP_ACCOUNTS 3 Accounts operator
2340 usri11_password_age specifies how many seconds have elapsed since the
2341 password was last changed.
2343 usri11_home_dir points to a null terminated ASCII string that contains
2344 the path name of the user's home directory.
2346 usri11_parms points to a null terminated ASCII string that is set
2347 aside for use by applications.
2349 usri11_last_logon specifies the time when the user last logged on.
2350 This value is stored as the number of seconds elapsed since
2351 00:00:00, January 1, 1970.
2353 usri11_last_logoff specifies the time when the user last logged off.
2354 This value is stored as the number of seconds elapsed since
2355 00:00:00, January 1, 1970. A value of 0 means the last logoff
2358 usri11_bad_pw_count specifies the number of incorrect passwords
2359 entered since the last successful logon.
2361 usri11_log1_num_logons specifies the number of times this user has
2362 logged on. A value of -1 means the number of logons is unknown.
2364 usri11_logon_server points to a null terminated ASCII string that
2365 contains the name of the server to which logon requests are sent.
2366 A null string indicates logon requests should be sent to the
2369 usri11_country_code specifies the country code for the user's language
2372 usri11_workstations points to a null terminated ASCII string that
2373 contains the names of workstations the user may log on from.
2374 There may be up to 8 workstations, with the names separated by
2375 commas. A null strings indicates there are no restrictions.
2377 usri11_max_storage specifies the maximum amount of disk space the user
2378 can occupy. A value of 0xffffffff indicates there are no
2381 usri11_units_per_week specifies the equal number of time units into
2382 which a week is divided. This value must be equal to 168.
2384 usri11_logon_hours points to a 21 byte (168 bits) string that
2385 specifies the time during which the user can log on. Each bit
2386 represents one unique hour in a week. The first bit (bit 0, word
2387 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2391 Leach, Naik [Page 29]
2395 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2398 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2399 are no restrictions.
2401 usri11_code_page specifies the code page for the user's language of
2404 All of the pointers in this data structure need to be treated
2405 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2406 to be ignored. The converter word returned in the parameters section
2407 needs to be subtracted from the lower 16 bits to calculate an offset
2408 into the return buffer where this ASCII string resides.
2410 There is no auxiliary data in the response.
2412 ****************************************************************************/
2414 #define usri11_name 0
2415 #define usri11_pad 21
2416 #define usri11_comment 22
2417 #define usri11_usr_comment 26
2418 #define usri11_full_name 30
2419 #define usri11_priv 34
2420 #define usri11_auth_flags 36
2421 #define usri11_password_age 40
2422 #define usri11_homedir 44
2423 #define usri11_parms 48
2424 #define usri11_last_logon 52
2425 #define usri11_last_logoff 56
2426 #define usri11_bad_pw_count 60
2427 #define usri11_num_logons 62
2428 #define usri11_logon_server 64
2429 #define usri11_country_code 68
2430 #define usri11_workstations 70
2431 #define usri11_max_storage 74
2432 #define usri11_units_per_week 78
2433 #define usri11_logon_hours 80
2434 #define usri11_code_page 84
2435 #define usri11_end 86
2437 #define USER_PRIV_GUEST 0
2438 #define USER_PRIV_USER 1
2439 #define USER_PRIV_ADMIN 2
2441 #define AF_OP_PRINT 0
2442 #define AF_OP_COMM 1
2443 #define AF_OP_SERVER 2
2444 #define AF_OP_ACCOUNTS 3
2447 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2448 int mdrcnt
,int mprcnt
,
2449 char **rdata
,char **rparam
,
2450 int *rdata_len
,int *rparam_len
)
2452 char *str1
= param
+2;
2453 char *str2
= skip_string(str1
,1);
2454 char *UserName
= skip_string(str2
,1);
2455 char *p
= skip_string(UserName
,1);
2456 int uLevel
= SVAL(p
,0);
2459 /* get NIS home of a previously validated user - simeon */
2460 /* With share level security vuid will always be zero.
2461 Don't depend on vuser being non-null !!. JRA */
2462 user_struct
*vuser
= get_valid_user_struct(vuid
);
2464 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
2465 vuser
->user
.unix_name
));
2468 *rparam
= REALLOC(*rparam
,*rparam_len
);
2470 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
2472 /* check it's a supported variant */
2473 if (strcmp(str1
,"zWrLh") != 0) return False
;
2476 case 0: p2
= "B21"; break;
2477 case 1: p2
= "B21BB16DWzzWz"; break;
2478 case 2: p2
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2479 case 10: p2
= "B21Bzzz"; break;
2480 case 11: p2
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2481 default: return False
;
2484 if (strcmp(p2
,str2
) != 0) return False
;
2486 *rdata_len
= mdrcnt
+ 1024;
2487 *rdata
= REALLOC(*rdata
,*rdata_len
);
2489 SSVAL(*rparam
,0,NERR_Success
);
2490 SSVAL(*rparam
,2,0); /* converter word */
2493 p2
= p
+ usri11_end
;
2496 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
2500 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
2505 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
2506 pstrcpy(p2
,"Comment");
2507 p2
= skip_string(p2
,1);
2509 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
2510 pstrcpy(p2
,"UserComment");
2511 p2
= skip_string(p2
,1);
2513 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2514 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
2515 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2516 p2
= skip_string(p2
,1);
2519 if (uLevel
== 11) /* modelled after NTAS 3.51 reply */
2521 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2522 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
2523 SIVALS(p
,usri11_password_age
,-1); /* password age */
2524 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
2525 pstrcpy(p2
, lp_logon_home());
2526 standard_sub_conn(conn
, p2
,*rdata_len
-(p2
- *rdata
));
2527 p2
= skip_string(p2
,1);
2528 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
2530 p2
= skip_string(p2
,1);
2531 SIVAL(p
,usri11_last_logon
,0); /* last logon */
2532 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
2533 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
2534 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
2535 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
2536 pstrcpy(p2
,"\\\\*");
2537 p2
= skip_string(p2
,1);
2538 SSVAL(p
,usri11_country_code
,0); /* country code */
2540 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
2542 p2
= skip_string(p2
,1);
2544 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
2545 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
2546 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
2548 /* a simple way to get logon hours at all times. */
2550 SCVAL(p2
,21,0); /* fix zero termination */
2551 p2
= skip_string(p2
,1);
2553 SSVAL(p
,usri11_code_page
,0); /* code page */
2555 if (uLevel
== 1 || uLevel
== 2)
2557 memset(p
+22,' ',16); /* password */
2558 SIVALS(p
,38,-1); /* password age */
2560 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2561 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
2562 pstrcpy(p2
,lp_logon_home());
2563 standard_sub_conn(conn
, p2
,*rdata_len
-(p2
- *rdata
));
2564 p2
= skip_string(p2
,1);
2565 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
2567 SSVAL(p
,52,0); /* flags */
2568 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
2569 pstrcpy(p2
,lp_logon_script());
2570 standard_sub_conn( conn
, p2
,*rdata_len
-(p2
- *rdata
));
2571 p2
= skip_string(p2
,1);
2574 SIVAL(p
,60,0); /* auth_flags */
2575 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
2576 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2577 p2
= skip_string(p2
,1);
2578 SIVAL(p
,68,0); /* urs_comment */
2579 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
2581 p2
= skip_string(p2
,1);
2582 SIVAL(p
,76,0); /* workstations */
2583 SIVAL(p
,80,0); /* last_logon */
2584 SIVAL(p
,84,0); /* last_logoff */
2585 SIVALS(p
,88,-1); /* acct_expires */
2586 SIVALS(p
,92,-1); /* max_storage */
2587 SSVAL(p
,96,168); /* units_per_week */
2588 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
2591 SSVALS(p
,102,-1); /* bad_pw_count */
2592 SSVALS(p
,104,-1); /* num_logons */
2593 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
2594 pstrcpy(p2
,"\\\\%L");
2595 standard_sub_conn(conn
, p2
,*rdata_len
-(p2
- *rdata
));
2596 p2
= skip_string(p2
,1);
2597 SSVAL(p
,110,49); /* country_code */
2598 SSVAL(p
,112,860); /* code page */
2602 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2604 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
2609 /*******************************************************************
2610 get groups that a user is a member of
2611 ******************************************************************/
2612 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2613 int mdrcnt
,int mprcnt
,
2614 char **rdata
,char **rparam
,
2615 int *rdata_len
,int *rparam_len
)
2617 char *str1
= param
+2;
2618 char *str2
= skip_string(str1
,1);
2619 char *UserName
= skip_string(str2
,1);
2620 char *p
= skip_string(UserName
,1);
2621 int uLevel
= SVAL(p
,0);
2626 *rparam
= REALLOC(*rparam
,*rparam_len
);
2628 /* check it's a supported varient */
2629 if (strcmp(str1
,"zWrLeh") != 0) return False
;
2631 case 0: p2
= "B21"; break;
2632 default: return False
;
2634 if (strcmp(p2
,str2
) != 0) return False
;
2636 *rdata_len
= mdrcnt
+ 1024;
2637 *rdata
= REALLOC(*rdata
,*rdata_len
);
2639 SSVAL(*rparam
,0,NERR_Success
);
2640 SSVAL(*rparam
,2,0); /* converter word */
2644 /* XXXX we need a real SAM database some day */
2645 pstrcpy(p
,"Users"); p
+= 21; count
++;
2646 pstrcpy(p
,"Domain Users"); p
+= 21; count
++;
2647 pstrcpy(p
,"Guests"); p
+= 21; count
++;
2648 pstrcpy(p
,"Domain Guests"); p
+= 21; count
++;
2650 *rdata_len
= PTR_DIFF(p
,*rdata
);
2652 SSVAL(*rparam
,4,count
); /* is this right?? */
2653 SSVAL(*rparam
,6,count
); /* is this right?? */
2659 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2660 int mdrcnt
,int mprcnt
,
2661 char **rdata
,char **rparam
,
2662 int *rdata_len
,int *rparam_len
)
2664 char *str1
= param
+2;
2665 char *str2
= skip_string(str1
,1);
2666 char *p
= skip_string(str2
,1);
2668 struct pack_desc desc
;
2674 memset((char *)&desc
,'\0',sizeof(desc
));
2676 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
2678 /* check it's a supported varient */
2679 if (strcmp(str1
,"OOWb54WrLh") != 0) return False
;
2680 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) return False
;
2681 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2683 desc
.buflen
= mdrcnt
;
2684 desc
.subformat
= NULL
;
2687 if (init_package(&desc
,1,0))
2689 PACKI(&desc
,"W",0); /* code */
2690 PACKS(&desc
,"B21",name
); /* eff. name */
2691 PACKS(&desc
,"B",""); /* pad */
2693 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2694 PACKI(&desc
,"D",0); /* auth flags XXX */
2695 PACKI(&desc
,"W",0); /* num logons */
2696 PACKI(&desc
,"W",0); /* bad pw count */
2697 PACKI(&desc
,"D",0); /* last logon */
2698 PACKI(&desc
,"D",-1); /* last logoff */
2699 PACKI(&desc
,"D",-1); /* logoff time */
2700 PACKI(&desc
,"D",-1); /* kickoff time */
2701 PACKI(&desc
,"D",0); /* password age */
2702 PACKI(&desc
,"D",0); /* password can change */
2703 PACKI(&desc
,"D",-1); /* password must change */
2706 fstrcpy(mypath
,"\\\\");
2707 fstrcat(mypath
,local_machine
);
2709 PACKS(&desc
,"z",mypath
); /* computer */
2711 PACKS(&desc
,"z",global_myworkgroup
);/* domain */
2713 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2714 /* made sure all macros are fully substituted and available */
2716 pstring logon_script
;
2717 pstrcpy(logon_script
,lp_logon_script());
2718 standard_sub_conn( conn
, logon_script
,sizeof(logon_script
) );
2719 PACKS(&desc
,"z", logon_script
); /* script path */
2721 /* End of JHT mods */
2723 PACKI(&desc
,"D",0x00000000); /* reserved */
2726 *rdata_len
= desc
.usedlen
;
2728 *rparam
= REALLOC(*rparam
,*rparam_len
);
2729 SSVALS(*rparam
,0,desc
.errcode
);
2731 SSVAL(*rparam
,4,desc
.neededlen
);
2733 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
2738 /****************************************************************************
2739 api_WAccessGetUserPerms
2740 ****************************************************************************/
2741 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2742 int mdrcnt
,int mprcnt
,
2743 char **rdata
,char **rparam
,
2744 int *rdata_len
,int *rparam_len
)
2746 char *str1
= param
+2;
2747 char *str2
= skip_string(str1
,1);
2748 char *user
= skip_string(str2
,1);
2749 char *resource
= skip_string(user
,1);
2751 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
2753 /* check it's a supported varient */
2754 if (strcmp(str1
,"zzh") != 0) return False
;
2755 if (strcmp(str2
,"") != 0) return False
;
2758 *rparam
= REALLOC(*rparam
,*rparam_len
);
2759 SSVALS(*rparam
,0,0); /* errorcode */
2760 SSVAL(*rparam
,2,0); /* converter word */
2761 SSVAL(*rparam
,4,0x7f); /* permission flags */
2766 /****************************************************************************
2767 api_WPrintJobEnumerate
2768 ****************************************************************************/
2769 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2770 int mdrcnt
,int mprcnt
,
2771 char **rdata
,char **rparam
,
2772 int *rdata_len
,int *rparam_len
)
2774 char *str1
= param
+2;
2775 char *str2
= skip_string(str1
,1);
2776 char *p
= skip_string(str2
,1);
2782 struct pack_desc desc
;
2783 print_queue_struct
*queue
=NULL
;
2784 print_status_struct status
;
2789 memset((char *)&desc
,'\0',sizeof(desc
));
2790 memset((char *)&status
,'\0',sizeof(status
));
2792 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
2794 /* check it's a supported varient */
2795 if (strcmp(str1
,"WWrLh") != 0) return False
;
2796 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2799 snum
= print_job_snum(job
);
2801 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2803 count
= print_queue_status(snum
,&queue
,&status
);
2804 for (i
= 0; i
< count
; i
++) {
2805 if (queue
[i
].job
== job
) break;
2809 *rdata
= REALLOC(*rdata
,mdrcnt
);
2811 desc
.buflen
= mdrcnt
;
2814 * Don't return data but need to get correct length
2815 * init_package will return wrong size if buflen=0
2817 desc
.buflen
= getlen(desc
.format
);
2818 desc
.base
= tmpdata
= (char *)malloc ( desc
.buflen
);
2821 if (init_package(&desc
,1,0)) {
2823 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
2824 *rdata_len
= desc
.usedlen
;
2827 desc
.errcode
= NERR_JobNotFound
;
2833 *rparam
= REALLOC(*rparam
,*rparam_len
);
2834 SSVALS(*rparam
,0,desc
.errcode
);
2836 SSVAL(*rparam
,4,desc
.neededlen
);
2841 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
2845 static BOOL
api_WPrintJobEnumerate(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 *p
= skip_string(str2
,1);
2858 struct pack_desc desc
;
2859 print_queue_struct
*queue
=NULL
;
2860 print_status_struct status
;
2862 memset((char *)&desc
,'\0',sizeof(desc
));
2863 memset((char *)&status
,'\0',sizeof(status
));
2865 p
= skip_string(p
,1);
2868 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
2870 /* check it's a supported varient */
2871 if (strcmp(str1
,"zWrLeh") != 0) return False
;
2872 if (uLevel
> 2) return False
; /* defined only for uLevel 0,1,2 */
2873 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2875 snum
= lp_servicenumber(name
);
2876 if (snum
< 0 && pcap_printername_ok(name
,NULL
)) {
2877 int pnum
= lp_servicenumber(PRINTERS_NAME
);
2879 lp_add_printer(name
,pnum
);
2880 snum
= lp_servicenumber(name
);
2884 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2886 count
= print_queue_status(snum
,&queue
,&status
);
2887 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2889 desc
.buflen
= mdrcnt
;
2891 if (init_package(&desc
,count
,0)) {
2893 for (i
= 0; i
< count
; i
++) {
2894 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
2895 if (desc
.errcode
== NERR_Success
) succnt
= i
+1;
2899 *rdata_len
= desc
.usedlen
;
2902 *rparam
= REALLOC(*rparam
,*rparam_len
);
2903 SSVALS(*rparam
,0,desc
.errcode
);
2905 SSVAL(*rparam
,4,succnt
);
2906 SSVAL(*rparam
,6,count
);
2910 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
2914 static int check_printdest_info(struct pack_desc
* desc
,
2915 int uLevel
, char* id
)
2917 desc
->subformat
= NULL
;
2919 case 0: desc
->format
= "B9"; break;
2920 case 1: desc
->format
= "B9B21WWzW"; break;
2921 case 2: desc
->format
= "z"; break;
2922 case 3: desc
->format
= "zzzWWzzzWW"; break;
2923 default: return False
;
2925 if (strcmp(desc
->format
,id
) != 0) return False
;
2929 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
2930 struct pack_desc
* desc
)
2933 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
2934 buf
[sizeof(buf
)-1] = 0;
2937 PACKS(desc
,"B9",buf
); /* szName */
2939 PACKS(desc
,"B21",""); /* szUserName */
2940 PACKI(desc
,"W",0); /* uJobId */
2941 PACKI(desc
,"W",0); /* fsStatus */
2942 PACKS(desc
,"z",""); /* pszStatus */
2943 PACKI(desc
,"W",0); /* time */
2946 if (uLevel
== 2 || uLevel
== 3) {
2947 PACKS(desc
,"z",buf
); /* pszPrinterName */
2949 PACKS(desc
,"z",""); /* pszUserName */
2950 PACKS(desc
,"z",""); /* pszLogAddr */
2951 PACKI(desc
,"W",0); /* uJobId */
2952 PACKI(desc
,"W",0); /* fsStatus */
2953 PACKS(desc
,"z",""); /* pszStatus */
2954 PACKS(desc
,"z",""); /* pszComment */
2955 PACKS(desc
,"z","NULL"); /* pszDrivers */
2956 PACKI(desc
,"W",0); /* time */
2957 PACKI(desc
,"W",0); /* pad1 */
2962 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2963 int mdrcnt
,int mprcnt
,
2964 char **rdata
,char **rparam
,
2965 int *rdata_len
,int *rparam_len
)
2967 char *str1
= param
+2;
2968 char *str2
= skip_string(str1
,1);
2969 char *p
= skip_string(str2
,1);
2970 char* PrinterName
= p
;
2972 struct pack_desc desc
;
2976 memset((char *)&desc
,'\0',sizeof(desc
));
2978 p
= skip_string(p
,1);
2981 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
2983 /* check it's a supported varient */
2984 if (strcmp(str1
,"zWrLh") != 0) return False
;
2985 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
2987 snum
= lp_servicenumber(PrinterName
);
2988 if (snum
< 0 && pcap_printername_ok(PrinterName
,NULL
)) {
2989 int pnum
= lp_servicenumber(PRINTERS_NAME
);
2991 lp_add_printer(PrinterName
,pnum
);
2992 snum
= lp_servicenumber(PrinterName
);
2998 desc
.errcode
= NERR_DestNotFound
;
3003 *rdata
= REALLOC(*rdata
,mdrcnt
);
3005 desc
.buflen
= mdrcnt
;
3008 * Don't return data but need to get correct length
3009 * init_package will return wrong size if buflen=0
3011 desc
.buflen
= getlen(desc
.format
);
3012 desc
.base
= tmpdata
= (char *)malloc ( desc
.buflen
);
3014 if (init_package(&desc
,1,0)) {
3015 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
3017 *rdata_len
= desc
.usedlen
;
3021 *rparam
= REALLOC(*rparam
,*rparam_len
);
3022 SSVALS(*rparam
,0,desc
.errcode
);
3024 SSVAL(*rparam
,4,desc
.neededlen
);
3026 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3031 static BOOL
api_WPrintDestEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3032 int mdrcnt
,int mprcnt
,
3033 char **rdata
,char **rparam
,
3034 int *rdata_len
,int *rparam_len
)
3036 char *str1
= param
+2;
3037 char *str2
= skip_string(str1
,1);
3038 char *p
= skip_string(str2
,1);
3042 struct pack_desc desc
;
3043 int services
= lp_numservices();
3045 memset((char *)&desc
,'\0',sizeof(desc
));
3049 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3051 /* check it's a supported varient */
3052 if (strcmp(str1
,"WrLeh") != 0) return False
;
3053 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3056 for (i
= 0; i
< services
; i
++)
3057 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
3060 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3062 desc
.buflen
= mdrcnt
;
3063 if (init_package(&desc
,queuecnt
,0)) {
3066 for (i
= 0; i
< services
; i
++) {
3067 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3068 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3070 if (desc
.errcode
== NERR_Success
) succnt
= n
;
3075 *rdata_len
= desc
.usedlen
;
3078 *rparam
= REALLOC(*rparam
,*rparam_len
);
3079 SSVALS(*rparam
,0,desc
.errcode
);
3081 SSVAL(*rparam
,4,succnt
);
3082 SSVAL(*rparam
,6,queuecnt
);
3084 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3088 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3089 int mdrcnt
,int mprcnt
,
3090 char **rdata
,char **rparam
,
3091 int *rdata_len
,int *rparam_len
)
3093 char *str1
= param
+2;
3094 char *str2
= skip_string(str1
,1);
3095 char *p
= skip_string(str2
,1);
3098 struct pack_desc desc
;
3100 memset((char *)&desc
,'\0',sizeof(desc
));
3104 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
3106 /* check it's a supported varient */
3107 if (strcmp(str1
,"WrLeh") != 0) return False
;
3108 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) return False
;
3110 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3112 desc
.buflen
= mdrcnt
;
3113 if (init_package(&desc
,1,0)) {
3114 PACKS(&desc
,"B41","NULL");
3117 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3119 *rdata_len
= desc
.usedlen
;
3122 *rparam
= REALLOC(*rparam
,*rparam_len
);
3123 SSVALS(*rparam
,0,desc
.errcode
);
3125 SSVAL(*rparam
,4,succnt
);
3128 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
3132 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3133 int mdrcnt
,int mprcnt
,
3134 char **rdata
,char **rparam
,
3135 int *rdata_len
,int *rparam_len
)
3137 char *str1
= param
+2;
3138 char *str2
= skip_string(str1
,1);
3139 char *p
= skip_string(str2
,1);
3142 struct pack_desc desc
;
3144 memset((char *)&desc
,'\0',sizeof(desc
));
3148 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
3150 /* check it's a supported varient */
3151 if (strcmp(str1
,"WrLeh") != 0) return False
;
3152 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) return False
;
3154 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3156 desc
.buflen
= mdrcnt
;
3158 if (init_package(&desc
,1,0)) {
3159 PACKS(&desc
,"B13","lpd");
3162 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3164 *rdata_len
= desc
.usedlen
;
3167 *rparam
= REALLOC(*rparam
,*rparam_len
);
3168 SSVALS(*rparam
,0,desc
.errcode
);
3170 SSVAL(*rparam
,4,succnt
);
3173 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
3177 static BOOL
api_WPrintPortEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3178 int mdrcnt
,int mprcnt
,
3179 char **rdata
,char **rparam
,
3180 int *rdata_len
,int *rparam_len
)
3182 char *str1
= param
+2;
3183 char *str2
= skip_string(str1
,1);
3184 char *p
= skip_string(str2
,1);
3187 struct pack_desc desc
;
3189 memset((char *)&desc
,'\0',sizeof(desc
));
3193 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
3195 /* check it's a supported varient */
3196 if (strcmp(str1
,"WrLeh") != 0) return False
;
3197 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) return False
;
3199 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3200 memset((char *)&desc
,'\0',sizeof(desc
));
3202 desc
.buflen
= mdrcnt
;
3204 if (init_package(&desc
,1,0)) {
3205 PACKS(&desc
,"B13","lp0");
3208 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3210 *rdata_len
= desc
.usedlen
;
3213 *rparam
= REALLOC(*rparam
,*rparam_len
);
3214 SSVALS(*rparam
,0,desc
.errcode
);
3216 SSVAL(*rparam
,4,succnt
);
3219 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
3223 /****************************************************************************
3224 The buffer was too small
3225 ****************************************************************************/
3227 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3228 int mdrcnt
,int mprcnt
,
3229 char **rdata
,char **rparam
,
3230 int *rdata_len
,int *rparam_len
)
3232 *rparam_len
= MIN(*rparam_len
,mprcnt
);
3233 *rparam
= REALLOC(*rparam
,*rparam_len
);
3237 SSVAL(*rparam
,0,NERR_BufTooSmall
);
3239 DEBUG(3,("Supplied buffer too small in API command\n"));
3245 /****************************************************************************
3246 The request is not supported
3247 ****************************************************************************/
3249 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3250 int mdrcnt
,int mprcnt
,
3251 char **rdata
,char **rparam
,
3252 int *rdata_len
,int *rparam_len
)
3255 *rparam
= REALLOC(*rparam
,*rparam_len
);
3259 SSVAL(*rparam
,0,NERR_notsupported
);
3260 SSVAL(*rparam
,2,0); /* converter word */
3262 DEBUG(3,("Unsupported API command\n"));
3274 BOOL (*fn
)(connection_struct
*,uint16
,char *,char *,
3275 int,int,char **,char **,int *,int *);
3277 } api_commands
[] = {
3278 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
,0},
3279 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
,0},
3280 #if 0 /* Not yet implemented. */
3281 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
,0},
3283 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
,0},
3284 #if 0 /* Not yet implemented. */
3285 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
,0},
3287 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
,0},
3288 #if 0 /* Not yet implemented. */
3289 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
,0},
3291 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
,0},
3292 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
,0},
3293 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
,0},
3294 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
,0},
3295 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
,0},
3296 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
,0},
3297 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
,0},
3298 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
,0},
3299 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
,0},
3300 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
,0},
3301 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
,0},
3302 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
,0},
3303 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
,0},
3304 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
,0},
3305 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
,0},
3306 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
,0},
3307 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
,0},
3308 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
,0},
3309 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
,0},
3310 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
,0},
3311 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
,0},
3312 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
,0},
3313 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
,0},
3314 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
,0},
3315 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
,0},
3316 {NULL
, -1, api_Unsupported
,0}};
3319 /****************************************************************************
3320 Handle remote api calls
3321 ****************************************************************************/
3323 int api_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,char *data
,char *params
,
3324 int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
3328 char *rparam
= NULL
;
3335 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3339 api_command
= SVAL(params
,0);
3341 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3344 skip_string(params
+2,1),
3345 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
3347 for (i
=0;api_commands
[i
].name
;i
++) {
3348 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
3349 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
3354 rdata
= (char *)malloc(1024);
3356 memset(rdata
,'\0',1024);
3358 rparam
= (char *)malloc(1024);
3360 memset(rparam
,'\0',1024);
3362 if(!rdata
|| !rparam
) {
3363 DEBUG(0,("api_reply: malloc fail !\n"));
3367 reply
= api_commands
[i
].fn(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3368 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3371 if (rdata_len
> mdrcnt
||
3372 rparam_len
> mprcnt
) {
3373 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3374 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3377 /* if we get False back then it's actually unsupported */
3379 api_Unsupported(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3380 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3382 send_trans_reply(outbuf
, rparam
, rparam_len
, rdata
, rdata_len
, False
);