2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1998
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
36 extern fstring local_machine
;
37 extern pstring global_myname
;
38 extern fstring global_myworkgroup
;
40 #define NERR_Success 0
41 #define NERR_badpass 86
42 #define NERR_notsupported 50
44 #define NERR_BASE (2100)
45 #define NERR_BufTooSmall (NERR_BASE+23)
46 #define NERR_JobNotFound (NERR_BASE+51)
47 #define NERR_DestNotFound (NERR_BASE+52)
49 #define ACCESS_READ 0x01
50 #define ACCESS_WRITE 0x02
51 #define ACCESS_CREATE 0x04
53 #define SHPWLEN 8 /* share password length */
55 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
56 int mdrcnt
,int mprcnt
,
57 char **rdata
,char **rparam
,
58 int *rdata_len
,int *rparam_len
);
59 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
60 int mdrcnt
,int mprcnt
,
61 char **rdata
,char **rparam
,
62 int *rdata_len
,int *rparam_len
);
65 static int CopyExpanded(connection_struct
*conn
,
66 int snum
, char** dst
, char* src
, int* n
)
71 if (!src
|| !dst
|| !n
|| !(*dst
)) return(0);
73 StrnCpy(buf
,src
,sizeof(buf
)/2);
74 pstring_sub(buf
,"%S",lp_servicename(snum
));
75 standard_sub_conn(conn
,buf
);
76 l
= push_ascii(*dst
,buf
,*n
-1, STR_TERMINATE
);
82 static int CopyAndAdvance(char** dst
, char* src
, int* n
)
85 if (!src
|| !dst
|| !n
|| !(*dst
)) return(0);
86 l
= push_ascii(*dst
,src
,*n
-1, STR_TERMINATE
);
92 static int StrlenExpanded(connection_struct
*conn
, int snum
, char* s
)
96 StrnCpy(buf
,s
,sizeof(buf
)/2);
97 pstring_sub(buf
,"%S",lp_servicename(snum
));
98 standard_sub_conn(conn
,buf
);
99 return strlen(buf
) + 1;
102 static char* Expand(connection_struct
*conn
, int snum
, char* s
)
105 if (!s
) return(NULL
);
106 StrnCpy(buf
,s
,sizeof(buf
)/2);
107 pstring_sub(buf
,"%S",lp_servicename(snum
));
108 standard_sub_conn(conn
,buf
);
112 /*******************************************************************
113 check a API string for validity when we only need to check the prefix
114 ******************************************************************/
115 static BOOL
prefix_ok(char *str
,char *prefix
)
117 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
121 char* format
; /* formatstring for structure */
122 char* subformat
; /* subformat for structure */
123 char* base
; /* baseaddress of buffer */
124 int buflen
; /* remaining size for fixed part; on init: length of base */
125 int subcount
; /* count of substructures */
126 char* structbuf
; /* pointer into buffer for remaining fixed part */
127 int stringlen
; /* remaining size for variable part */
128 char* stringbuf
; /* pointer into buffer for remaining variable part */
129 int neededlen
; /* total needed size */
130 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
131 char* curpos
; /* current position; pointer into format or subformat */
135 static int get_counter(char** p
)
138 if (!p
|| !(*p
)) return(1);
139 if (!isdigit((int)**p
)) return 1;
143 n
= 10 * n
+ (i
- '0');
150 static int getlen(char* p
)
156 case 'W': /* word (2 byte) */
159 case 'K': /* status word? (2 byte) */
162 case 'N': /* count of substructures (word) at end */
165 case 'D': /* double word (4 byte) */
166 case 'z': /* offset to zero terminated string (4 byte) */
167 case 'l': /* offset to user data (4 byte) */
170 case 'b': /* offset to data (with counter) (4 byte) */
174 case 'B': /* byte (with optional counter) */
175 n
+= get_counter(&p
);
182 static BOOL
init_package(struct pack_desc
* p
, int count
, int subcount
)
187 if (!p
->format
|| !p
->base
) return(False
);
189 i
= count
* getlen(p
->format
);
190 if (p
->subformat
) i
+= subcount
* getlen(p
->subformat
);
191 p
->structbuf
= p
->base
;
195 p
->curpos
= p
->format
;
201 * This is the old error code we used. Aparently
202 * WinNT/2k systems return ERRbuftoosmall (2123) and
203 * OS/2 needs this. I'm leaving this here so we can revert
206 p
->errcode
= ERRmoredata
;
208 p
->errcode
= ERRbuftoosmall
;
212 p
->errcode
= NERR_Success
;
215 p
->stringbuf
= p
->base
+ i
;
217 return(p
->errcode
== NERR_Success
);
220 static int package(struct pack_desc
* p
, ...)
223 int needed
=0, stringneeded
;
225 int is_string
=0, stringused
;
232 p
->curpos
= p
->format
;
234 p
->curpos
= p
->subformat
;
239 str
= va_arg(args
,char*);
240 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
249 switch( *p
->curpos
++ ) {
250 case 'W': /* word (2 byte) */
252 temp
= va_arg(args
,int);
253 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,temp
);
255 case 'K': /* status word? (2 byte) */
257 temp
= va_arg(args
,int);
258 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,temp
);
260 case 'N': /* count of substructures (word) at end */
262 p
->subcount
= va_arg(args
,int);
263 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,p
->subcount
);
265 case 'D': /* double word (4 byte) */
267 temp
= va_arg(args
,int);
268 if (p
->buflen
>= needed
) SIVAL(p
->structbuf
,0,temp
);
270 case 'B': /* byte (with optional counter) */
271 needed
= get_counter(&p
->curpos
);
273 char *s
= va_arg(args
,char*);
274 if (p
->buflen
>= needed
) StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
277 case 'z': /* offset to zero terminated string (4 byte) */
278 str
= va_arg(args
,char*);
279 stringneeded
= (str
? strlen(str
)+1 : 0);
282 case 'l': /* offset to user data (4 byte) */
283 str
= va_arg(args
,char*);
284 stringneeded
= va_arg(args
,int);
287 case 'b': /* offset to data (with counter) (4 byte) */
288 str
= va_arg(args
,char*);
289 stringneeded
= get_counter(&p
->curpos
);
294 if (stringneeded
>= 0) {
296 if (p
->buflen
>= needed
) {
297 stringused
= stringneeded
;
298 if (stringused
> p
->stringlen
) {
299 stringused
= (is_string
? p
->stringlen
: 0);
300 if (p
->errcode
== NERR_Success
) p
->errcode
= ERRmoredata
;
303 SIVAL(p
->structbuf
,0,0);
305 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
306 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
307 if (is_string
) p
->stringbuf
[stringused
-1] = '\0';
308 p
->stringbuf
+= stringused
;
309 p
->stringlen
-= stringused
;
310 p
->usedlen
+= stringused
;
313 p
->neededlen
+= stringneeded
;
315 p
->neededlen
+= needed
;
316 if (p
->buflen
>= needed
) {
317 p
->structbuf
+= needed
;
319 p
->usedlen
+= needed
;
322 if (p
->errcode
== NERR_Success
) p
->errcode
= ERRmoredata
;
328 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
329 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
331 #define PACK(desc,t,v) package(desc,v)
332 #define PACKl(desc,t,v,l) package(desc,v,l)
335 static void PACKI(struct pack_desc
* desc
,char *t
,int v
)
340 static void PACKS(struct pack_desc
* desc
,char *t
,char *v
)
346 /****************************************************************************
348 ****************************************************************************/
349 static void PackDriverData(struct pack_desc
* desc
)
351 char drivdata
[4+4+32];
352 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
353 SIVAL(drivdata
,4,1000); /* lVersion */
354 memset(drivdata
+8,0,32); /* szDeviceName */
355 push_ascii(drivdata
+8,"NULL",-1, STR_TERMINATE
);
356 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
359 static int check_printq_info(struct pack_desc
* desc
,
360 int uLevel
, char *id1
, char *id2
)
362 desc
->subformat
= NULL
;
365 desc
->format
= "B13";
368 desc
->format
= "B13BWWWzzzzzWW";
371 desc
->format
= "B13BWWWzzzzzWN";
372 desc
->subformat
= "WB21BB16B10zWWzDDz";
375 desc
->format
= "zWWWWzzzzWWzzl";
378 desc
->format
= "zWWWWzzzzWNzzl";
379 desc
->subformat
= "WWzWWDDzz";
388 desc
->format
= "WzzzzzzzzN";
389 desc
->subformat
= "z";
391 default: return False
;
393 if (strcmp(desc
->format
,id1
) != 0) return False
;
394 if (desc
->subformat
&& strcmp(desc
->subformat
,id2
) != 0) return False
;
399 #define RAP_JOB_STATUS_QUEUED 0
400 #define RAP_JOB_STATUS_PAUSED 1
401 #define RAP_JOB_STATUS_SPOOLING 2
402 #define RAP_JOB_STATUS_PRINTING 3
403 #define RAP_JOB_STATUS_PRINTED 4
405 #define RAP_QUEUE_STATUS_PAUSED 1
406 #define RAP_QUEUE_STATUS_ERROR 2
408 /* turn a print job status into a on the wire status
410 static int printj_status(int v
)
414 return RAP_JOB_STATUS_QUEUED
;
416 return RAP_JOB_STATUS_PAUSED
;
418 return RAP_JOB_STATUS_SPOOLING
;
420 return RAP_JOB_STATUS_PRINTING
;
425 /* turn a print queue status into a on the wire status
427 static int printq_status(int v
)
433 return RAP_QUEUE_STATUS_PAUSED
;
435 return RAP_QUEUE_STATUS_ERROR
;
438 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
439 struct pack_desc
* desc
,
440 print_queue_struct
* queue
, int n
)
442 time_t t
= queue
->time
;
444 /* the client expects localtime */
447 PACKI(desc
,"W",queue
->job
); /* uJobId */
449 PACKS(desc
,"B21",queue
->user
); /* szUserName */
450 PACKS(desc
,"B",""); /* pad */
451 PACKS(desc
,"B16",""); /* szNotifyName */
452 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
453 PACKS(desc
,"z",""); /* pszParms */
454 PACKI(desc
,"W",n
+1); /* uPosition */
455 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
456 PACKS(desc
,"z",""); /* pszStatus */
457 PACKI(desc
,"D",t
); /* ulSubmitted */
458 PACKI(desc
,"D",queue
->size
); /* ulSize */
459 PACKS(desc
,"z",queue
->file
); /* pszComment */
461 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
462 PACKI(desc
,"W",queue
->priority
); /* uPriority */
463 PACKS(desc
,"z",queue
->user
); /* pszUserName */
464 PACKI(desc
,"W",n
+1); /* uPosition */
465 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
466 PACKI(desc
,"D",t
); /* ulSubmitted */
467 PACKI(desc
,"D",queue
->size
); /* ulSize */
468 PACKS(desc
,"z","Samba"); /* pszComment */
469 PACKS(desc
,"z",queue
->file
); /* pszDocument */
471 PACKS(desc
,"z",""); /* pszNotifyName */
472 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
473 PACKS(desc
,"z",""); /* pszParms */
474 PACKS(desc
,"z",""); /* pszStatus */
475 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
476 PACKS(desc
,"z","lpd"); /* pszQProcName */
477 PACKS(desc
,"z",""); /* pszQProcParms */
478 PACKS(desc
,"z","NULL"); /* pszDriverName */
479 PackDriverData(desc
); /* pDriverData */
480 PACKS(desc
,"z",""); /* pszPrinterName */
481 } else if (uLevel
== 4) { /* OS2 */
482 PACKS(desc
,"z",""); /* pszSpoolFileName */
483 PACKS(desc
,"z",""); /* pszPortName */
484 PACKS(desc
,"z",""); /* pszStatus */
485 PACKI(desc
,"D",0); /* ulPagesSpooled */
486 PACKI(desc
,"D",0); /* ulPagesSent */
487 PACKI(desc
,"D",0); /* ulPagesPrinted */
488 PACKI(desc
,"D",0); /* ulTimePrinted */
489 PACKI(desc
,"D",0); /* ulExtendJobStatus */
490 PACKI(desc
,"D",0); /* ulStartPage */
491 PACKI(desc
,"D",0); /* ulEndPage */
496 /********************************************************************
497 Return a driver name given an snum.
498 Looks in a tdb first. Returns True if from tdb, False otherwise.
499 ********************************************************************/
501 static BOOL
get_driver_name(int snum
, pstring drivername
)
503 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
506 get_a_printer (&info
, 2, lp_servicename(snum
));
508 pstrcpy( drivername
, info
->info_2
->drivername
);
510 free_a_printer(&info
, 2);
512 pstrcpy( drivername
, lp_printerdriver(snum
));
518 /********************************************************************
519 Respond to the DosPrintQInfo command with a level of 52
520 This is used to get printer driver information for Win9x clients
521 ********************************************************************/
522 static void fill_printq_info_52(connection_struct
*conn
, int snum
, int uLevel
,
523 struct pack_desc
* desc
,
524 int count
, print_queue_struct
* queue
,
525 print_status_struct
* status
)
529 pstring tok
,driver
,datafile
,langmon
,helpfile
,datatype
;
538 * Check in the tdb *first* before checking the legacy
539 * files. This allows an NT upload to take precedence over
540 * the existing fileset. JRA.
542 * we need to lookup the driver name prior to making the call
543 * to get_a_printer_driver_9x_compatible() and not rely on the
544 * 'print driver' parameter --jerry
548 if ((get_driver_name(snum
,drivername
)) &&
549 ((ok
= get_a_printer_driver_9x_compatible(gen_line
, drivername
)) == True
))
553 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername
, gen_line
));
557 /* didn't find driver in tdb */
559 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
560 snum
, drivername
, lp_driverfile(snum
)));
562 lines
= file_lines_load(lp_driverfile(snum
),NULL
);
565 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum
),
567 desc
->errcode
=NERR_notsupported
;
571 /* lookup the long printer driver name in the file description */
572 for (i
=0;lines
[i
] && !ok
;i
++)
575 if (next_token(&p
,tok
,":",sizeof(tok
)) &&
576 (strlen(drivername
) == strlen(tok
)) &&
577 (!strncmp(tok
,drivername
,strlen(drivername
))))
586 /* driver file name */
587 if (!next_token(&p
,driver
,":",sizeof(driver
)))
591 if (!next_token(&p
,datafile
,":",sizeof(datafile
)))
595 * for the next tokens - which may be empty - I have
596 * to check for empty tokens first because the
597 * next_token function will skip all empty token
606 else if (!next_token(&p
,helpfile
,":",sizeof(helpfile
)))
609 /* language monitor */
615 else if (!next_token(&p
,langmon
,":",sizeof(langmon
)))
618 /* default data type */
619 if (!next_token(&p
,datatype
,":",sizeof(datatype
)))
622 PACKI(desc
,"W",0x0400); /* don't know */
623 PACKS(desc
,"z",drivername
); /* long printer name */
624 PACKS(desc
,"z",driver
); /* Driverfile Name */
625 PACKS(desc
,"z",datafile
); /* Datafile name */
626 PACKS(desc
,"z",langmon
); /* language monitor */
629 fstrcpy(location
, "\\\\");
630 fstrcat(location
, global_myname
);
631 fstrcat(location
, "\\print$\\WIN40\\0");
632 PACKS(desc
,"z",location
); /* share to retrieve files */
636 PACKS(desc
,"z",lp_driverlocation(snum
)); /* share to retrieve files */
638 PACKS(desc
,"z",datatype
); /* default data type */
639 PACKS(desc
,"z",helpfile
); /* helpfile name */
640 PACKS(desc
,"z",driver
); /* driver name */
642 DEBUG(3,("printerdriver:%s:\n",drivername
));
643 DEBUG(3,("Driver:%s:\n",driver
));
644 DEBUG(3,("Data File:%s:\n",datafile
));
645 DEBUG(3,("Language Monitor:%s:\n",langmon
));
647 DEBUG(3,("lp_driverlocation:%s:\n",location
));
649 DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum
)));
650 DEBUG(3,("Data Type:%s:\n",datatype
));
651 DEBUG(3,("Help File:%s:\n",helpfile
));
652 PACKI(desc
,"N",count
); /* number of files to copy */
654 for (i
=0;i
<count
;i
++)
656 /* no need to check return value here
657 * - it was already tested in
658 * get_printerdrivernumber */
659 next_token(&p
,tok
,",",sizeof(tok
));
660 PACKS(desc
,"z",tok
); /* driver files to copy */
661 DEBUG(3,("file:%s:\n",tok
));
664 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
665 SERVICE(snum
),count
));
667 desc
->errcode
=NERR_Success
;
673 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
674 desc
->errcode
=NERR_notsupported
;
677 file_lines_free(lines
);
681 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
682 struct pack_desc
* desc
,
683 int count
, print_queue_struct
* queue
,
684 print_status_struct
* status
)
689 PACKS(desc
,"B13",SERVICE(snum
));
694 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
697 PACKI(desc
,"K",printq_status(status
->status
));
701 if (uLevel
== 1 || uLevel
== 2) {
702 PACKS(desc
,"B",""); /* alignment */
703 PACKI(desc
,"W",5); /* priority */
704 PACKI(desc
,"W",0); /* start time */
705 PACKI(desc
,"W",0); /* until time */
706 PACKS(desc
,"z",""); /* pSepFile */
707 PACKS(desc
,"z","lpd"); /* pPrProc */
708 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
709 PACKS(desc
,"z",""); /* pParms */
711 PACKS(desc
,"z","UNKNOWN PRINTER");
712 PACKI(desc
,"W",LPSTAT_ERROR
);
714 else if (!status
|| !status
->message
[0]) {
715 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
716 PACKI(desc
,"W",LPSTAT_OK
); /* status */
718 PACKS(desc
,"z",status
->message
);
719 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
721 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
724 if (uLevel
== 3 || uLevel
== 4) {
727 PACKI(desc
,"W",5); /* uPriority */
728 PACKI(desc
,"W",0); /* uStarttime */
729 PACKI(desc
,"W",0); /* uUntiltime */
730 PACKI(desc
,"W",5); /* pad1 */
731 PACKS(desc
,"z",""); /* pszSepFile */
732 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
733 PACKS(desc
,"z",NULL
); /* pszParms */
734 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
735 /* "don't ask" that it's done this way to fix corrupted
736 Win9X/ME printer comments. */
738 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
740 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
742 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
743 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
744 get_driver_name(snum
,drivername
);
745 PACKS(desc
,"z",drivername
); /* pszDriverName */
746 PackDriverData(desc
); /* pDriverData */
749 if (uLevel
== 2 || uLevel
== 4) {
751 for (i
=0;i
<count
;i
++)
752 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
756 fill_printq_info_52(conn
, snum
, uLevel
, desc
, count
, queue
, status
);
760 /* This function returns the number of files for a given driver */
761 static int get_printerdrivernumber(int snum
)
772 * Check in the tdb *first* before checking the legacy
773 * files. This allows an NT upload to take precedence over
774 * the existing fileset. JRA.
776 * we need to lookup the driver name prior to making the call
777 * to get_a_printer_driver_9x_compatible() and not rely on the
778 * 'print driver' parameter --jerry
781 if ((get_driver_name(snum
,drivername
)) &&
782 (ok
= get_a_printer_driver_9x_compatible(gen_line
, drivername
) == True
))
785 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername
, gen_line
));
789 /* didn't find driver in tdb */
791 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
792 snum
, drivername
, lp_driverfile(snum
)));
794 lines
= file_lines_load(lp_driverfile(snum
), NULL
);
797 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum
),strerror(errno
)));
801 /* lookup the long printer driver name in the file description */
802 for (i
=0;lines
[i
] && !ok
;i
++)
805 if (next_token(&p
,tok
,":",sizeof(tok
)) &&
806 (strlen(drivername
) == strlen(tok
)) &&
807 (!strncmp(tok
,drivername
,strlen(drivername
))))
819 if (*p
++ == ':') i
--;
822 DEBUG(3,("Can't determine number of printer driver files\n"));
826 /* count the number of files */
827 while (next_token(&p
,tok
,",",sizeof(tok
)))
835 file_lines_free(lines
);
840 static BOOL
api_DosPrintQGetInfo(connection_struct
*conn
,
841 uint16 vuid
, char *param
,char *data
,
842 int mdrcnt
,int mprcnt
,
843 char **rdata
,char **rparam
,
844 int *rdata_len
,int *rparam_len
)
846 char *str1
= param
+2;
847 char *str2
= skip_string(str1
,1);
848 char *p
= skip_string(str2
,1);
854 struct pack_desc desc
;
855 print_queue_struct
*queue
=NULL
;
856 print_status_struct status
;
859 memset((char *)&status
,'\0',sizeof(status
));
860 memset((char *)&desc
,'\0',sizeof(desc
));
862 p
= skip_string(p
,1);
866 /* remove any trailing username */
867 if ((p
= strchr_m(QueueName
,'%')))
870 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
872 /* check it's a supported varient */
873 if (!prefix_ok(str1
,"zWrLh"))
875 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
877 * Patch from Scott Moomaw <scott@bridgewater.edu>
878 * to return the 'invalid info level' error if an
879 * unknown level was requested.
883 *rparam
= REALLOC(*rparam
,*rparam_len
);
884 SSVALS(*rparam
,0,ERRunknownlevel
);
890 snum
= lp_servicenumber(QueueName
);
891 if (snum
< 0 && pcap_printername_ok(QueueName
,NULL
)) {
892 int pnum
= lp_servicenumber(PRINTERS_NAME
);
894 lp_add_printer(QueueName
,pnum
);
895 snum
= lp_servicenumber(QueueName
);
899 if (snum
< 0 || !VALID_SNUM(snum
))
903 count
= get_printerdrivernumber(snum
);
904 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
906 count
= print_queue_status(snum
, &queue
,&status
);
910 *rdata
= REALLOC(*rdata
,mdrcnt
);
912 desc
.buflen
= mdrcnt
;
915 * Don't return data but need to get correct length
916 * init_package will return wrong size if buflen=0
918 desc
.buflen
= getlen(desc
.format
);
919 desc
.base
= tmpdata
= (char *) malloc (desc
.buflen
);
922 if (init_package(&desc
,1,count
)) {
923 desc
.subcount
= count
;
924 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
927 *rdata_len
= desc
.usedlen
;
930 * We must set the return code to ERRbuftoosmall
931 * in order to support lanman style printing with Win NT/2k
934 if (!mdrcnt
&& lp_disable_spoolss())
935 desc
.errcode
= ERRbuftoosmall
;
937 *rdata_len
= desc
.usedlen
;
939 *rparam
= REALLOC(*rparam
,*rparam_len
);
940 SSVALS(*rparam
,0,desc
.errcode
);
942 SSVAL(*rparam
,4,desc
.neededlen
);
944 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
952 /****************************************************************************
953 View list of all print jobs on all queues.
954 ****************************************************************************/
956 static BOOL
api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
, char* param
, char* data
,
957 int mdrcnt
, int mprcnt
,
958 char **rdata
, char** rparam
,
959 int *rdata_len
, int *rparam_len
)
961 char *param_format
= param
+2;
962 char *output_format1
= skip_string(param_format
,1);
963 char *p
= skip_string(output_format1
,1);
964 int uLevel
= SVAL(p
,0);
965 char *output_format2
= p
+ 4;
966 int services
= lp_numservices();
968 struct pack_desc desc
;
969 print_queue_struct
**queue
= NULL
;
970 print_status_struct
*status
= NULL
;
971 int* subcntarr
= NULL
;
972 int queuecnt
, subcnt
=0, succnt
=0;
974 memset((char *)&desc
,'\0',sizeof(desc
));
976 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
978 if (!prefix_ok(param_format
,"WrLeh")) return False
;
979 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
981 * Patch from Scott Moomaw <scott@bridgewater.edu>
982 * to return the 'invalid info level' error if an
983 * unknown level was requested.
987 *rparam
= REALLOC(*rparam
,*rparam_len
);
988 SSVALS(*rparam
,0,ERRunknownlevel
);
995 for (i
= 0; i
< services
; i
++)
996 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
999 if((queue
= (print_queue_struct
**)malloc(queuecnt
*sizeof(print_queue_struct
*))) == NULL
) {
1000 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1003 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
1004 if((status
= (print_status_struct
*)malloc(queuecnt
*sizeof(print_status_struct
))) == NULL
) {
1005 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1008 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
1009 if((subcntarr
= (int*)malloc(queuecnt
*sizeof(int))) == NULL
) {
1010 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1015 for (i
= 0; i
< services
; i
++)
1016 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1017 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
1018 subcnt
+= subcntarr
[n
];
1022 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
1024 desc
.buflen
= mdrcnt
;
1026 if (init_package(&desc
,queuecnt
,subcnt
)) {
1029 for (i
= 0; i
< services
; i
++)
1030 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1031 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
1033 if (desc
.errcode
== NERR_Success
) succnt
= n
;
1037 SAFE_FREE(subcntarr
);
1039 *rdata_len
= desc
.usedlen
;
1041 *rparam
= REALLOC(*rparam
,*rparam_len
);
1042 SSVALS(*rparam
,0,desc
.errcode
);
1044 SSVAL(*rparam
,4,succnt
);
1045 SSVAL(*rparam
,6,queuecnt
);
1047 for (i
= 0; i
< queuecnt
; i
++) {
1048 if (queue
) SAFE_FREE(queue
[i
]);
1057 /****************************************************************************
1058 get info level for a server list query
1059 ****************************************************************************/
1060 static BOOL
check_server_info(int uLevel
, char* id
)
1064 if (strcmp(id
,"B16") != 0) return False
;
1067 if (strcmp(id
,"B16BBDz") != 0) return False
;
1075 struct srv_info_struct
1085 /*******************************************************************
1086 get server info lists from the files saved by nmbd. Return the
1088 ******************************************************************/
1089 static int get_server_info(uint32 servertype
,
1090 struct srv_info_struct
**servers
,
1096 BOOL local_list_only
;
1099 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
);
1101 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
1105 /* request for everything is code for request all servers */
1106 if (servertype
== SV_TYPE_ALL
)
1107 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1109 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1111 DEBUG(4,("Servertype search: %8x\n",servertype
));
1113 for (i
=0;lines
[i
];i
++) {
1115 struct srv_info_struct
*s
;
1116 char *ptr
= lines
[i
];
1119 if (!*ptr
) continue;
1121 if (count
== alloced
) {
1122 struct srv_info_struct
*ts
;
1125 ts
= (struct srv_info_struct
*)
1126 Realloc(*servers
,sizeof(**servers
)*alloced
);
1128 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1132 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1134 s
= &(*servers
)[count
];
1136 if (!next_token(&ptr
,s
->name
, NULL
, sizeof(s
->name
))) continue;
1137 if (!next_token(&ptr
,stype
, NULL
, sizeof(stype
))) continue;
1138 if (!next_token(&ptr
,s
->comment
, NULL
, sizeof(s
->comment
))) continue;
1139 if (!next_token(&ptr
,s
->domain
, NULL
, sizeof(s
->domain
))) {
1140 /* this allows us to cope with an old nmbd */
1141 pstrcpy(s
->domain
,global_myworkgroup
);
1144 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1145 DEBUG(4,("r:host file "));
1149 /* Filter the servers/domains we return based on what was asked for. */
1151 /* Check to see if we are being asked for a local list only. */
1152 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1153 DEBUG(4,("r: local list only"));
1157 /* doesn't match up: don't want it */
1158 if (!(servertype
& s
->type
)) {
1159 DEBUG(4,("r:serv type "));
1163 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1164 (s
->type
& SV_TYPE_DOMAIN_ENUM
))
1166 DEBUG(4,("s: dom mismatch "));
1170 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1175 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1176 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1180 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1181 s
->name
, s
->type
, s
->comment
, s
->domain
));
1183 s
->server_added
= True
;
1188 DEBUG(4,("%20s %8x %25s %15s\n",
1189 s
->name
, s
->type
, s
->comment
, s
->domain
));
1193 file_lines_free(lines
);
1198 /*******************************************************************
1199 fill in a server info structure
1200 ******************************************************************/
1201 static int fill_srv_info(struct srv_info_struct
*service
,
1202 int uLevel
, char **buf
, int *buflen
,
1203 char **stringbuf
, int *stringspace
, char *baseaddr
)
1212 case 0: struct_len
= 16; break;
1213 case 1: struct_len
= 26; break;
1223 len
= strlen(service
->comment
)+1;
1227 if (buflen
) *buflen
= struct_len
;
1228 if (stringspace
) *stringspace
= len
;
1229 return struct_len
+ len
;
1234 if (*buflen
< struct_len
) return -1;
1242 p2
= p
+ struct_len
;
1243 l2
= *buflen
- struct_len
;
1245 if (!baseaddr
) baseaddr
= p
;
1250 push_ascii(p
,service
->name
, 15, STR_TERMINATE
);
1254 push_ascii(p
,service
->name
,15, STR_TERMINATE
);
1255 SIVAL(p
,18,service
->type
);
1256 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1257 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1263 *buf
= p
+ struct_len
;
1264 *buflen
-= struct_len
;
1277 static BOOL
srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1279 return(strcmp(s1
->name
,s2
->name
));
1282 /****************************************************************************
1283 view list of servers available (or possibly domains). The info is
1284 extracted from lists saved by nmbd on the local host
1285 ****************************************************************************/
1286 static BOOL
api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1287 int mdrcnt
, int mprcnt
, char **rdata
,
1288 char **rparam
, int *rdata_len
, int *rparam_len
)
1290 char *str1
= param
+2;
1291 char *str2
= skip_string(str1
,1);
1292 char *p
= skip_string(str2
,1);
1293 int uLevel
= SVAL(p
,0);
1294 int buf_len
= SVAL(p
,2);
1295 uint32 servertype
= IVAL(p
,4);
1297 int data_len
, fixed_len
, string_len
;
1298 int f_len
= 0, s_len
= 0;
1299 struct srv_info_struct
*servers
=NULL
;
1300 int counted
=0,total
=0;
1303 BOOL domain_request
;
1306 /* If someone sets all the bits they don't really mean to set
1307 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1310 if (servertype
== SV_TYPE_ALL
)
1311 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1313 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1314 any other bit (they may just set this bit on it's own) they
1315 want all the locally seen servers. However this bit can be
1316 set on its own so set the requested servers to be
1317 ALL - DOMAIN_ENUM. */
1319 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1320 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1322 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1323 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1327 if (!prefix_ok(str1
,"WrLehD")) return False
;
1328 if (!check_server_info(uLevel
,str2
)) return False
;
1330 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1331 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1332 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1334 if (strcmp(str1
, "WrLehDz") == 0) {
1335 pull_ascii_fstring(domain
, p
);
1337 fstrcpy(domain
, global_myworkgroup
);
1340 if (lp_browse_list())
1341 total
= get_server_info(servertype
,&servers
,domain
);
1343 data_len
= fixed_len
= string_len
= 0;
1347 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1350 char *lastname
=NULL
;
1352 for (i
=0;i
<total
;i
++)
1354 struct srv_info_struct
*s
= &servers
[i
];
1355 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1357 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1358 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1359 s
->name
, s
->type
, s
->comment
, s
->domain
));
1361 if (data_len
<= buf_len
) {
1364 string_len
+= s_len
;
1371 *rdata_len
= fixed_len
+ string_len
;
1372 *rdata
= REALLOC(*rdata
,*rdata_len
);
1373 memset(*rdata
,'\0',*rdata_len
);
1375 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1381 char *lastname
=NULL
;
1382 int count2
= counted
;
1383 for (i
= 0; i
< total
&& count2
;i
++)
1385 struct srv_info_struct
*s
= &servers
[i
];
1386 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1388 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1389 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1390 s
->name
, s
->type
, s
->comment
, s
->domain
));
1396 *rparam
= REALLOC(*rparam
,*rparam_len
);
1397 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1399 SSVAL(*rparam
,4,counted
);
1400 SSVAL(*rparam
,6,counted
+missed
);
1404 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1405 domain
,uLevel
,counted
,counted
+missed
));
1410 /****************************************************************************
1411 command 0x34 - suspected of being a "Lookup Names" stub api
1412 ****************************************************************************/
1413 static BOOL
api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1414 int mdrcnt
, int mprcnt
, char **rdata
,
1415 char **rparam
, int *rdata_len
, int *rparam_len
)
1417 char *str1
= param
+2;
1418 char *str2
= skip_string(str1
,1);
1419 char *p
= skip_string(str2
,1);
1420 int uLevel
= SVAL(p
,0);
1421 int buf_len
= SVAL(p
,2);
1425 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1426 str1
, str2
, p
, uLevel
, buf_len
));
1428 if (!prefix_ok(str1
,"zWrLeh")) return False
;
1433 *rparam
= REALLOC(*rparam
,*rparam_len
);
1435 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1437 SSVAL(*rparam
,4,counted
);
1438 SSVAL(*rparam
,6,counted
+missed
);
1443 /****************************************************************************
1444 get info about a share
1445 ****************************************************************************/
1446 static BOOL
check_share_info(int uLevel
, char* id
)
1450 if (strcmp(id
,"B13") != 0) return False
;
1453 if (strcmp(id
,"B13BWz") != 0) return False
;
1456 if (strcmp(id
,"B13BWzWWWzB9B") != 0) return False
;
1459 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False
;
1461 default: return False
;
1466 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1467 char** buf
, int* buflen
,
1468 char** stringbuf
, int* stringspace
, char* baseaddr
)
1477 case 0: struct_len
= 13; break;
1478 case 1: struct_len
= 20; break;
1479 case 2: struct_len
= 40; break;
1480 case 91: struct_len
= 68; break;
1488 if (uLevel
> 0) len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1489 if (uLevel
> 1) len
+= strlen(lp_pathname(snum
)) + 1;
1490 if (buflen
) *buflen
= struct_len
;
1491 if (stringspace
) *stringspace
= len
;
1492 return struct_len
+ len
;
1497 if ((*buflen
) < struct_len
) return -1;
1505 p2
= p
+ struct_len
;
1506 l2
= (*buflen
) - struct_len
;
1508 if (!baseaddr
) baseaddr
= p
;
1510 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1516 type
= STYPE_DISKTREE
;
1517 if (lp_print_ok(snum
)) type
= STYPE_PRINTQ
;
1518 if (strequal("IPC",lp_fstype(snum
))) type
= STYPE_IPC
;
1519 SSVAL(p
,14,type
); /* device type */
1520 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1521 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1526 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1527 SSVALS(p
,22,-1); /* max uses */
1528 SSVAL(p
,24,1); /* current uses */
1529 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1530 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1531 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1536 memset(p
+40,0,SHPWLEN
+2);
1548 (*buf
) = p
+ struct_len
;
1549 (*buflen
) -= struct_len
;
1551 (*stringspace
) = l2
;
1561 static BOOL
api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1562 int mdrcnt
,int mprcnt
,
1563 char **rdata
,char **rparam
,
1564 int *rdata_len
,int *rparam_len
)
1566 char *str1
= param
+2;
1567 char *str2
= skip_string(str1
,1);
1568 char *netname
= skip_string(str2
,1);
1569 char *p
= skip_string(netname
,1);
1570 int uLevel
= SVAL(p
,0);
1571 int snum
= find_service(netname
);
1573 if (snum
< 0) return False
;
1575 /* check it's a supported varient */
1576 if (!prefix_ok(str1
,"zWrLh")) return False
;
1577 if (!check_share_info(uLevel
,str2
)) return False
;
1579 *rdata
= REALLOC(*rdata
,mdrcnt
);
1581 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1582 if (*rdata_len
< 0) return False
;
1585 *rparam
= REALLOC(*rparam
,*rparam_len
);
1586 SSVAL(*rparam
,0,NERR_Success
);
1587 SSVAL(*rparam
,2,0); /* converter word */
1588 SSVAL(*rparam
,4,*rdata_len
);
1593 /****************************************************************************
1594 view list of shares available
1595 ****************************************************************************/
1596 static BOOL
api_RNetShareEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1597 int mdrcnt
,int mprcnt
,
1598 char **rdata
,char **rparam
,
1599 int *rdata_len
,int *rparam_len
)
1601 char *str1
= param
+2;
1602 char *str2
= skip_string(str1
,1);
1603 char *p
= skip_string(str2
,1);
1604 int uLevel
= SVAL(p
,0);
1605 int buf_len
= SVAL(p
,2);
1607 int count
=lp_numservices();
1608 int total
=0,counted
=0;
1609 BOOL missed
= False
;
1611 int data_len
, fixed_len
, string_len
;
1612 int f_len
= 0, s_len
= 0;
1614 if (!prefix_ok(str1
,"WrLeh")) return False
;
1615 if (!check_share_info(uLevel
,str2
)) return False
;
1617 data_len
= fixed_len
= string_len
= 0;
1618 for (i
=0;i
<count
;i
++)
1619 if (lp_browseable(i
) && lp_snum_ok(i
))
1622 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1623 if (data_len
<= buf_len
)
1627 string_len
+= s_len
;
1632 *rdata_len
= fixed_len
+ string_len
;
1633 *rdata
= REALLOC(*rdata
,*rdata_len
);
1634 memset(*rdata
,0,*rdata_len
);
1636 p2
= (*rdata
) + fixed_len
; /* auxillery data (strings) will go here */
1640 for (i
= 0; i
< count
;i
++)
1641 if (lp_browseable(i
) && lp_snum_ok(i
))
1642 if (fill_share_info(conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0)
1646 *rparam
= REALLOC(*rparam
,*rparam_len
);
1647 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1649 SSVAL(*rparam
,4,counted
);
1650 SSVAL(*rparam
,6,total
);
1652 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1653 counted
,total
,uLevel
,
1654 buf_len
,*rdata_len
,mdrcnt
));
1658 /****************************************************************************
1660 ****************************************************************************/
1661 static BOOL
api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1662 int mdrcnt
,int mprcnt
,
1663 char **rdata
,char **rparam
,
1664 int *rdata_len
,int *rparam_len
)
1666 char *str1
= param
+2;
1667 char *str2
= skip_string(str1
,1);
1668 char *p
= skip_string(str2
,1);
1669 int uLevel
= SVAL(p
,0);
1673 char *command
, *cmdname
;
1678 /* check it's a supported varient */
1679 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) return False
;
1680 if (!check_share_info(uLevel
,str2
)) return False
;
1681 if (uLevel
!= 2) return False
;
1683 pull_ascii_fstring(sharename
,data
);
1684 snum
= find_service(sharename
);
1685 if (snum
>= 0) { /* already exists */
1690 /* only support disk share adds */
1691 if (SVAL(data
,14)!=STYPE_DISKTREE
) return False
;
1693 offset
= IVAL(data
, 16);
1694 if (offset
>= mdrcnt
) {
1695 res
= ERRinvalidparam
;
1698 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1700 offset
= IVAL(data
, 26);
1701 if (offset
>= mdrcnt
) {
1702 res
= ERRinvalidparam
;
1705 pull_ascii_pstring(pathname
, offset
? (data
+offset
) : "");
1707 string_replace(sharename
, '"', ' ');
1708 string_replace(pathname
, '"', ' ');
1709 string_replace(comment
, '"', ' ');
1711 cmdname
= lp_add_share_cmd();
1713 if (!cmdname
|| *cmdname
== '\0') return False
;
1715 asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1716 lp_add_share_cmd(), dyn_CONFIGFILE
, sharename
, pathname
, comment
);
1719 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1720 if ((res
= smbrun(command
, NULL
)) != 0) {
1721 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command
, res
));
1727 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
);
1729 } else return False
;
1732 *rparam
= REALLOC(*rparam
,*rparam_len
);
1733 SSVAL(*rparam
,0,NERR_Success
);
1734 SSVAL(*rparam
,2,0); /* converter word */
1735 SSVAL(*rparam
,4,*rdata_len
);
1742 *rparam
= REALLOC(*rparam
,*rparam_len
);
1744 SSVAL(*rparam
,0,res
);
1750 /****************************************************************************
1751 view list of groups available
1752 ****************************************************************************/
1753 static BOOL
api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1754 int mdrcnt
,int mprcnt
,
1755 char **rdata
,char **rparam
,
1756 int *rdata_len
,int *rparam_len
)
1758 char *str1
= param
+2;
1759 char *str2
= skip_string(str1
,1);
1760 char *p
= skip_string(str2
,1);
1761 int uLevel
= SVAL(p
,0);
1765 if (!prefix_ok(str1
,"WrLeh")) return False
;
1767 /* check it's a supported variant */
1777 if (strcmp(p2
,str2
) != 0) return False
;
1779 *rdata_len
= mdrcnt
+ 1024;
1780 *rdata
= REALLOC(*rdata
,*rdata_len
);
1782 SSVAL(*rparam
,0,NERR_Success
);
1783 SSVAL(*rparam
,2,0); /* converter word */
1787 /* XXXX we need a real SAM database some day */
1788 pstrcpy(p
,"Users"); p
+= 21; count
++;
1789 pstrcpy(p
,"Domain Users"); p
+= 21; count
++;
1790 pstrcpy(p
,"Guests"); p
+= 21; count
++;
1791 pstrcpy(p
,"Domain Guests"); p
+= 21; count
++;
1793 *rdata_len
= PTR_DIFF(p
,*rdata
);
1796 *rparam
= REALLOC(*rparam
,*rparam_len
);
1798 SSVAL(*rparam
,4,count
); /* is this right?? */
1799 SSVAL(*rparam
,6,count
); /* is this right?? */
1801 DEBUG(3,("api_RNetGroupEnum gave %d entries\n", count
));
1806 /****************************************************************************
1807 view list of groups available
1808 ****************************************************************************/
1809 static BOOL
api_RNetUserEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1810 int mdrcnt
,int mprcnt
,
1811 char **rdata
,char **rparam
,
1812 int *rdata_len
,int *rparam_len
)
1814 char *str1
= param
+2;
1815 char *str2
= skip_string(str1
,1);
1816 char *p
= skip_string(str2
,1);
1817 int uLevel
= SVAL(p
,0);
1821 if (!prefix_ok(str1
,"WrLeh")) return False
;
1823 /* check it's a supported variant */
1833 if (strcmp(p2
,str2
) != 0) return False
;
1835 *rdata_len
= mdrcnt
+ 1024;
1836 *rdata
= REALLOC(*rdata
,*rdata_len
);
1838 SSVAL(*rparam
,0,NERR_Success
);
1839 SSVAL(*rparam
,2,0); /* converter word */
1843 /* XXXX we need a real SAM database some day */
1844 pstrcpy(p
,"Users"); p
+= 21; count
++;
1845 pstrcpy(p
,"Domain Users"); p
+= 21; count
++;
1846 pstrcpy(p
,"Guests"); p
+= 21; count
++;
1847 pstrcpy(p
,"Domain Guests"); p
+= 21; count
++;
1849 *rdata_len
= PTR_DIFF(p
,*rdata
);
1852 *rparam
= REALLOC(*rparam
,*rparam_len
);
1854 SSVAL(*rparam
,4,count
); /* is this right?? */
1855 SSVAL(*rparam
,6,count
); /* is this right?? */
1857 DEBUG(3,("api_RNetUserEnum gave %d entries\n", count
));
1864 /****************************************************************************
1865 get the time of day info
1866 ****************************************************************************/
1867 static BOOL
api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1868 int mdrcnt
,int mprcnt
,
1869 char **rdata
,char **rparam
,
1870 int *rdata_len
,int *rparam_len
)
1874 *rparam
= REALLOC(*rparam
,*rparam_len
);
1877 *rdata
= REALLOC(*rdata
,*rdata_len
);
1879 SSVAL(*rparam
,0,NERR_Success
);
1880 SSVAL(*rparam
,2,0); /* converter word */
1886 time_t unixdate
= time(NULL
);
1888 put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
1889 by NT in a "net time" operation,
1890 it seems to ignore the one below */
1892 /* the client expects to get localtime, not GMT, in this bit
1893 (I think, this needs testing) */
1894 t
= LocalTime(&unixdate
);
1896 SIVAL(p
,4,0); /* msecs ? */
1897 CVAL(p
,8) = t
->tm_hour
;
1898 CVAL(p
,9) = t
->tm_min
;
1899 CVAL(p
,10) = t
->tm_sec
;
1900 CVAL(p
,11) = 0; /* hundredths of seconds */
1901 SSVALS(p
,12,TimeDiff(unixdate
)/60); /* timezone in minutes from GMT */
1902 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
1903 CVAL(p
,16) = t
->tm_mday
;
1904 CVAL(p
,17) = t
->tm_mon
+ 1;
1905 SSVAL(p
,18,1900+t
->tm_year
);
1906 CVAL(p
,20) = t
->tm_wday
;
1913 /****************************************************************************
1914 Set the user password.
1915 *****************************************************************************/
1917 static BOOL
api_SetUserPassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1918 int mdrcnt
,int mprcnt
,
1919 char **rdata
,char **rparam
,
1920 int *rdata_len
,int *rparam_len
)
1922 char *p
= skip_string(param
+2,2);
1924 fstring pass1
,pass2
;
1926 struct passwd
*passwd
;
1928 pull_ascii_fstring(user
,p
);
1930 p
= skip_string(p
,1);
1932 memset(pass1
,'\0',sizeof(pass1
));
1933 memset(pass2
,'\0',sizeof(pass2
));
1935 memcpy(pass2
,p
+16,16);
1938 *rparam
= REALLOC(*rparam
,*rparam_len
);
1942 SSVAL(*rparam
,0,NERR_badpass
);
1943 SSVAL(*rparam
,2,0); /* converter word */
1945 DEBUG(3,("Set password for <%s>\n",user
));
1948 * Pass the user through the NT -> unix user mapping
1952 (void)map_username(user
);
1955 * Do any UNIX username case mangling.
1957 passwd
= Get_Pwnam_Modify( user
);
1960 * Attempt to verify the old password against smbpasswd entries
1961 * Win98 clients send old and new password in plaintext for this call.
1965 fstring saved_pass2
;
1966 SAM_ACCOUNT
*sampass
=NULL
;
1969 * Save the new password as change_oem_password overwrites it
1973 fstrcpy(saved_pass2
, pass2
);
1975 if (check_plaintext_password(user
,pass1
,strlen(pass1
),&sampass
) &&
1976 change_oem_password(sampass
,pass2
))
1978 SSVAL(*rparam
,0,NERR_Success
);
1981 * If unix password sync was requested, attempt to change
1982 * the /etc/passwd database also. Return failure if this cannot
1986 if(lp_unix_password_sync() && !chgpasswd(user
,pass1
,saved_pass2
,False
))
1987 SSVAL(*rparam
,0,NERR_badpass
);
1989 pdb_free_sam(&sampass
);
1994 * If the above failed, attempt the plaintext password change.
1995 * This tests against the /etc/passwd database only.
1998 if(SVAL(*rparam
,0) != NERR_Success
)
2000 if NT_STATUS_IS_OK(pass_check(passwd
, user
, pass1
,
2001 strlen(pass1
), NULL
, False
))
2003 if (chgpasswd(user
,pass1
,pass2
,False
)) {
2004 SSVAL(*rparam
,0,NERR_Success
);
2010 * If the plaintext change failed, attempt
2011 * the old encrypted method. NT will generate this
2012 * after trying the samr method. Note that this
2013 * method is done as a last resort as this
2014 * password change method loses the NT password hash
2015 * and cannot change the UNIX password as no plaintext
2019 if(SVAL(*rparam
,0) != NERR_Success
)
2021 SAM_ACCOUNT
*hnd
= NULL
;
2023 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
) &&
2024 change_lanman_password(hnd
,(unsigned char *)pass1
,(unsigned char *)pass2
))
2026 SSVAL(*rparam
,0,NERR_Success
);
2032 memset((char *)pass1
,'\0',sizeof(fstring
));
2033 memset((char *)pass2
,'\0',sizeof(fstring
));
2038 /****************************************************************************
2039 Set the user password (SamOEM version - gets plaintext).
2040 ****************************************************************************/
2042 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2043 int mdrcnt
,int mprcnt
,
2044 char **rdata
,char **rparam
,
2045 int *rdata_len
,int *rparam_len
)
2048 char *p
= param
+ 2;
2050 *rparam
= REALLOC(*rparam
,*rparam_len
);
2054 SSVAL(*rparam
,0,NERR_badpass
);
2057 * Check the parameter definition is correct.
2059 if(!strequal(param
+ 2, "zsT")) {
2060 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param
+ 2));
2063 p
= skip_string(p
, 1);
2065 if(!strequal(p
, "B516B16")) {
2066 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2069 p
= skip_string(p
,1);
2071 p
+= pull_ascii_fstring(user
,p
);
2073 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2076 * Pass the user through the NT -> unix user mapping
2080 (void)map_username(user
);
2083 * Do any UNIX username case mangling.
2085 (void)Get_Pwnam_Modify( user
);
2087 if (pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
))
2089 SSVAL(*rparam
,0,NERR_Success
);
2095 /****************************************************************************
2098 ****************************************************************************/
2099 static BOOL
api_RDosPrintJobDel(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 int function
= SVAL(param
,0);
2105 char *str1
= param
+2;
2106 char *str2
= skip_string(str1
,1);
2107 char *p
= skip_string(str2
,1);
2109 extern struct current_user current_user
;
2110 WERROR werr
= WERR_OK
;
2114 /* check it's a supported varient */
2115 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2119 *rparam
= REALLOC(*rparam
,*rparam_len
);
2122 if (!print_job_exists(jobid
)) {
2123 errcode
= NERR_JobNotFound
;
2127 errcode
= NERR_notsupported
;
2130 case 81: /* delete */
2131 if (print_job_delete(¤t_user
, jobid
, &werr
))
2132 errcode
= NERR_Success
;
2134 case 82: /* pause */
2135 if (print_job_pause(¤t_user
, jobid
, &werr
))
2136 errcode
= NERR_Success
;
2138 case 83: /* resume */
2139 if (print_job_resume(¤t_user
, jobid
, &werr
))
2140 errcode
= NERR_Success
;
2144 if (!W_ERROR_IS_OK(werr
))
2145 errcode
= W_ERROR_V(werr
);
2148 SSVAL(*rparam
,0,errcode
);
2149 SSVAL(*rparam
,2,0); /* converter word */
2154 /****************************************************************************
2155 Purge a print queue - or pause or resume it.
2156 ****************************************************************************/
2157 static BOOL
api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2158 int mdrcnt
,int mprcnt
,
2159 char **rdata
,char **rparam
,
2160 int *rdata_len
,int *rparam_len
)
2162 int function
= SVAL(param
,0);
2163 char *str1
= param
+2;
2164 char *str2
= skip_string(str1
,1);
2165 char *QueueName
= skip_string(str2
,1);
2166 int errcode
= NERR_notsupported
;
2168 WERROR werr
= WERR_OK
;
2169 extern struct current_user current_user
;
2171 /* check it's a supported varient */
2172 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2176 *rparam
= REALLOC(*rparam
,*rparam_len
);
2179 snum
= print_queue_snum(QueueName
);
2182 errcode
= NERR_JobNotFound
;
2187 case 74: /* Pause queue */
2188 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2190 case 75: /* Resume queue */
2191 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2193 case 103: /* Purge */
2194 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2198 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2201 SSVAL(*rparam
,0,errcode
);
2202 SSVAL(*rparam
,2,0); /* converter word */
2208 /****************************************************************************
2209 set the property of a print job (undocumented?)
2210 ? function = 0xb -> set name of print job
2211 ? function = 0x6 -> move print job up/down
2212 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2213 or <WWsTP> <WB21BB16B10zWWzDDz>
2214 ****************************************************************************/
2215 static int check_printjob_info(struct pack_desc
* desc
,
2216 int uLevel
, char* id
)
2218 desc
->subformat
= NULL
;
2220 case 0: desc
->format
= "W"; break;
2221 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2222 case 2: desc
->format
= "WWzWWDDzz"; break;
2223 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2224 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2225 default: return False
;
2227 if (strcmp(desc
->format
,id
) != 0) return False
;
2231 static BOOL
api_PrintJobInfo(connection_struct
*conn
,uint16 vuid
,char *param
,char *data
,
2232 int mdrcnt
,int mprcnt
,
2233 char **rdata
,char **rparam
,
2234 int *rdata_len
,int *rparam_len
)
2236 struct pack_desc desc
;
2237 char *str1
= param
+2;
2238 char *str2
= skip_string(str1
,1);
2239 char *p
= skip_string(str2
,1);
2241 int uLevel
= SVAL(p
,2);
2242 int function
= SVAL(p
,4);
2247 *rparam
= REALLOC(*rparam
,*rparam_len
);
2251 /* check it's a supported varient */
2252 if ((strcmp(str1
,"WWsTP")) ||
2253 (!check_printjob_info(&desc
,uLevel
,str2
)))
2256 if (!print_job_exists(jobid
)) {
2257 errcode
=NERR_JobNotFound
;
2261 errcode
= NERR_notsupported
;
2265 /* change job place in the queue,
2266 data gives the new place */
2267 place
= SVAL(data
,0);
2268 if (print_job_set_place(jobid
, place
)) {
2269 errcode
=NERR_Success
;
2274 /* change print job name, data gives the name */
2275 if (print_job_set_name(jobid
, data
)) {
2276 errcode
=NERR_Success
;
2285 SSVALS(*rparam
,0,errcode
);
2286 SSVAL(*rparam
,2,0); /* converter word */
2292 /****************************************************************************
2293 get info about the server
2294 ****************************************************************************/
2295 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2296 int mdrcnt
,int mprcnt
,
2297 char **rdata
,char **rparam
,
2298 int *rdata_len
,int *rparam_len
)
2300 char *str1
= param
+2;
2301 char *str2
= skip_string(str1
,1);
2302 char *p
= skip_string(str2
,1);
2303 int uLevel
= SVAL(p
,0);
2307 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2309 /* check it's a supported varient */
2310 if (!prefix_ok(str1
,"WrLh")) return False
;
2313 if (strcmp(str2
,"B16") != 0) return False
;
2317 if (strcmp(str2
,"B16BBDz") != 0) return False
;
2321 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2326 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2331 if (strcmp(str2
,"DN") != 0) return False
;
2335 if (strcmp(str2
,"B16BBDzWWzzz") != 0) return False
;
2338 default: return False
;
2341 *rdata_len
= mdrcnt
;
2342 *rdata
= REALLOC(*rdata
,*rdata_len
);
2345 p2
= p
+ struct_len
;
2347 srvstr_push(NULL
, p
,local_machine
,16,
2348 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2353 struct srv_info_struct
*servers
=NULL
;
2356 uint32 servertype
= lp_default_server_announce();
2358 pstrcpy(comment
,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH
));
2360 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,global_myworkgroup
))>0) {
2361 for (i
=0;i
<count
;i
++)
2362 if (strequal(servers
[i
].name
,local_machine
))
2364 servertype
= servers
[i
].type
;
2365 pstrcpy(comment
,servers
[i
].comment
);
2370 SCVAL(p
,0,lp_major_announce_version());
2371 SCVAL(p
,1,lp_minor_announce_version());
2372 SIVAL(p
,2,servertype
);
2374 if (mdrcnt
== struct_len
) {
2377 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2378 standard_sub_conn(conn
,comment
);
2379 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2380 p2
= skip_string(p2
,1);
2385 return False
; /* not yet implemented */
2388 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2391 *rparam
= REALLOC(*rparam
,*rparam_len
);
2392 SSVAL(*rparam
,0,NERR_Success
);
2393 SSVAL(*rparam
,2,0); /* converter word */
2394 SSVAL(*rparam
,4,*rdata_len
);
2400 /****************************************************************************
2401 get info about the server
2402 ****************************************************************************/
2403 static BOOL
api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2404 int mdrcnt
,int mprcnt
,
2405 char **rdata
,char **rparam
,
2406 int *rdata_len
,int *rparam_len
)
2408 char *str1
= param
+2;
2409 char *str2
= skip_string(str1
,1);
2410 char *p
= skip_string(str2
,1);
2412 extern userdom_struct current_user_info
;
2413 int level
= SVAL(p
,0);
2415 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2418 *rparam
= REALLOC(*rparam
,*rparam_len
);
2420 /* check it's a supported varient */
2421 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz")))
2424 *rdata_len
= mdrcnt
+ 1024;
2425 *rdata
= REALLOC(*rdata
,*rdata_len
);
2427 SSVAL(*rparam
,0,NERR_Success
);
2428 SSVAL(*rparam
,2,0); /* converter word */
2434 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2435 pstrcpy(p2
,local_machine
);
2437 p2
= skip_string(p2
,1);
2440 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2441 pstrcpy(p2
,current_user_info
.smb_name
);
2442 p2
= skip_string(p2
,1);
2445 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2446 pstrcpy(p2
,global_myworkgroup
);
2448 p2
= skip_string(p2
,1);
2451 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2452 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2455 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2456 pstrcpy(p2
,global_myworkgroup
); /* don't know. login domain?? */
2457 p2
= skip_string(p2
,1);
2460 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
2462 p2
= skip_string(p2
,1);
2465 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2467 SSVAL(*rparam
,4,*rdata_len
);
2472 /****************************************************************************
2473 get info about a user
2475 struct user_info_11 {
2476 char usri11_name[21]; 0-20
2478 char *usri11_comment; 22-25
2479 char *usri11_usr_comment; 26-29
2480 unsigned short usri11_priv; 30-31
2481 unsigned long usri11_auth_flags; 32-35
2482 long usri11_password_age; 36-39
2483 char *usri11_homedir; 40-43
2484 char *usri11_parms; 44-47
2485 long usri11_last_logon; 48-51
2486 long usri11_last_logoff; 52-55
2487 unsigned short usri11_bad_pw_count; 56-57
2488 unsigned short usri11_num_logons; 58-59
2489 char *usri11_logon_server; 60-63
2490 unsigned short usri11_country_code; 64-65
2491 char *usri11_workstations; 66-69
2492 unsigned long usri11_max_storage; 70-73
2493 unsigned short usri11_units_per_week; 74-75
2494 unsigned char *usri11_logon_hours; 76-79
2495 unsigned short usri11_code_page; 80-81
2500 usri11_name specifies the user name for which information is retireved
2502 usri11_pad aligns the next data structure element to a word boundary
2504 usri11_comment is a null terminated ASCII comment
2506 usri11_user_comment is a null terminated ASCII comment about the user
2508 usri11_priv specifies the level of the privilege assigned to the user.
2509 The possible values are:
2511 Name Value Description
2512 USER_PRIV_GUEST 0 Guest privilege
2513 USER_PRIV_USER 1 User privilege
2514 USER_PRV_ADMIN 2 Administrator privilege
2516 usri11_auth_flags specifies the account operator privileges. The
2517 possible values are:
2519 Name Value Description
2520 AF_OP_PRINT 0 Print operator
2523 Leach, Naik [Page 28]
2527 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2530 AF_OP_COMM 1 Communications operator
2531 AF_OP_SERVER 2 Server operator
2532 AF_OP_ACCOUNTS 3 Accounts operator
2535 usri11_password_age specifies how many seconds have elapsed since the
2536 password was last changed.
2538 usri11_home_dir points to a null terminated ASCII string that contains
2539 the path name of the user's home directory.
2541 usri11_parms points to a null terminated ASCII string that is set
2542 aside for use by applications.
2544 usri11_last_logon specifies the time when the user last logged on.
2545 This value is stored as the number of seconds elapsed since
2546 00:00:00, January 1, 1970.
2548 usri11_last_logoff specifies the time when the user last logged off.
2549 This value is stored as the number of seconds elapsed since
2550 00:00:00, January 1, 1970. A value of 0 means the last logoff
2553 usri11_bad_pw_count specifies the number of incorrect passwords
2554 entered since the last successful logon.
2556 usri11_log1_num_logons specifies the number of times this user has
2557 logged on. A value of -1 means the number of logons is unknown.
2559 usri11_logon_server points to a null terminated ASCII string that
2560 contains the name of the server to which logon requests are sent.
2561 A null string indicates logon requests should be sent to the
2564 usri11_country_code specifies the country code for the user's language
2567 usri11_workstations points to a null terminated ASCII string that
2568 contains the names of workstations the user may log on from.
2569 There may be up to 8 workstations, with the names separated by
2570 commas. A null strings indicates there are no restrictions.
2572 usri11_max_storage specifies the maximum amount of disk space the user
2573 can occupy. A value of 0xffffffff indicates there are no
2576 usri11_units_per_week specifies the equal number of time units into
2577 which a week is divided. This value must be equal to 168.
2579 usri11_logon_hours points to a 21 byte (168 bits) string that
2580 specifies the time during which the user can log on. Each bit
2581 represents one unique hour in a week. The first bit (bit 0, word
2582 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2586 Leach, Naik [Page 29]
2590 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2593 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2594 are no restrictions.
2596 usri11_code_page specifies the code page for the user's language of
2599 All of the pointers in this data structure need to be treated
2600 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2601 to be ignored. The converter word returned in the parameters section
2602 needs to be subtracted from the lower 16 bits to calculate an offset
2603 into the return buffer where this ASCII string resides.
2605 There is no auxiliary data in the response.
2607 ****************************************************************************/
2609 #define usri11_name 0
2610 #define usri11_pad 21
2611 #define usri11_comment 22
2612 #define usri11_usr_comment 26
2613 #define usri11_full_name 30
2614 #define usri11_priv 34
2615 #define usri11_auth_flags 36
2616 #define usri11_password_age 40
2617 #define usri11_homedir 44
2618 #define usri11_parms 48
2619 #define usri11_last_logon 52
2620 #define usri11_last_logoff 56
2621 #define usri11_bad_pw_count 60
2622 #define usri11_num_logons 62
2623 #define usri11_logon_server 64
2624 #define usri11_country_code 68
2625 #define usri11_workstations 70
2626 #define usri11_max_storage 74
2627 #define usri11_units_per_week 78
2628 #define usri11_logon_hours 80
2629 #define usri11_code_page 84
2630 #define usri11_end 86
2632 #define USER_PRIV_GUEST 0
2633 #define USER_PRIV_USER 1
2634 #define USER_PRIV_ADMIN 2
2636 #define AF_OP_PRINT 0
2637 #define AF_OP_COMM 1
2638 #define AF_OP_SERVER 2
2639 #define AF_OP_ACCOUNTS 3
2642 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2643 int mdrcnt
,int mprcnt
,
2644 char **rdata
,char **rparam
,
2645 int *rdata_len
,int *rparam_len
)
2647 char *str1
= param
+2;
2648 char *str2
= skip_string(str1
,1);
2649 char *UserName
= skip_string(str2
,1);
2650 char *p
= skip_string(UserName
,1);
2651 int uLevel
= SVAL(p
,0);
2654 /* get NIS home of a previously validated user - simeon */
2655 /* With share level security vuid will always be zero.
2656 Don't depend on vuser being non-null !!. JRA */
2657 user_struct
*vuser
= get_valid_user_struct(vuid
);
2659 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
2660 vuser
->user
.unix_name
));
2663 *rparam
= REALLOC(*rparam
,*rparam_len
);
2665 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
2667 /* check it's a supported variant */
2668 if (strcmp(str1
,"zWrLh") != 0) return False
;
2671 case 0: p2
= "B21"; break;
2672 case 1: p2
= "B21BB16DWzzWz"; break;
2673 case 2: p2
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2674 case 10: p2
= "B21Bzzz"; break;
2675 case 11: p2
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2676 default: return False
;
2679 if (strcmp(p2
,str2
) != 0) return False
;
2681 *rdata_len
= mdrcnt
+ 1024;
2682 *rdata
= REALLOC(*rdata
,*rdata_len
);
2684 SSVAL(*rparam
,0,NERR_Success
);
2685 SSVAL(*rparam
,2,0); /* converter word */
2688 p2
= p
+ usri11_end
;
2691 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
2695 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
2700 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
2701 pstrcpy(p2
,"Comment");
2702 p2
= skip_string(p2
,1);
2704 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
2705 pstrcpy(p2
,"UserComment");
2706 p2
= skip_string(p2
,1);
2708 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2709 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
2710 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2711 p2
= skip_string(p2
,1);
2714 if (uLevel
== 11) /* modelled after NTAS 3.51 reply */
2716 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2717 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
2718 SIVALS(p
,usri11_password_age
,-1); /* password age */
2719 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
2720 pstrcpy(p2
, lp_logon_home());
2721 standard_sub_conn(conn
, p2
);
2722 p2
= skip_string(p2
,1);
2723 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
2725 p2
= skip_string(p2
,1);
2726 SIVAL(p
,usri11_last_logon
,0); /* last logon */
2727 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
2728 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
2729 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
2730 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
2731 pstrcpy(p2
,"\\\\*");
2732 p2
= skip_string(p2
,1);
2733 SSVAL(p
,usri11_country_code
,0); /* country code */
2735 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
2737 p2
= skip_string(p2
,1);
2739 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
2740 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
2741 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
2743 /* a simple way to get logon hours at all times. */
2745 SCVAL(p2
,21,0); /* fix zero termination */
2746 p2
= skip_string(p2
,1);
2748 SSVAL(p
,usri11_code_page
,0); /* code page */
2750 if (uLevel
== 1 || uLevel
== 2)
2752 memset(p
+22,' ',16); /* password */
2753 SIVALS(p
,38,-1); /* password age */
2755 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2756 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
2757 pstrcpy(p2
,lp_logon_home());
2758 standard_sub_conn(conn
, p2
);
2759 p2
= skip_string(p2
,1);
2760 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
2762 SSVAL(p
,52,0); /* flags */
2763 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
2764 pstrcpy(p2
,lp_logon_script());
2765 standard_sub_conn( conn
, p2
);
2766 p2
= skip_string(p2
,1);
2769 SIVAL(p
,60,0); /* auth_flags */
2770 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
2771 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2772 p2
= skip_string(p2
,1);
2773 SIVAL(p
,68,0); /* urs_comment */
2774 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
2776 p2
= skip_string(p2
,1);
2777 SIVAL(p
,76,0); /* workstations */
2778 SIVAL(p
,80,0); /* last_logon */
2779 SIVAL(p
,84,0); /* last_logoff */
2780 SIVALS(p
,88,-1); /* acct_expires */
2781 SIVALS(p
,92,-1); /* max_storage */
2782 SSVAL(p
,96,168); /* units_per_week */
2783 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
2786 SSVALS(p
,102,-1); /* bad_pw_count */
2787 SSVALS(p
,104,-1); /* num_logons */
2788 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
2789 pstrcpy(p2
,"\\\\%L");
2790 standard_sub_conn(conn
, p2
);
2791 p2
= skip_string(p2
,1);
2792 SSVAL(p
,110,49); /* country_code */
2793 SSVAL(p
,112,860); /* code page */
2797 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2799 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
2804 /*******************************************************************
2805 get groups that a user is a member of
2806 ******************************************************************/
2807 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2808 int mdrcnt
,int mprcnt
,
2809 char **rdata
,char **rparam
,
2810 int *rdata_len
,int *rparam_len
)
2812 char *str1
= param
+2;
2813 char *str2
= skip_string(str1
,1);
2814 char *UserName
= skip_string(str2
,1);
2815 char *p
= skip_string(UserName
,1);
2816 int uLevel
= SVAL(p
,0);
2821 *rparam
= REALLOC(*rparam
,*rparam_len
);
2823 /* check it's a supported varient */
2824 if (strcmp(str1
,"zWrLeh") != 0) return False
;
2826 case 0: p2
= "B21"; break;
2827 default: return False
;
2829 if (strcmp(p2
,str2
) != 0) return False
;
2831 *rdata_len
= mdrcnt
+ 1024;
2832 *rdata
= REALLOC(*rdata
,*rdata_len
);
2834 SSVAL(*rparam
,0,NERR_Success
);
2835 SSVAL(*rparam
,2,0); /* converter word */
2839 /* XXXX we need a real SAM database some day */
2840 pstrcpy(p
,"Users"); p
+= 21; count
++;
2841 pstrcpy(p
,"Domain Users"); p
+= 21; count
++;
2842 pstrcpy(p
,"Guests"); p
+= 21; count
++;
2843 pstrcpy(p
,"Domain Guests"); p
+= 21; count
++;
2845 *rdata_len
= PTR_DIFF(p
,*rdata
);
2847 SSVAL(*rparam
,4,count
); /* is this right?? */
2848 SSVAL(*rparam
,6,count
); /* is this right?? */
2854 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2855 int mdrcnt
,int mprcnt
,
2856 char **rdata
,char **rparam
,
2857 int *rdata_len
,int *rparam_len
)
2859 char *str1
= param
+2;
2860 char *str2
= skip_string(str1
,1);
2861 char *p
= skip_string(str2
,1);
2863 struct pack_desc desc
;
2869 memset((char *)&desc
,'\0',sizeof(desc
));
2871 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
2873 /* check it's a supported varient */
2874 if (strcmp(str1
,"OOWb54WrLh") != 0) return False
;
2875 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) return False
;
2876 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2878 desc
.buflen
= mdrcnt
;
2879 desc
.subformat
= NULL
;
2882 if (init_package(&desc
,1,0))
2884 PACKI(&desc
,"W",0); /* code */
2885 PACKS(&desc
,"B21",name
); /* eff. name */
2886 PACKS(&desc
,"B",""); /* pad */
2888 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2889 PACKI(&desc
,"D",0); /* auth flags XXX */
2890 PACKI(&desc
,"W",0); /* num logons */
2891 PACKI(&desc
,"W",0); /* bad pw count */
2892 PACKI(&desc
,"D",0); /* last logon */
2893 PACKI(&desc
,"D",-1); /* last logoff */
2894 PACKI(&desc
,"D",-1); /* logoff time */
2895 PACKI(&desc
,"D",-1); /* kickoff time */
2896 PACKI(&desc
,"D",0); /* password age */
2897 PACKI(&desc
,"D",0); /* password can change */
2898 PACKI(&desc
,"D",-1); /* password must change */
2901 fstrcpy(mypath
,"\\\\");
2902 fstrcat(mypath
,local_machine
);
2904 PACKS(&desc
,"z",mypath
); /* computer */
2906 PACKS(&desc
,"z",global_myworkgroup
);/* domain */
2908 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2909 /* made sure all macros are fully substituted and available */
2911 pstring logon_script
;
2912 pstrcpy(logon_script
,lp_logon_script());
2913 standard_sub_conn( conn
, logon_script
);
2914 PACKS(&desc
,"z", logon_script
); /* script path */
2916 /* End of JHT mods */
2918 PACKI(&desc
,"D",0x00000000); /* reserved */
2921 *rdata_len
= desc
.usedlen
;
2923 *rparam
= REALLOC(*rparam
,*rparam_len
);
2924 SSVALS(*rparam
,0,desc
.errcode
);
2926 SSVAL(*rparam
,4,desc
.neededlen
);
2928 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
2933 /****************************************************************************
2934 api_WAccessGetUserPerms
2935 ****************************************************************************/
2936 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2937 int mdrcnt
,int mprcnt
,
2938 char **rdata
,char **rparam
,
2939 int *rdata_len
,int *rparam_len
)
2941 char *str1
= param
+2;
2942 char *str2
= skip_string(str1
,1);
2943 char *user
= skip_string(str2
,1);
2944 char *resource
= skip_string(user
,1);
2946 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
2948 /* check it's a supported varient */
2949 if (strcmp(str1
,"zzh") != 0) return False
;
2950 if (strcmp(str2
,"") != 0) return False
;
2953 *rparam
= REALLOC(*rparam
,*rparam_len
);
2954 SSVALS(*rparam
,0,0); /* errorcode */
2955 SSVAL(*rparam
,2,0); /* converter word */
2956 SSVAL(*rparam
,4,0x7f); /* permission flags */
2961 /****************************************************************************
2962 api_WPrintJobEnumerate
2963 ****************************************************************************/
2964 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2965 int mdrcnt
,int mprcnt
,
2966 char **rdata
,char **rparam
,
2967 int *rdata_len
,int *rparam_len
)
2969 char *str1
= param
+2;
2970 char *str2
= skip_string(str1
,1);
2971 char *p
= skip_string(str2
,1);
2977 struct pack_desc desc
;
2978 print_queue_struct
*queue
=NULL
;
2979 print_status_struct status
;
2984 memset((char *)&desc
,'\0',sizeof(desc
));
2985 memset((char *)&status
,'\0',sizeof(status
));
2987 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
2989 /* check it's a supported varient */
2990 if (strcmp(str1
,"WWrLh") != 0) return False
;
2991 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2994 snum
= print_job_snum(job
);
2996 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2998 count
= print_queue_status(snum
,&queue
,&status
);
2999 for (i
= 0; i
< count
; i
++) {
3000 if (queue
[i
].job
== job
) break;
3004 *rdata
= REALLOC(*rdata
,mdrcnt
);
3006 desc
.buflen
= mdrcnt
;
3009 * Don't return data but need to get correct length
3010 * init_package will return wrong size if buflen=0
3012 desc
.buflen
= getlen(desc
.format
);
3013 desc
.base
= tmpdata
= (char *)malloc ( desc
.buflen
);
3016 if (init_package(&desc
,1,0)) {
3018 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3019 *rdata_len
= desc
.usedlen
;
3022 desc
.errcode
= NERR_JobNotFound
;
3028 *rparam
= REALLOC(*rparam
,*rparam_len
);
3029 SSVALS(*rparam
,0,desc
.errcode
);
3031 SSVAL(*rparam
,4,desc
.neededlen
);
3036 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3040 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3041 int mdrcnt
,int mprcnt
,
3042 char **rdata
,char **rparam
,
3043 int *rdata_len
,int *rparam_len
)
3045 char *str1
= param
+2;
3046 char *str2
= skip_string(str1
,1);
3047 char *p
= skip_string(str2
,1);
3053 struct pack_desc desc
;
3054 print_queue_struct
*queue
=NULL
;
3055 print_status_struct status
;
3057 memset((char *)&desc
,'\0',sizeof(desc
));
3058 memset((char *)&status
,'\0',sizeof(status
));
3060 p
= skip_string(p
,1);
3063 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3065 /* check it's a supported varient */
3066 if (strcmp(str1
,"zWrLeh") != 0) return False
;
3067 if (uLevel
> 2) return False
; /* defined only for uLevel 0,1,2 */
3068 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
3070 snum
= lp_servicenumber(name
);
3071 if (snum
< 0 && pcap_printername_ok(name
,NULL
)) {
3072 int pnum
= lp_servicenumber(PRINTERS_NAME
);
3074 lp_add_printer(name
,pnum
);
3075 snum
= lp_servicenumber(name
);
3079 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
3081 count
= print_queue_status(snum
,&queue
,&status
);
3082 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3084 desc
.buflen
= mdrcnt
;
3086 if (init_package(&desc
,count
,0)) {
3088 for (i
= 0; i
< count
; i
++) {
3089 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3090 if (desc
.errcode
== NERR_Success
) succnt
= i
+1;
3094 *rdata_len
= desc
.usedlen
;
3097 *rparam
= REALLOC(*rparam
,*rparam_len
);
3098 SSVALS(*rparam
,0,desc
.errcode
);
3100 SSVAL(*rparam
,4,succnt
);
3101 SSVAL(*rparam
,6,count
);
3105 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3109 static int check_printdest_info(struct pack_desc
* desc
,
3110 int uLevel
, char* id
)
3112 desc
->subformat
= NULL
;
3114 case 0: desc
->format
= "B9"; break;
3115 case 1: desc
->format
= "B9B21WWzW"; break;
3116 case 2: desc
->format
= "z"; break;
3117 case 3: desc
->format
= "zzzWWzzzWW"; break;
3118 default: return False
;
3120 if (strcmp(desc
->format
,id
) != 0) return False
;
3124 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3125 struct pack_desc
* desc
)
3128 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3129 buf
[sizeof(buf
)-1] = 0;
3132 PACKS(desc
,"B9",buf
); /* szName */
3134 PACKS(desc
,"B21",""); /* szUserName */
3135 PACKI(desc
,"W",0); /* uJobId */
3136 PACKI(desc
,"W",0); /* fsStatus */
3137 PACKS(desc
,"z",""); /* pszStatus */
3138 PACKI(desc
,"W",0); /* time */
3141 if (uLevel
== 2 || uLevel
== 3) {
3142 PACKS(desc
,"z",buf
); /* pszPrinterName */
3144 PACKS(desc
,"z",""); /* pszUserName */
3145 PACKS(desc
,"z",""); /* pszLogAddr */
3146 PACKI(desc
,"W",0); /* uJobId */
3147 PACKI(desc
,"W",0); /* fsStatus */
3148 PACKS(desc
,"z",""); /* pszStatus */
3149 PACKS(desc
,"z",""); /* pszComment */
3150 PACKS(desc
,"z","NULL"); /* pszDrivers */
3151 PACKI(desc
,"W",0); /* time */
3152 PACKI(desc
,"W",0); /* pad1 */
3157 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3158 int mdrcnt
,int mprcnt
,
3159 char **rdata
,char **rparam
,
3160 int *rdata_len
,int *rparam_len
)
3162 char *str1
= param
+2;
3163 char *str2
= skip_string(str1
,1);
3164 char *p
= skip_string(str2
,1);
3165 char* PrinterName
= p
;
3167 struct pack_desc desc
;
3171 memset((char *)&desc
,'\0',sizeof(desc
));
3173 p
= skip_string(p
,1);
3176 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
3178 /* check it's a supported varient */
3179 if (strcmp(str1
,"zWrLh") != 0) return False
;
3180 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3182 snum
= lp_servicenumber(PrinterName
);
3183 if (snum
< 0 && pcap_printername_ok(PrinterName
,NULL
)) {
3184 int pnum
= lp_servicenumber(PRINTERS_NAME
);
3186 lp_add_printer(PrinterName
,pnum
);
3187 snum
= lp_servicenumber(PrinterName
);
3193 desc
.errcode
= NERR_DestNotFound
;
3198 *rdata
= REALLOC(*rdata
,mdrcnt
);
3200 desc
.buflen
= mdrcnt
;
3203 * Don't return data but need to get correct length
3204 * init_package will return wrong size if buflen=0
3206 desc
.buflen
= getlen(desc
.format
);
3207 desc
.base
= tmpdata
= (char *)malloc ( desc
.buflen
);
3209 if (init_package(&desc
,1,0)) {
3210 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
3212 *rdata_len
= desc
.usedlen
;
3216 *rparam
= REALLOC(*rparam
,*rparam_len
);
3217 SSVALS(*rparam
,0,desc
.errcode
);
3219 SSVAL(*rparam
,4,desc
.neededlen
);
3221 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3226 static BOOL
api_WPrintDestEnum(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 char *str1
= param
+2;
3232 char *str2
= skip_string(str1
,1);
3233 char *p
= skip_string(str2
,1);
3237 struct pack_desc desc
;
3238 int services
= lp_numservices();
3240 memset((char *)&desc
,'\0',sizeof(desc
));
3244 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3246 /* check it's a supported varient */
3247 if (strcmp(str1
,"WrLeh") != 0) return False
;
3248 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3251 for (i
= 0; i
< services
; i
++)
3252 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
3255 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3257 desc
.buflen
= mdrcnt
;
3258 if (init_package(&desc
,queuecnt
,0)) {
3261 for (i
= 0; i
< services
; i
++) {
3262 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3263 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3265 if (desc
.errcode
== NERR_Success
) succnt
= n
;
3270 *rdata_len
= desc
.usedlen
;
3273 *rparam
= REALLOC(*rparam
,*rparam_len
);
3274 SSVALS(*rparam
,0,desc
.errcode
);
3276 SSVAL(*rparam
,4,succnt
);
3277 SSVAL(*rparam
,6,queuecnt
);
3279 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3283 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3284 int mdrcnt
,int mprcnt
,
3285 char **rdata
,char **rparam
,
3286 int *rdata_len
,int *rparam_len
)
3288 char *str1
= param
+2;
3289 char *str2
= skip_string(str1
,1);
3290 char *p
= skip_string(str2
,1);
3293 struct pack_desc desc
;
3295 memset((char *)&desc
,'\0',sizeof(desc
));
3299 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
3301 /* check it's a supported varient */
3302 if (strcmp(str1
,"WrLeh") != 0) return False
;
3303 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) return False
;
3305 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3307 desc
.buflen
= mdrcnt
;
3308 if (init_package(&desc
,1,0)) {
3309 PACKS(&desc
,"B41","NULL");
3312 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3314 *rdata_len
= desc
.usedlen
;
3317 *rparam
= REALLOC(*rparam
,*rparam_len
);
3318 SSVALS(*rparam
,0,desc
.errcode
);
3320 SSVAL(*rparam
,4,succnt
);
3323 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
3327 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3328 int mdrcnt
,int mprcnt
,
3329 char **rdata
,char **rparam
,
3330 int *rdata_len
,int *rparam_len
)
3332 char *str1
= param
+2;
3333 char *str2
= skip_string(str1
,1);
3334 char *p
= skip_string(str2
,1);
3337 struct pack_desc desc
;
3339 memset((char *)&desc
,'\0',sizeof(desc
));
3343 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
3345 /* check it's a supported varient */
3346 if (strcmp(str1
,"WrLeh") != 0) return False
;
3347 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) return False
;
3349 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3351 desc
.buflen
= mdrcnt
;
3353 if (init_package(&desc
,1,0)) {
3354 PACKS(&desc
,"B13","lpd");
3357 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3359 *rdata_len
= desc
.usedlen
;
3362 *rparam
= REALLOC(*rparam
,*rparam_len
);
3363 SSVALS(*rparam
,0,desc
.errcode
);
3365 SSVAL(*rparam
,4,succnt
);
3368 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
3372 static BOOL
api_WPrintPortEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3373 int mdrcnt
,int mprcnt
,
3374 char **rdata
,char **rparam
,
3375 int *rdata_len
,int *rparam_len
)
3377 char *str1
= param
+2;
3378 char *str2
= skip_string(str1
,1);
3379 char *p
= skip_string(str2
,1);
3382 struct pack_desc desc
;
3384 memset((char *)&desc
,'\0',sizeof(desc
));
3388 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
3390 /* check it's a supported varient */
3391 if (strcmp(str1
,"WrLeh") != 0) return False
;
3392 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) return False
;
3394 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3395 memset((char *)&desc
,'\0',sizeof(desc
));
3397 desc
.buflen
= mdrcnt
;
3399 if (init_package(&desc
,1,0)) {
3400 PACKS(&desc
,"B13","lp0");
3403 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3405 *rdata_len
= desc
.usedlen
;
3408 *rparam
= REALLOC(*rparam
,*rparam_len
);
3409 SSVALS(*rparam
,0,desc
.errcode
);
3411 SSVAL(*rparam
,4,succnt
);
3414 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
3418 struct session_info
{
3426 struct sessions_info
{
3428 struct session_info
*session_list
;
3431 static int gather_sessioninfo(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
3433 struct sessions_info
*sinfo
= state
;
3434 struct session_info
*curinfo
= NULL
;
3435 struct sessionid
*sessid
= (struct sessionid
*) dbuf
.dptr
;
3438 sinfo
->session_list
= REALLOC(sinfo
->session_list
, sinfo
->count
* sizeof(struct session_info
));
3440 curinfo
= &(sinfo
->session_list
[sinfo
->count
- 1]);
3442 safe_strcpy(curinfo
->machine
, sessid
->remote_machine
,
3443 sizeof(curinfo
->machine
));
3444 safe_strcpy(curinfo
->username
, uidtoname(sessid
->uid
),
3445 sizeof(curinfo
->username
));
3446 DEBUG(7,("gather_sessioninfo session from %s@%s\n",
3447 curinfo
->username
, curinfo
->machine
));
3451 /****************************************************************************
3453 ****************************************************************************/
3454 static BOOL
api_RNetSessionEnum(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
3455 int mdrcnt
,int mprcnt
,
3456 char **rdata
,char **rparam
,
3457 int *rdata_len
,int *rparam_len
)
3460 char *str1
= param
+2;
3461 char *str2
= skip_string(str1
,1);
3462 char *p
= skip_string(str2
,1);
3464 struct pack_desc desc
;
3465 struct sessions_info sinfo
;
3468 memset((char *)&desc
,'\0',sizeof(desc
));
3472 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
3473 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
3474 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
3476 /* check it's a supported varient */
3477 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) return False
;
3478 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) return False
;
3481 sinfo
.session_list
= NULL
;
3483 if (!session_traverse(gather_sessioninfo
, &sinfo
)) {
3484 DEBUG(4,("RNetSessionEnum session_traverse failed\n"));
3488 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3489 memset((char *)&desc
,'\0',sizeof(desc
));
3491 desc
.buflen
= mdrcnt
;
3493 if (!init_package(&desc
,sinfo
.count
,0)) {
3497 for(i
=0; i
<sinfo
.count
; i
++) {
3498 PACKS(&desc
, "z", sinfo
.session_list
[i
].machine
);
3499 PACKS(&desc
, "z", sinfo
.session_list
[i
].username
);
3500 PACKI(&desc
, "W", 1); /* num conns */
3501 PACKI(&desc
, "W", 0); /* num opens */
3502 PACKI(&desc
, "W", 1); /* num users */
3503 PACKI(&desc
, "D", 0); /* session time */
3504 PACKI(&desc
, "D", 0); /* idle time */
3505 PACKI(&desc
, "D", 0); /* flags */
3506 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
3509 *rdata_len
= desc
.usedlen
;
3512 *rparam
= REALLOC(*rparam
,*rparam_len
);
3513 SSVALS(*rparam
,0,desc
.errcode
);
3514 SSVAL(*rparam
,2,0); /* converter */
3515 SSVAL(*rparam
,4,sinfo
.count
); /* count */
3517 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
3522 /****************************************************************************
3523 The buffer was too small
3524 ****************************************************************************/
3526 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3527 int mdrcnt
,int mprcnt
,
3528 char **rdata
,char **rparam
,
3529 int *rdata_len
,int *rparam_len
)
3531 *rparam_len
= MIN(*rparam_len
,mprcnt
);
3532 *rparam
= REALLOC(*rparam
,*rparam_len
);
3536 SSVAL(*rparam
,0,NERR_BufTooSmall
);
3538 DEBUG(3,("Supplied buffer too small in API command\n"));
3544 /****************************************************************************
3545 The request is not supported
3546 ****************************************************************************/
3548 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3549 int mdrcnt
,int mprcnt
,
3550 char **rdata
,char **rparam
,
3551 int *rdata_len
,int *rparam_len
)
3554 *rparam
= REALLOC(*rparam
,*rparam_len
);
3558 SSVAL(*rparam
,0,NERR_notsupported
);
3559 SSVAL(*rparam
,2,0); /* converter word */
3561 DEBUG(3,("Unsupported API command\n"));
3573 BOOL (*fn
)(connection_struct
*,uint16
,char *,char *,
3574 int,int,char **,char **,int *,int *);
3576 } api_commands
[] = {
3577 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
,0},
3578 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
,0},
3579 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
,0},
3580 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
,0},
3581 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
,0},
3582 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
,0},
3583 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
,0},
3584 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
,0},
3585 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
,0},
3586 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
,0},
3587 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
,0},
3588 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
,0},
3589 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
,0},
3590 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
,0},
3591 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
,0},
3592 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
,0},
3593 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
,0},
3594 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
,0},
3595 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
,0},
3596 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
,0},
3597 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
,0},
3598 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
,0},
3599 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
,0},
3600 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
,0},
3601 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
,0},
3602 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
,0},
3603 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
,0},
3604 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
,0},
3605 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
,0},
3606 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
,0},
3607 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
,0},
3608 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
,0},
3609 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
,0},
3610 {NULL
, -1, api_Unsupported
,0}};
3613 /****************************************************************************
3614 Handle remote api calls
3615 ****************************************************************************/
3617 int api_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,char *data
,char *params
,
3618 int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
3622 char *rparam
= NULL
;
3629 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3633 api_command
= SVAL(params
,0);
3635 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3638 skip_string(params
+2,1),
3639 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
3641 for (i
=0;api_commands
[i
].name
;i
++) {
3642 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
3643 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
3648 rdata
= (char *)malloc(1024);
3650 memset(rdata
,'\0',1024);
3652 rparam
= (char *)malloc(1024);
3654 memset(rparam
,'\0',1024);
3656 if(!rdata
|| !rparam
) {
3657 DEBUG(0,("api_reply: malloc fail !\n"));
3661 reply
= api_commands
[i
].fn(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3662 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3665 if (rdata_len
> mdrcnt
||
3666 rparam_len
> mprcnt
) {
3667 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3668 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3671 /* if we get False back then it's actually unsupported */
3673 api_Unsupported(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3674 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3676 send_trans_reply(outbuf
, rparam
, rparam_len
, rdata
, rdata_len
, False
);