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
);
1797 pdb_free_sam(sampass
);
1801 * If the above failed, attempt the plaintext password change.
1802 * This tests against the /etc/passwd database only.
1805 if(SVAL(*rparam
,0) != NERR_Success
)
1807 if (password_ok(user
, pass1
,strlen(pass1
),NULL
) &&
1808 chgpasswd(user
,pass1
,pass2
,False
))
1810 SSVAL(*rparam
,0,NERR_Success
);
1815 * If the plaintext change failed, attempt
1816 * the old encrypted method. NT will generate this
1817 * after trying the samr method. Note that this
1818 * method is done as a last resort as this
1819 * password change method loses the NT password hash
1820 * and cannot change the UNIX password as no plaintext
1824 if(SVAL(*rparam
,0) != NERR_Success
)
1826 SAM_ACCOUNT
*sampass
= NULL
;
1828 if(check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &sampass
) &&
1829 change_lanman_password(sampass
,(unsigned char *)pass1
,(unsigned char *)pass2
))
1831 SSVAL(*rparam
,0,NERR_Success
);
1833 pdb_free_sam(sampass
);
1836 memset((char *)pass1
,'\0',sizeof(fstring
));
1837 memset((char *)pass2
,'\0',sizeof(fstring
));
1842 /****************************************************************************
1843 Set the user password (SamOEM version - gets plaintext).
1844 ****************************************************************************/
1846 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1847 int mdrcnt
,int mprcnt
,
1848 char **rdata
,char **rparam
,
1849 int *rdata_len
,int *rparam_len
)
1852 char *p
= param
+ 2;
1854 *rparam
= REALLOC(*rparam
,*rparam_len
);
1858 SSVAL(*rparam
,0,NERR_badpass
);
1861 * Check the parameter definition is correct.
1863 if(!strequal(param
+ 2, "zsT")) {
1864 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param
+ 2));
1867 p
= skip_string(p
, 1);
1869 if(!strequal(p
, "B516B16")) {
1870 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
1873 p
= skip_string(p
,1);
1876 p
= skip_string(p
,1);
1878 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
1881 * Pass the user through the NT -> unix user mapping
1885 (void)map_username(user
);
1888 * Do any UNIX username case mangling.
1890 (void)Get_Pwnam( user
, True
);
1892 if (pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
))
1894 SSVAL(*rparam
,0,NERR_Success
);
1900 /****************************************************************************
1903 ****************************************************************************/
1904 static BOOL
api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1905 int mdrcnt
,int mprcnt
,
1906 char **rdata
,char **rparam
,
1907 int *rdata_len
,int *rparam_len
)
1909 int function
= SVAL(param
,0);
1910 char *str1
= param
+2;
1911 char *str2
= skip_string(str1
,1);
1912 char *p
= skip_string(str2
,1);
1914 extern struct current_user current_user
;
1915 WERROR werr
= WERR_OK
;
1919 /* check it's a supported varient */
1920 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
1924 *rparam
= REALLOC(*rparam
,*rparam_len
);
1927 if (!print_job_exists(jobid
)) {
1928 errcode
= NERR_JobNotFound
;
1932 errcode
= NERR_notsupported
;
1935 case 81: /* delete */
1936 if (print_job_delete(¤t_user
, jobid
, &werr
))
1937 errcode
= NERR_Success
;
1939 case 82: /* pause */
1940 if (print_job_pause(¤t_user
, jobid
, &werr
))
1941 errcode
= NERR_Success
;
1943 case 83: /* resume */
1944 if (print_job_resume(¤t_user
, jobid
, &werr
))
1945 errcode
= NERR_Success
;
1949 if (!W_ERROR_IS_OK(werr
))
1950 errcode
= W_ERROR_V(werr
);
1953 SSVAL(*rparam
,0,errcode
);
1954 SSVAL(*rparam
,2,0); /* converter word */
1959 /****************************************************************************
1960 Purge a print queue - or pause or resume it.
1961 ****************************************************************************/
1962 static BOOL
api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1963 int mdrcnt
,int mprcnt
,
1964 char **rdata
,char **rparam
,
1965 int *rdata_len
,int *rparam_len
)
1967 int function
= SVAL(param
,0);
1968 char *str1
= param
+2;
1969 char *str2
= skip_string(str1
,1);
1970 char *QueueName
= skip_string(str2
,1);
1971 int errcode
= NERR_notsupported
;
1973 WERROR werr
= WERR_OK
;
1974 extern struct current_user current_user
;
1976 /* check it's a supported varient */
1977 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
1981 *rparam
= REALLOC(*rparam
,*rparam_len
);
1984 snum
= print_queue_snum(QueueName
);
1987 errcode
= NERR_JobNotFound
;
1992 case 74: /* Pause queue */
1993 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
1995 case 75: /* Resume queue */
1996 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
1998 case 103: /* Purge */
1999 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2003 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2005 SSVAL(*rparam
,0,errcode
);
2006 SSVAL(*rparam
,2,0); /* converter word */
2012 /****************************************************************************
2013 set the property of a print job (undocumented?)
2014 ? function = 0xb -> set name of print job
2015 ? function = 0x6 -> move print job up/down
2016 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2017 or <WWsTP> <WB21BB16B10zWWzDDz>
2018 ****************************************************************************/
2019 static int check_printjob_info(struct pack_desc
* desc
,
2020 int uLevel
, char* id
)
2022 desc
->subformat
= NULL
;
2024 case 0: desc
->format
= "W"; break;
2025 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2026 case 2: desc
->format
= "WWzWWDDzz"; break;
2027 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2028 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2029 default: return False
;
2031 if (strcmp(desc
->format
,id
) != 0) return False
;
2035 static BOOL
api_PrintJobInfo(connection_struct
*conn
,uint16 vuid
,char *param
,char *data
,
2036 int mdrcnt
,int mprcnt
,
2037 char **rdata
,char **rparam
,
2038 int *rdata_len
,int *rparam_len
)
2040 struct pack_desc desc
;
2041 char *str1
= param
+2;
2042 char *str2
= skip_string(str1
,1);
2043 char *p
= skip_string(str2
,1);
2045 int uLevel
= SVAL(p
,2);
2046 int function
= SVAL(p
,4);
2051 *rparam
= REALLOC(*rparam
,*rparam_len
);
2055 /* check it's a supported varient */
2056 if ((strcmp(str1
,"WWsTP")) ||
2057 (!check_printjob_info(&desc
,uLevel
,str2
)))
2060 if (!print_job_exists(jobid
)) {
2061 errcode
=NERR_JobNotFound
;
2065 errcode
= NERR_notsupported
;
2069 /* change job place in the queue,
2070 data gives the new place */
2071 place
= SVAL(data
,0);
2072 if (print_job_set_place(jobid
, place
)) {
2073 errcode
=NERR_Success
;
2078 /* change print job name, data gives the name */
2079 if (print_job_set_name(jobid
, data
)) {
2080 errcode
=NERR_Success
;
2089 SSVALS(*rparam
,0,errcode
);
2090 SSVAL(*rparam
,2,0); /* converter word */
2096 /****************************************************************************
2097 get info about the server
2098 ****************************************************************************/
2099 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2100 int mdrcnt
,int mprcnt
,
2101 char **rdata
,char **rparam
,
2102 int *rdata_len
,int *rparam_len
)
2104 char *str1
= param
+2;
2105 char *str2
= skip_string(str1
,1);
2106 char *p
= skip_string(str2
,1);
2107 int uLevel
= SVAL(p
,0);
2111 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2113 /* check it's a supported varient */
2114 if (!prefix_ok(str1
,"WrLh")) return False
;
2117 if (strcmp(str2
,"B16") != 0) return False
;
2121 if (strcmp(str2
,"B16BBDz") != 0) return False
;
2125 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2130 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2135 if (strcmp(str2
,"DN") != 0) return False
;
2139 if (strcmp(str2
,"B16BBDzWWzzz") != 0) return False
;
2142 default: return False
;
2145 *rdata_len
= mdrcnt
;
2146 *rdata
= REALLOC(*rdata
,*rdata_len
);
2149 p2
= p
+ struct_len
;
2151 StrnCpy(p
,local_machine
,16);
2157 struct srv_info_struct
*servers
=NULL
;
2160 uint32 servertype
= lp_default_server_announce();
2162 pstrcpy(comment
,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH
));
2164 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,global_myworkgroup
))>0) {
2165 for (i
=0;i
<count
;i
++)
2166 if (strequal(servers
[i
].name
,local_machine
))
2168 servertype
= servers
[i
].type
;
2169 pstrcpy(comment
,servers
[i
].comment
);
2174 SCVAL(p
,0,lp_major_announce_version());
2175 SCVAL(p
,1,lp_minor_announce_version());
2176 SIVAL(p
,2,servertype
);
2178 if (mdrcnt
== struct_len
) {
2181 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2182 standard_sub_conn(conn
,comment
,sizeof(comment
));
2183 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2184 p2
= skip_string(p2
,1);
2189 return False
; /* not yet implemented */
2192 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2195 *rparam
= REALLOC(*rparam
,*rparam_len
);
2196 SSVAL(*rparam
,0,NERR_Success
);
2197 SSVAL(*rparam
,2,0); /* converter word */
2198 SSVAL(*rparam
,4,*rdata_len
);
2204 /****************************************************************************
2205 get info about the server
2206 ****************************************************************************/
2207 static BOOL
api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2208 int mdrcnt
,int mprcnt
,
2209 char **rdata
,char **rparam
,
2210 int *rdata_len
,int *rparam_len
)
2212 char *str1
= param
+2;
2213 char *str2
= skip_string(str1
,1);
2214 char *p
= skip_string(str2
,1);
2216 extern userdom_struct current_user_info
;
2217 int level
= SVAL(p
,0);
2219 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2222 *rparam
= REALLOC(*rparam
,*rparam_len
);
2224 /* check it's a supported varient */
2225 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz")))
2228 *rdata_len
= mdrcnt
+ 1024;
2229 *rdata
= REALLOC(*rdata
,*rdata_len
);
2231 SSVAL(*rparam
,0,NERR_Success
);
2232 SSVAL(*rparam
,2,0); /* converter word */
2238 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2239 pstrcpy(p2
,local_machine
);
2241 p2
= skip_string(p2
,1);
2244 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2245 pstrcpy(p2
,current_user_info
.smb_name
);
2246 p2
= skip_string(p2
,1);
2249 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2250 pstrcpy(p2
,global_myworkgroup
);
2252 p2
= skip_string(p2
,1);
2255 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2256 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2259 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2260 pstrcpy(p2
,global_myworkgroup
); /* don't know. login domain?? */
2261 p2
= skip_string(p2
,1);
2264 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
2266 p2
= skip_string(p2
,1);
2269 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2271 SSVAL(*rparam
,4,*rdata_len
);
2276 /****************************************************************************
2277 get info about a user
2279 struct user_info_11 {
2280 char usri11_name[21]; 0-20
2282 char *usri11_comment; 22-25
2283 char *usri11_usr_comment; 26-29
2284 unsigned short usri11_priv; 30-31
2285 unsigned long usri11_auth_flags; 32-35
2286 long usri11_password_age; 36-39
2287 char *usri11_homedir; 40-43
2288 char *usri11_parms; 44-47
2289 long usri11_last_logon; 48-51
2290 long usri11_last_logoff; 52-55
2291 unsigned short usri11_bad_pw_count; 56-57
2292 unsigned short usri11_num_logons; 58-59
2293 char *usri11_logon_server; 60-63
2294 unsigned short usri11_country_code; 64-65
2295 char *usri11_workstations; 66-69
2296 unsigned long usri11_max_storage; 70-73
2297 unsigned short usri11_units_per_week; 74-75
2298 unsigned char *usri11_logon_hours; 76-79
2299 unsigned short usri11_code_page; 80-81
2304 usri11_name specifies the user name for which information is retireved
2306 usri11_pad aligns the next data structure element to a word boundary
2308 usri11_comment is a null terminated ASCII comment
2310 usri11_user_comment is a null terminated ASCII comment about the user
2312 usri11_priv specifies the level of the privilege assigned to the user.
2313 The possible values are:
2315 Name Value Description
2316 USER_PRIV_GUEST 0 Guest privilege
2317 USER_PRIV_USER 1 User privilege
2318 USER_PRV_ADMIN 2 Administrator privilege
2320 usri11_auth_flags specifies the account operator privileges. The
2321 possible values are:
2323 Name Value Description
2324 AF_OP_PRINT 0 Print operator
2327 Leach, Naik [Page 28]
2331 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2334 AF_OP_COMM 1 Communications operator
2335 AF_OP_SERVER 2 Server operator
2336 AF_OP_ACCOUNTS 3 Accounts operator
2339 usri11_password_age specifies how many seconds have elapsed since the
2340 password was last changed.
2342 usri11_home_dir points to a null terminated ASCII string that contains
2343 the path name of the user's home directory.
2345 usri11_parms points to a null terminated ASCII string that is set
2346 aside for use by applications.
2348 usri11_last_logon specifies the time when the user last logged on.
2349 This value is stored as the number of seconds elapsed since
2350 00:00:00, January 1, 1970.
2352 usri11_last_logoff specifies the time when the user last logged off.
2353 This value is stored as the number of seconds elapsed since
2354 00:00:00, January 1, 1970. A value of 0 means the last logoff
2357 usri11_bad_pw_count specifies the number of incorrect passwords
2358 entered since the last successful logon.
2360 usri11_log1_num_logons specifies the number of times this user has
2361 logged on. A value of -1 means the number of logons is unknown.
2363 usri11_logon_server points to a null terminated ASCII string that
2364 contains the name of the server to which logon requests are sent.
2365 A null string indicates logon requests should be sent to the
2368 usri11_country_code specifies the country code for the user's language
2371 usri11_workstations points to a null terminated ASCII string that
2372 contains the names of workstations the user may log on from.
2373 There may be up to 8 workstations, with the names separated by
2374 commas. A null strings indicates there are no restrictions.
2376 usri11_max_storage specifies the maximum amount of disk space the user
2377 can occupy. A value of 0xffffffff indicates there are no
2380 usri11_units_per_week specifies the equal number of time units into
2381 which a week is divided. This value must be equal to 168.
2383 usri11_logon_hours points to a 21 byte (168 bits) string that
2384 specifies the time during which the user can log on. Each bit
2385 represents one unique hour in a week. The first bit (bit 0, word
2386 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2390 Leach, Naik [Page 29]
2394 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2397 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2398 are no restrictions.
2400 usri11_code_page specifies the code page for the user's language of
2403 All of the pointers in this data structure need to be treated
2404 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2405 to be ignored. The converter word returned in the parameters section
2406 needs to be subtracted from the lower 16 bits to calculate an offset
2407 into the return buffer where this ASCII string resides.
2409 There is no auxiliary data in the response.
2411 ****************************************************************************/
2413 #define usri11_name 0
2414 #define usri11_pad 21
2415 #define usri11_comment 22
2416 #define usri11_usr_comment 26
2417 #define usri11_full_name 30
2418 #define usri11_priv 34
2419 #define usri11_auth_flags 36
2420 #define usri11_password_age 40
2421 #define usri11_homedir 44
2422 #define usri11_parms 48
2423 #define usri11_last_logon 52
2424 #define usri11_last_logoff 56
2425 #define usri11_bad_pw_count 60
2426 #define usri11_num_logons 62
2427 #define usri11_logon_server 64
2428 #define usri11_country_code 68
2429 #define usri11_workstations 70
2430 #define usri11_max_storage 74
2431 #define usri11_units_per_week 78
2432 #define usri11_logon_hours 80
2433 #define usri11_code_page 84
2434 #define usri11_end 86
2436 #define USER_PRIV_GUEST 0
2437 #define USER_PRIV_USER 1
2438 #define USER_PRIV_ADMIN 2
2440 #define AF_OP_PRINT 0
2441 #define AF_OP_COMM 1
2442 #define AF_OP_SERVER 2
2443 #define AF_OP_ACCOUNTS 3
2446 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2447 int mdrcnt
,int mprcnt
,
2448 char **rdata
,char **rparam
,
2449 int *rdata_len
,int *rparam_len
)
2451 char *str1
= param
+2;
2452 char *str2
= skip_string(str1
,1);
2453 char *UserName
= skip_string(str2
,1);
2454 char *p
= skip_string(UserName
,1);
2455 int uLevel
= SVAL(p
,0);
2458 /* get NIS home of a previously validated user - simeon */
2459 /* With share level security vuid will always be zero.
2460 Don't depend on vuser being non-null !!. JRA */
2461 user_struct
*vuser
= get_valid_user_struct(vuid
);
2463 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
2464 vuser
->user
.unix_name
));
2467 *rparam
= REALLOC(*rparam
,*rparam_len
);
2469 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
2471 /* check it's a supported variant */
2472 if (strcmp(str1
,"zWrLh") != 0) return False
;
2475 case 0: p2
= "B21"; break;
2476 case 1: p2
= "B21BB16DWzzWz"; break;
2477 case 2: p2
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2478 case 10: p2
= "B21Bzzz"; break;
2479 case 11: p2
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2480 default: return False
;
2483 if (strcmp(p2
,str2
) != 0) return False
;
2485 *rdata_len
= mdrcnt
+ 1024;
2486 *rdata
= REALLOC(*rdata
,*rdata_len
);
2488 SSVAL(*rparam
,0,NERR_Success
);
2489 SSVAL(*rparam
,2,0); /* converter word */
2492 p2
= p
+ usri11_end
;
2495 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
2499 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
2504 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
2505 pstrcpy(p2
,"Comment");
2506 p2
= skip_string(p2
,1);
2508 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
2509 pstrcpy(p2
,"UserComment");
2510 p2
= skip_string(p2
,1);
2512 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2513 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
2514 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2515 p2
= skip_string(p2
,1);
2518 if (uLevel
== 11) /* modelled after NTAS 3.51 reply */
2520 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2521 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
2522 SIVALS(p
,usri11_password_age
,-1); /* password age */
2523 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
2524 pstrcpy(p2
, lp_logon_home());
2525 standard_sub_conn(conn
, p2
,*rdata_len
-(p2
- *rdata
));
2526 p2
= skip_string(p2
,1);
2527 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
2529 p2
= skip_string(p2
,1);
2530 SIVAL(p
,usri11_last_logon
,0); /* last logon */
2531 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
2532 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
2533 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
2534 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
2535 pstrcpy(p2
,"\\\\*");
2536 p2
= skip_string(p2
,1);
2537 SSVAL(p
,usri11_country_code
,0); /* country code */
2539 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
2541 p2
= skip_string(p2
,1);
2543 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
2544 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
2545 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
2547 /* a simple way to get logon hours at all times. */
2549 SCVAL(p2
,21,0); /* fix zero termination */
2550 p2
= skip_string(p2
,1);
2552 SSVAL(p
,usri11_code_page
,0); /* code page */
2554 if (uLevel
== 1 || uLevel
== 2)
2556 memset(p
+22,' ',16); /* password */
2557 SIVALS(p
,38,-1); /* password age */
2559 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2560 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
2561 pstrcpy(p2
,lp_logon_home());
2562 standard_sub_conn(conn
, p2
,*rdata_len
-(p2
- *rdata
));
2563 p2
= skip_string(p2
,1);
2564 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
2566 SSVAL(p
,52,0); /* flags */
2567 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
2568 pstrcpy(p2
,lp_logon_script());
2569 standard_sub_conn( conn
, p2
,*rdata_len
-(p2
- *rdata
));
2570 p2
= skip_string(p2
,1);
2573 SIVAL(p
,60,0); /* auth_flags */
2574 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
2575 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2576 p2
= skip_string(p2
,1);
2577 SIVAL(p
,68,0); /* urs_comment */
2578 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
2580 p2
= skip_string(p2
,1);
2581 SIVAL(p
,76,0); /* workstations */
2582 SIVAL(p
,80,0); /* last_logon */
2583 SIVAL(p
,84,0); /* last_logoff */
2584 SIVALS(p
,88,-1); /* acct_expires */
2585 SIVALS(p
,92,-1); /* max_storage */
2586 SSVAL(p
,96,168); /* units_per_week */
2587 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
2590 SSVALS(p
,102,-1); /* bad_pw_count */
2591 SSVALS(p
,104,-1); /* num_logons */
2592 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
2593 pstrcpy(p2
,"\\\\%L");
2594 standard_sub_conn(conn
, p2
,*rdata_len
-(p2
- *rdata
));
2595 p2
= skip_string(p2
,1);
2596 SSVAL(p
,110,49); /* country_code */
2597 SSVAL(p
,112,860); /* code page */
2601 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2603 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
2608 /*******************************************************************
2609 get groups that a user is a member of
2610 ******************************************************************/
2611 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2612 int mdrcnt
,int mprcnt
,
2613 char **rdata
,char **rparam
,
2614 int *rdata_len
,int *rparam_len
)
2616 char *str1
= param
+2;
2617 char *str2
= skip_string(str1
,1);
2618 char *UserName
= skip_string(str2
,1);
2619 char *p
= skip_string(UserName
,1);
2620 int uLevel
= SVAL(p
,0);
2625 *rparam
= REALLOC(*rparam
,*rparam_len
);
2627 /* check it's a supported varient */
2628 if (strcmp(str1
,"zWrLeh") != 0) return False
;
2630 case 0: p2
= "B21"; break;
2631 default: return False
;
2633 if (strcmp(p2
,str2
) != 0) return False
;
2635 *rdata_len
= mdrcnt
+ 1024;
2636 *rdata
= REALLOC(*rdata
,*rdata_len
);
2638 SSVAL(*rparam
,0,NERR_Success
);
2639 SSVAL(*rparam
,2,0); /* converter word */
2643 /* XXXX we need a real SAM database some day */
2644 pstrcpy(p
,"Users"); p
+= 21; count
++;
2645 pstrcpy(p
,"Domain Users"); p
+= 21; count
++;
2646 pstrcpy(p
,"Guests"); p
+= 21; count
++;
2647 pstrcpy(p
,"Domain Guests"); p
+= 21; count
++;
2649 *rdata_len
= PTR_DIFF(p
,*rdata
);
2651 SSVAL(*rparam
,4,count
); /* is this right?? */
2652 SSVAL(*rparam
,6,count
); /* is this right?? */
2658 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2659 int mdrcnt
,int mprcnt
,
2660 char **rdata
,char **rparam
,
2661 int *rdata_len
,int *rparam_len
)
2663 char *str1
= param
+2;
2664 char *str2
= skip_string(str1
,1);
2665 char *p
= skip_string(str2
,1);
2667 struct pack_desc desc
;
2673 memset((char *)&desc
,'\0',sizeof(desc
));
2675 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
2677 /* check it's a supported varient */
2678 if (strcmp(str1
,"OOWb54WrLh") != 0) return False
;
2679 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) return False
;
2680 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2682 desc
.buflen
= mdrcnt
;
2683 desc
.subformat
= NULL
;
2686 if (init_package(&desc
,1,0))
2688 PACKI(&desc
,"W",0); /* code */
2689 PACKS(&desc
,"B21",name
); /* eff. name */
2690 PACKS(&desc
,"B",""); /* pad */
2692 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2693 PACKI(&desc
,"D",0); /* auth flags XXX */
2694 PACKI(&desc
,"W",0); /* num logons */
2695 PACKI(&desc
,"W",0); /* bad pw count */
2696 PACKI(&desc
,"D",0); /* last logon */
2697 PACKI(&desc
,"D",-1); /* last logoff */
2698 PACKI(&desc
,"D",-1); /* logoff time */
2699 PACKI(&desc
,"D",-1); /* kickoff time */
2700 PACKI(&desc
,"D",0); /* password age */
2701 PACKI(&desc
,"D",0); /* password can change */
2702 PACKI(&desc
,"D",-1); /* password must change */
2705 fstrcpy(mypath
,"\\\\");
2706 fstrcat(mypath
,local_machine
);
2708 PACKS(&desc
,"z",mypath
); /* computer */
2710 PACKS(&desc
,"z",global_myworkgroup
);/* domain */
2712 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2713 /* made sure all macros are fully substituted and available */
2715 pstring logon_script
;
2716 pstrcpy(logon_script
,lp_logon_script());
2717 standard_sub_conn( conn
, logon_script
,sizeof(logon_script
) );
2718 PACKS(&desc
,"z", logon_script
); /* script path */
2720 /* End of JHT mods */
2722 PACKI(&desc
,"D",0x00000000); /* reserved */
2725 *rdata_len
= desc
.usedlen
;
2727 *rparam
= REALLOC(*rparam
,*rparam_len
);
2728 SSVALS(*rparam
,0,desc
.errcode
);
2730 SSVAL(*rparam
,4,desc
.neededlen
);
2732 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
2737 /****************************************************************************
2738 api_WAccessGetUserPerms
2739 ****************************************************************************/
2740 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2741 int mdrcnt
,int mprcnt
,
2742 char **rdata
,char **rparam
,
2743 int *rdata_len
,int *rparam_len
)
2745 char *str1
= param
+2;
2746 char *str2
= skip_string(str1
,1);
2747 char *user
= skip_string(str2
,1);
2748 char *resource
= skip_string(user
,1);
2750 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
2752 /* check it's a supported varient */
2753 if (strcmp(str1
,"zzh") != 0) return False
;
2754 if (strcmp(str2
,"") != 0) return False
;
2757 *rparam
= REALLOC(*rparam
,*rparam_len
);
2758 SSVALS(*rparam
,0,0); /* errorcode */
2759 SSVAL(*rparam
,2,0); /* converter word */
2760 SSVAL(*rparam
,4,0x7f); /* permission flags */
2765 /****************************************************************************
2766 api_WPrintJobEnumerate
2767 ****************************************************************************/
2768 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2769 int mdrcnt
,int mprcnt
,
2770 char **rdata
,char **rparam
,
2771 int *rdata_len
,int *rparam_len
)
2773 char *str1
= param
+2;
2774 char *str2
= skip_string(str1
,1);
2775 char *p
= skip_string(str2
,1);
2781 struct pack_desc desc
;
2782 print_queue_struct
*queue
=NULL
;
2783 print_status_struct status
;
2788 memset((char *)&desc
,'\0',sizeof(desc
));
2789 memset((char *)&status
,'\0',sizeof(status
));
2791 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
2793 /* check it's a supported varient */
2794 if (strcmp(str1
,"WWrLh") != 0) return False
;
2795 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2798 snum
= print_job_snum(job
);
2800 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2802 count
= print_queue_status(snum
,&queue
,&status
);
2803 for (i
= 0; i
< count
; i
++) {
2804 if (queue
[i
].job
== job
) break;
2808 *rdata
= REALLOC(*rdata
,mdrcnt
);
2810 desc
.buflen
= mdrcnt
;
2813 * Don't return data but need to get correct length
2814 * init_package will return wrong size if buflen=0
2816 desc
.buflen
= getlen(desc
.format
);
2817 desc
.base
= tmpdata
= (char *)malloc ( desc
.buflen
);
2820 if (init_package(&desc
,1,0)) {
2822 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
2823 *rdata_len
= desc
.usedlen
;
2826 desc
.errcode
= NERR_JobNotFound
;
2832 *rparam
= REALLOC(*rparam
,*rparam_len
);
2833 SSVALS(*rparam
,0,desc
.errcode
);
2835 SSVAL(*rparam
,4,desc
.neededlen
);
2840 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
2844 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2845 int mdrcnt
,int mprcnt
,
2846 char **rdata
,char **rparam
,
2847 int *rdata_len
,int *rparam_len
)
2849 char *str1
= param
+2;
2850 char *str2
= skip_string(str1
,1);
2851 char *p
= skip_string(str2
,1);
2857 struct pack_desc desc
;
2858 print_queue_struct
*queue
=NULL
;
2859 print_status_struct status
;
2861 memset((char *)&desc
,'\0',sizeof(desc
));
2862 memset((char *)&status
,'\0',sizeof(status
));
2864 p
= skip_string(p
,1);
2867 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
2869 /* check it's a supported varient */
2870 if (strcmp(str1
,"zWrLeh") != 0) return False
;
2871 if (uLevel
> 2) return False
; /* defined only for uLevel 0,1,2 */
2872 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2874 snum
= lp_servicenumber(name
);
2875 if (snum
< 0 && pcap_printername_ok(name
,NULL
)) {
2876 int pnum
= lp_servicenumber(PRINTERS_NAME
);
2878 lp_add_printer(name
,pnum
);
2879 snum
= lp_servicenumber(name
);
2883 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2885 count
= print_queue_status(snum
,&queue
,&status
);
2886 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2888 desc
.buflen
= mdrcnt
;
2890 if (init_package(&desc
,count
,0)) {
2892 for (i
= 0; i
< count
; i
++) {
2893 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
2894 if (desc
.errcode
== NERR_Success
) succnt
= i
+1;
2898 *rdata_len
= desc
.usedlen
;
2901 *rparam
= REALLOC(*rparam
,*rparam_len
);
2902 SSVALS(*rparam
,0,desc
.errcode
);
2904 SSVAL(*rparam
,4,succnt
);
2905 SSVAL(*rparam
,6,count
);
2909 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
2913 static int check_printdest_info(struct pack_desc
* desc
,
2914 int uLevel
, char* id
)
2916 desc
->subformat
= NULL
;
2918 case 0: desc
->format
= "B9"; break;
2919 case 1: desc
->format
= "B9B21WWzW"; break;
2920 case 2: desc
->format
= "z"; break;
2921 case 3: desc
->format
= "zzzWWzzzWW"; break;
2922 default: return False
;
2924 if (strcmp(desc
->format
,id
) != 0) return False
;
2928 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
2929 struct pack_desc
* desc
)
2932 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
2933 buf
[sizeof(buf
)-1] = 0;
2936 PACKS(desc
,"B9",buf
); /* szName */
2938 PACKS(desc
,"B21",""); /* szUserName */
2939 PACKI(desc
,"W",0); /* uJobId */
2940 PACKI(desc
,"W",0); /* fsStatus */
2941 PACKS(desc
,"z",""); /* pszStatus */
2942 PACKI(desc
,"W",0); /* time */
2945 if (uLevel
== 2 || uLevel
== 3) {
2946 PACKS(desc
,"z",buf
); /* pszPrinterName */
2948 PACKS(desc
,"z",""); /* pszUserName */
2949 PACKS(desc
,"z",""); /* pszLogAddr */
2950 PACKI(desc
,"W",0); /* uJobId */
2951 PACKI(desc
,"W",0); /* fsStatus */
2952 PACKS(desc
,"z",""); /* pszStatus */
2953 PACKS(desc
,"z",""); /* pszComment */
2954 PACKS(desc
,"z","NULL"); /* pszDrivers */
2955 PACKI(desc
,"W",0); /* time */
2956 PACKI(desc
,"W",0); /* pad1 */
2961 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2962 int mdrcnt
,int mprcnt
,
2963 char **rdata
,char **rparam
,
2964 int *rdata_len
,int *rparam_len
)
2966 char *str1
= param
+2;
2967 char *str2
= skip_string(str1
,1);
2968 char *p
= skip_string(str2
,1);
2969 char* PrinterName
= p
;
2971 struct pack_desc desc
;
2975 memset((char *)&desc
,'\0',sizeof(desc
));
2977 p
= skip_string(p
,1);
2980 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
2982 /* check it's a supported varient */
2983 if (strcmp(str1
,"zWrLh") != 0) return False
;
2984 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
2986 snum
= lp_servicenumber(PrinterName
);
2987 if (snum
< 0 && pcap_printername_ok(PrinterName
,NULL
)) {
2988 int pnum
= lp_servicenumber(PRINTERS_NAME
);
2990 lp_add_printer(PrinterName
,pnum
);
2991 snum
= lp_servicenumber(PrinterName
);
2997 desc
.errcode
= NERR_DestNotFound
;
3002 *rdata
= REALLOC(*rdata
,mdrcnt
);
3004 desc
.buflen
= mdrcnt
;
3007 * Don't return data but need to get correct length
3008 * init_package will return wrong size if buflen=0
3010 desc
.buflen
= getlen(desc
.format
);
3011 desc
.base
= tmpdata
= (char *)malloc ( desc
.buflen
);
3013 if (init_package(&desc
,1,0)) {
3014 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
3016 *rdata_len
= desc
.usedlen
;
3020 *rparam
= REALLOC(*rparam
,*rparam_len
);
3021 SSVALS(*rparam
,0,desc
.errcode
);
3023 SSVAL(*rparam
,4,desc
.neededlen
);
3025 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3030 static BOOL
api_WPrintDestEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3031 int mdrcnt
,int mprcnt
,
3032 char **rdata
,char **rparam
,
3033 int *rdata_len
,int *rparam_len
)
3035 char *str1
= param
+2;
3036 char *str2
= skip_string(str1
,1);
3037 char *p
= skip_string(str2
,1);
3041 struct pack_desc desc
;
3042 int services
= lp_numservices();
3044 memset((char *)&desc
,'\0',sizeof(desc
));
3048 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3050 /* check it's a supported varient */
3051 if (strcmp(str1
,"WrLeh") != 0) return False
;
3052 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3055 for (i
= 0; i
< services
; i
++)
3056 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
3059 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3061 desc
.buflen
= mdrcnt
;
3062 if (init_package(&desc
,queuecnt
,0)) {
3065 for (i
= 0; i
< services
; i
++) {
3066 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3067 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3069 if (desc
.errcode
== NERR_Success
) succnt
= n
;
3074 *rdata_len
= desc
.usedlen
;
3077 *rparam
= REALLOC(*rparam
,*rparam_len
);
3078 SSVALS(*rparam
,0,desc
.errcode
);
3080 SSVAL(*rparam
,4,succnt
);
3081 SSVAL(*rparam
,6,queuecnt
);
3083 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3087 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3088 int mdrcnt
,int mprcnt
,
3089 char **rdata
,char **rparam
,
3090 int *rdata_len
,int *rparam_len
)
3092 char *str1
= param
+2;
3093 char *str2
= skip_string(str1
,1);
3094 char *p
= skip_string(str2
,1);
3097 struct pack_desc desc
;
3099 memset((char *)&desc
,'\0',sizeof(desc
));
3103 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
3105 /* check it's a supported varient */
3106 if (strcmp(str1
,"WrLeh") != 0) return False
;
3107 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) return False
;
3109 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3111 desc
.buflen
= mdrcnt
;
3112 if (init_package(&desc
,1,0)) {
3113 PACKS(&desc
,"B41","NULL");
3116 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3118 *rdata_len
= desc
.usedlen
;
3121 *rparam
= REALLOC(*rparam
,*rparam_len
);
3122 SSVALS(*rparam
,0,desc
.errcode
);
3124 SSVAL(*rparam
,4,succnt
);
3127 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
3131 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3132 int mdrcnt
,int mprcnt
,
3133 char **rdata
,char **rparam
,
3134 int *rdata_len
,int *rparam_len
)
3136 char *str1
= param
+2;
3137 char *str2
= skip_string(str1
,1);
3138 char *p
= skip_string(str2
,1);
3141 struct pack_desc desc
;
3143 memset((char *)&desc
,'\0',sizeof(desc
));
3147 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
3149 /* check it's a supported varient */
3150 if (strcmp(str1
,"WrLeh") != 0) return False
;
3151 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) return False
;
3153 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3155 desc
.buflen
= mdrcnt
;
3157 if (init_package(&desc
,1,0)) {
3158 PACKS(&desc
,"B13","lpd");
3161 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3163 *rdata_len
= desc
.usedlen
;
3166 *rparam
= REALLOC(*rparam
,*rparam_len
);
3167 SSVALS(*rparam
,0,desc
.errcode
);
3169 SSVAL(*rparam
,4,succnt
);
3172 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
3176 static BOOL
api_WPrintPortEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3177 int mdrcnt
,int mprcnt
,
3178 char **rdata
,char **rparam
,
3179 int *rdata_len
,int *rparam_len
)
3181 char *str1
= param
+2;
3182 char *str2
= skip_string(str1
,1);
3183 char *p
= skip_string(str2
,1);
3186 struct pack_desc desc
;
3188 memset((char *)&desc
,'\0',sizeof(desc
));
3192 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
3194 /* check it's a supported varient */
3195 if (strcmp(str1
,"WrLeh") != 0) return False
;
3196 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) return False
;
3198 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3199 memset((char *)&desc
,'\0',sizeof(desc
));
3201 desc
.buflen
= mdrcnt
;
3203 if (init_package(&desc
,1,0)) {
3204 PACKS(&desc
,"B13","lp0");
3207 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3209 *rdata_len
= desc
.usedlen
;
3212 *rparam
= REALLOC(*rparam
,*rparam_len
);
3213 SSVALS(*rparam
,0,desc
.errcode
);
3215 SSVAL(*rparam
,4,succnt
);
3218 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
3222 /****************************************************************************
3223 The buffer was too small
3224 ****************************************************************************/
3226 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3227 int mdrcnt
,int mprcnt
,
3228 char **rdata
,char **rparam
,
3229 int *rdata_len
,int *rparam_len
)
3231 *rparam_len
= MIN(*rparam_len
,mprcnt
);
3232 *rparam
= REALLOC(*rparam
,*rparam_len
);
3236 SSVAL(*rparam
,0,NERR_BufTooSmall
);
3238 DEBUG(3,("Supplied buffer too small in API command\n"));
3244 /****************************************************************************
3245 The request is not supported
3246 ****************************************************************************/
3248 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3249 int mdrcnt
,int mprcnt
,
3250 char **rdata
,char **rparam
,
3251 int *rdata_len
,int *rparam_len
)
3254 *rparam
= REALLOC(*rparam
,*rparam_len
);
3258 SSVAL(*rparam
,0,NERR_notsupported
);
3259 SSVAL(*rparam
,2,0); /* converter word */
3261 DEBUG(3,("Unsupported API command\n"));
3273 BOOL (*fn
)(connection_struct
*,uint16
,char *,char *,
3274 int,int,char **,char **,int *,int *);
3276 } api_commands
[] = {
3277 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
,0},
3278 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
,0},
3279 #if 0 /* Not yet implemented. */
3280 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
,0},
3282 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
,0},
3283 #if 0 /* Not yet implemented. */
3284 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
,0},
3286 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
,0},
3287 #if 0 /* Not yet implemented. */
3288 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
,0},
3290 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
,0},
3291 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
,0},
3292 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
,0},
3293 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
,0},
3294 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
,0},
3295 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
,0},
3296 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
,0},
3297 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
,0},
3298 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
,0},
3299 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
,0},
3300 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
,0},
3301 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
,0},
3302 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
,0},
3303 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
,0},
3304 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
,0},
3305 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
,0},
3306 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
,0},
3307 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
,0},
3308 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
,0},
3309 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
,0},
3310 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
,0},
3311 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
,0},
3312 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
,0},
3313 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
,0},
3314 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
,0},
3315 {NULL
, -1, api_Unsupported
,0}};
3318 /****************************************************************************
3319 Handle remote api calls
3320 ****************************************************************************/
3322 int api_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,char *data
,char *params
,
3323 int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
3327 char *rparam
= NULL
;
3334 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3338 api_command
= SVAL(params
,0);
3340 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3343 skip_string(params
+2,1),
3344 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
3346 for (i
=0;api_commands
[i
].name
;i
++) {
3347 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
3348 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
3353 rdata
= (char *)malloc(1024);
3355 memset(rdata
,'\0',1024);
3357 rparam
= (char *)malloc(1024);
3359 memset(rparam
,'\0',1024);
3361 if(!rdata
|| !rparam
) {
3362 DEBUG(0,("api_reply: malloc fail !\n"));
3366 reply
= api_commands
[i
].fn(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3367 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3370 if (rdata_len
> mdrcnt
||
3371 rparam_len
> mprcnt
) {
3372 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3373 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3376 /* if we get False back then it's actually unsupported */
3378 api_Unsupported(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3379 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3381 send_trans_reply(outbuf
, rparam
, rparam_len
, rdata
, rdata_len
, False
);