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
37 extern int DEBUGLEVEL
;
40 extern fstring local_machine
;
41 extern fstring global_myworkgroup
;
43 #define NERR_Success 0
44 #define NERR_badpass 86
45 #define NERR_notsupported 50
47 #define NERR_BASE (2100)
48 #define NERR_BufTooSmall (NERR_BASE+23)
49 #define NERR_JobNotFound (NERR_BASE+51)
50 #define NERR_DestNotFound (NERR_BASE+52)
51 #define ERROR_INVALID_LEVEL 124
53 #define ACCESS_READ 0x01
54 #define ACCESS_WRITE 0x02
55 #define ACCESS_CREATE 0x04
57 #define SHPWLEN 8 /* share password length */
58 #define NNLEN 12 /* 8.3 net name length */
59 #define SNLEN 15 /* service name length */
60 #define QNLEN 12 /* queue name maximum length */
63 extern int smb_read_error
;
65 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
66 int mdrcnt
,int mprcnt
,
67 char **rdata
,char **rparam
,
68 int *rdata_len
,int *rparam_len
);
69 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
70 int mdrcnt
,int mprcnt
,
71 char **rdata
,char **rparam
,
72 int *rdata_len
,int *rparam_len
);
75 static int CopyExpanded(connection_struct
*conn
,
76 int snum
, char** dst
, char* src
, int* n
)
81 if (!src
|| !dst
|| !n
|| !(*dst
)) return(0);
83 StrnCpy(buf
,src
,sizeof(buf
)/2);
84 string_sub(buf
,"%S",lp_servicename(snum
));
85 standard_sub(conn
,buf
);
93 static int CopyAndAdvance(char** dst
, char* src
, int* n
)
96 if (!src
|| !dst
|| !n
|| !(*dst
)) return(0);
104 static int StrlenExpanded(connection_struct
*conn
, int snum
, char* s
)
108 StrnCpy(buf
,s
,sizeof(buf
)/2);
109 string_sub(buf
,"%S",lp_servicename(snum
));
110 standard_sub(conn
,buf
);
111 return strlen(buf
) + 1;
114 static char* Expand(connection_struct
*conn
, int snum
, char* s
)
117 if (!s
) return(NULL
);
118 StrnCpy(buf
,s
,sizeof(buf
)/2);
119 string_sub(buf
,"%S",lp_servicename(snum
));
120 standard_sub(conn
,buf
);
124 /*******************************************************************
125 check a API string for validity when we only need to check the prefix
126 ******************************************************************/
127 static BOOL
prefix_ok(char *str
,char *prefix
)
129 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
132 /*******************************************************************
133 copies parameters and data, as needed, into the smb buffer
135 *both* the data and params sections should be aligned. this
136 is fudged in the rpc pipes by
137 at present, only the data section is. this may be a possible
138 cause of some of the ipc problems being experienced. lkcl26dec97
140 ******************************************************************/
141 static void copy_trans_params_and_data(char *outbuf
, int align
,
142 struct mem_buf
*rparam
, struct mem_buf
*rdata
,
143 int param_offset
, int data_offset
,
144 int param_len
, int data_len
)
146 char *copy_into
= smb_buf(outbuf
)+1;
148 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
149 param_offset
, param_offset
+ param_len
,
150 data_offset
, data_offset
+ data_len
));
152 if (param_len
) mem_buf_copy(copy_into
, rparam
, param_offset
, param_len
);
153 copy_into
+= param_len
+ align
;
154 if (data_len
) mem_buf_copy(copy_into
, rdata
, data_offset
, data_len
);
157 /****************************************************************************
159 ****************************************************************************/
160 static void send_trans_reply(char *outbuf
,
161 struct mem_buf
*rdata
,
162 struct mem_buf
*rparam
,
163 uint16
*setup
, int lsetup
, int max_data_ret
)
166 int this_ldata
,this_lparam
;
167 int tot_data
=0,tot_param
=0;
170 int ldata
= rdata
? mem_buf_len(rdata
) : 0;
171 int lparam
= rparam
? mem_buf_len(rparam
) : 0;
173 BOOL buffer_too_large
= max_data_ret
? ldata
> max_data_ret
: False
;
175 if (buffer_too_large
)
177 DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata
, max_data_ret
));
178 ldata
= max_data_ret
;
181 this_lparam
= MIN(lparam
,max_send
- (500+lsetup
*SIZEOFWORD
)); /* hack */
182 this_ldata
= MIN(ldata
,max_send
- (500+lsetup
*SIZEOFWORD
+this_lparam
));
184 align
= ((this_lparam
)%4);
186 set_message(outbuf
,10+lsetup
,1+align
+this_ldata
+this_lparam
,True
);
188 if (buffer_too_large
)
190 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
191 SIVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
192 SIVAL(outbuf
, smb_rcls
, 0x80000000 | NT_STATUS_ACCESS_VIOLATION
);
195 copy_trans_params_and_data(outbuf
, align
,
197 tot_param
, tot_data
,
198 this_lparam
, this_ldata
);
200 SSVAL(outbuf
,smb_vwv0
,lparam
);
201 SSVAL(outbuf
,smb_vwv1
,ldata
);
202 SSVAL(outbuf
,smb_vwv3
,this_lparam
);
203 SSVAL(outbuf
,smb_vwv4
,smb_offset(smb_buf(outbuf
)+1,outbuf
));
204 SSVAL(outbuf
,smb_vwv5
,0);
205 SSVAL(outbuf
,smb_vwv6
,this_ldata
);
206 SSVAL(outbuf
,smb_vwv7
,smb_offset(smb_buf(outbuf
)+1+this_lparam
+align
,outbuf
));
207 SSVAL(outbuf
,smb_vwv8
,0);
208 SSVAL(outbuf
,smb_vwv9
,lsetup
);
210 for (i
=0;i
<lsetup
;i
++)
212 SSVAL(outbuf
,smb_vwv10
+i
*SIZEOFWORD
,setup
[i
]);
216 send_smb(Client
,outbuf
);
218 tot_data
= this_ldata
;
219 tot_param
= this_lparam
;
221 while (tot_data
< ldata
|| tot_param
< lparam
)
223 this_lparam
= MIN(lparam
-tot_param
, max_send
- 500); /* hack */
224 this_ldata
= MIN(ldata
-tot_data
, max_send
- (500+this_lparam
));
226 align
= (this_lparam
%4);
228 set_message(outbuf
,10,1+this_ldata
+this_lparam
+align
,False
);
230 copy_trans_params_and_data(outbuf
, align
,
232 tot_param
, tot_data
,
233 this_lparam
, this_ldata
);
235 SSVAL(outbuf
,smb_vwv3
,this_lparam
);
236 SSVAL(outbuf
,smb_vwv4
,smb_offset(smb_buf(outbuf
)+1,outbuf
));
237 SSVAL(outbuf
,smb_vwv5
,tot_param
);
238 SSVAL(outbuf
,smb_vwv6
,this_ldata
);
239 SSVAL(outbuf
,smb_vwv7
,smb_offset(smb_buf(outbuf
)+1+this_lparam
+align
,outbuf
));
240 SSVAL(outbuf
,smb_vwv8
,tot_data
);
241 SSVAL(outbuf
,smb_vwv9
,0);
244 send_smb(Client
,outbuf
);
246 tot_data
+= this_ldata
;
247 tot_param
+= this_lparam
;
252 char* format
; /* formatstring for structure */
253 char* subformat
; /* subformat for structure */
254 char* base
; /* baseaddress of buffer */
255 int buflen
; /* remaining size for fixed part; on init: length of base */
256 int subcount
; /* count of substructures */
257 char* structbuf
; /* pointer into buffer for remaining fixed part */
258 int stringlen
; /* remaining size for variable part */
259 char* stringbuf
; /* pointer into buffer for remaining variable part */
260 int neededlen
; /* total needed size */
261 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
262 char* curpos
; /* current position; pointer into format or subformat */
266 static int get_counter(char** p
)
269 if (!p
|| !(*p
)) return(1);
270 if (!isdigit((int)**p
)) return 1;
274 n
= 10 * n
+ (i
- '0');
281 static int getlen(char* p
)
287 case 'W': /* word (2 byte) */
290 case 'N': /* count of substructures (word) at end */
293 case 'D': /* double word (4 byte) */
294 case 'z': /* offset to zero terminated string (4 byte) */
295 case 'l': /* offset to user data (4 byte) */
298 case 'b': /* offset to data (with counter) (4 byte) */
302 case 'B': /* byte (with optional counter) */
303 n
+= get_counter(&p
);
310 static BOOL
init_package(struct pack_desc
* p
, int count
, int subcount
)
315 if (!p
->format
|| !p
->base
) return(False
);
317 i
= count
* getlen(p
->format
);
318 if (p
->subformat
) i
+= subcount
* getlen(p
->subformat
);
319 p
->structbuf
= p
->base
;
323 p
->curpos
= p
->format
;
327 p
->errcode
= ERRmoredata
;
330 p
->errcode
= NERR_Success
;
333 p
->stringbuf
= p
->base
+ i
;
335 return(p
->errcode
== NERR_Success
);
339 static int package(struct pack_desc
* p
, ...)
342 static int package(va_alist
)
348 int needed
=0, stringneeded
;
350 int is_string
=0, stringused
;
357 p
= va_arg(args
,struct pack_desc
*);
362 p
->curpos
= p
->format
;
364 p
->curpos
= p
->subformat
;
369 str
= va_arg(args
,char*);
370 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
374 if (!p
->curpos
) return(0);
376 switch( *p
->curpos
++ ) {
377 case 'W': /* word (2 byte) */
379 temp
= va_arg(args
,int);
380 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,temp
);
382 case 'N': /* count of substructures (word) at end */
384 p
->subcount
= va_arg(args
,int);
385 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,p
->subcount
);
387 case 'D': /* double word (4 byte) */
389 temp
= va_arg(args
,int);
390 if (p
->buflen
>= needed
) SIVAL(p
->structbuf
,0,temp
);
392 case 'B': /* byte (with optional counter) */
393 needed
= get_counter(&p
->curpos
);
395 char *s
= va_arg(args
,char*);
396 if (p
->buflen
>= needed
) StrnCpy(p
->structbuf
,s
?s
:"",needed
);
399 case 'z': /* offset to zero terminated string (4 byte) */
400 str
= va_arg(args
,char*);
401 stringneeded
= (str
? strlen(str
)+1 : 0);
404 case 'l': /* offset to user data (4 byte) */
405 str
= va_arg(args
,char*);
406 stringneeded
= va_arg(args
,int);
409 case 'b': /* offset to data (with counter) (4 byte) */
410 str
= va_arg(args
,char*);
411 stringneeded
= get_counter(&p
->curpos
);
416 if (stringneeded
>= 0) {
418 if (p
->buflen
>= needed
) {
419 stringused
= stringneeded
;
420 if (stringused
> p
->stringlen
) {
421 stringused
= (is_string
? p
->stringlen
: 0);
422 if (p
->errcode
== NERR_Success
) p
->errcode
= ERRmoredata
;
425 SIVAL(p
->structbuf
,0,0);
427 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
428 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
429 if (is_string
) p
->stringbuf
[stringused
-1] = '\0';
430 p
->stringbuf
+= stringused
;
431 p
->stringlen
-= stringused
;
432 p
->usedlen
+= stringused
;
435 p
->neededlen
+= stringneeded
;
437 p
->neededlen
+= needed
;
438 if (p
->buflen
>= needed
) {
439 p
->structbuf
+= needed
;
441 p
->usedlen
+= needed
;
444 if (p
->errcode
== NERR_Success
) p
->errcode
= ERRmoredata
;
450 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
451 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
453 #define PACK(desc,t,v) package(desc,v)
454 #define PACKl(desc,t,v,l) package(desc,v,l)
457 static void PACKI(struct pack_desc
* desc
,char *t
,int v
)
462 static void PACKS(struct pack_desc
* desc
,char *t
,char *v
)
468 /****************************************************************************
470 ****************************************************************************/
472 static void PackDriverData(struct pack_desc
* desc
)
474 char drivdata
[4+4+32];
475 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
476 SIVAL(drivdata
,4,1000); /* lVersion */
477 memset(drivdata
+8,0,32); /* szDeviceName */
478 pstrcpy(drivdata
+8,"NULL");
479 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
482 static int check_printq_info(struct pack_desc
* desc
,
483 int uLevel
, char *id1
, char *id2
)
485 desc
->subformat
= NULL
;
488 desc
->format
= "B13";
491 desc
->format
= "B13BWWWzzzzzWW";
494 desc
->format
= "B13BWWWzzzzzWN";
495 desc
->subformat
= "WB21BB16B10zWWzDDz";
498 desc
->format
= "zWWWWzzzzWWzzl";
501 desc
->format
= "zWWWWzzzzWNzzl";
502 desc
->subformat
= "WWzWWDDzz";
508 desc
->format
= "WzzzzzzzzN";
509 desc
->subformat
= "z";
511 default: return False
;
513 if (strcmp(desc
->format
,id1
) != 0) return False
;
514 if (desc
->subformat
&& strcmp(desc
->subformat
,id2
) != 0) return False
;
518 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
519 struct pack_desc
* desc
,
520 print_queue_struct
* queue
, int n
)
522 time_t t
= queue
->time
;
524 /* the client expects localtime */
527 PACKI(desc
,"W",printjob_encode(snum
, queue
->job
)); /* uJobId */
529 PACKS(desc
,"B21",queue
->user
); /* szUserName */
530 PACKS(desc
,"B",""); /* pad */
531 PACKS(desc
,"B16",""); /* szNotifyName */
532 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
533 PACKS(desc
,"z",""); /* pszParms */
534 PACKI(desc
,"W",n
+1); /* uPosition */
535 PACKI(desc
,"W",queue
->status
); /* fsStatus */
536 PACKS(desc
,"z",""); /* pszStatus */
537 PACKI(desc
,"D",t
); /* ulSubmitted */
538 PACKI(desc
,"D",queue
->size
); /* ulSize */
539 PACKS(desc
,"z",queue
->file
); /* pszComment */
541 if (uLevel
== 2 || uLevel
== 3) {
542 PACKI(desc
,"W",queue
->priority
); /* uPriority */
543 PACKS(desc
,"z",queue
->user
); /* pszUserName */
544 PACKI(desc
,"W",n
+1); /* uPosition */
545 PACKI(desc
,"W",queue
->status
); /* fsStatus */
546 PACKI(desc
,"D",t
); /* ulSubmitted */
547 PACKI(desc
,"D",queue
->size
); /* ulSize */
548 PACKS(desc
,"z","Samba"); /* pszComment */
549 PACKS(desc
,"z",queue
->file
); /* pszDocument */
551 PACKS(desc
,"z",""); /* pszNotifyName */
552 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
553 PACKS(desc
,"z",""); /* pszParms */
554 PACKS(desc
,"z",""); /* pszStatus */
555 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
556 PACKS(desc
,"z","lpd"); /* pszQProcName */
557 PACKS(desc
,"z",""); /* pszQProcParms */
558 PACKS(desc
,"z","NULL"); /* pszDriverName */
559 PackDriverData(desc
); /* pDriverData */
560 PACKS(desc
,"z",""); /* pszPrinterName */
565 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
566 struct pack_desc
* desc
,
567 int count
, print_queue_struct
* queue
,
568 print_status_struct
* status
)
573 PACKS(desc
,"B13",SERVICE(snum
));
578 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
582 if (uLevel
== 1 || uLevel
== 2) {
583 PACKS(desc
,"B",""); /* alignment */
584 PACKI(desc
,"W",5); /* priority */
585 PACKI(desc
,"W",0); /* start time */
586 PACKI(desc
,"W",0); /* until time */
587 PACKS(desc
,"z",""); /* pSepFile */
588 PACKS(desc
,"z","lpd"); /* pPrProc */
589 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
590 PACKS(desc
,"z",""); /* pParms */
592 PACKS(desc
,"z","UNKNOWN PRINTER");
593 PACKI(desc
,"W",LPSTAT_ERROR
);
595 else if (!status
|| !status
->message
[0]) {
596 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
597 PACKI(desc
,"W",LPSTAT_OK
); /* status */
599 PACKS(desc
,"z",status
->message
);
600 PACKI(desc
,"W",status
->status
); /* status */
602 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
604 if (uLevel
== 3 || uLevel
== 4) {
605 PACKI(desc
,"W",5); /* uPriority */
606 PACKI(desc
,"W",0); /* uStarttime */
607 PACKI(desc
,"W",0); /* uUntiltime */
608 PACKI(desc
,"W",5); /* pad1 */
609 PACKS(desc
,"z",""); /* pszSepFile */
610 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
611 PACKS(desc
,"z",""); /* pszParms */
612 if (!status
|| !status
->message
[0]) {
613 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
))); /* pszComment */
614 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
616 PACKS(desc
,"z",status
->message
); /* pszComment */
617 PACKI(desc
,"W",status
->status
); /* fsStatus */
619 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
620 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
621 PACKS(desc
,"z",lp_printerdriver(snum
)); /* pszDriverName */
622 PackDriverData(desc
); /* pDriverData */
624 if (uLevel
== 2 || uLevel
== 4) {
626 for (i
=0;i
<count
;i
++)
627 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
632 pstring tok
,driver
,datafile
,langmon
,helpfile
,datatype
;
637 pstrcpy(fname
,lp_driverfile());
638 f
=sys_fopen(fname
,"r");
640 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname
,strerror(errno
)));
641 desc
->errcode
=NERR_notsupported
;
645 if((p
=(char *)malloc(8192*sizeof(char))) == NULL
) {
646 DEBUG(0,("fill_printq_info: malloc fail !\n"));
647 desc
->errcode
=NERR_notsupported
;
652 bzero(p
, 8192*sizeof(char));
655 /* lookup the long printer driver name in the file description */
656 while (f
&& !feof(f
) && !ok
)
658 p
= q
; /* reset string pointer */
661 if (next_token(&p
,tok
,":",sizeof(tok
)) &&
662 (strlen(lp_printerdriver(snum
)) == strlen(tok
)) &&
663 (!strncmp(tok
,lp_printerdriver(snum
),strlen(lp_printerdriver(snum
)))))
668 /* driver file name */
669 if (ok
&& !next_token(&p
,driver
,":",sizeof(driver
))) ok
= 0;
671 if (ok
&& !next_token(&p
,datafile
,":",sizeof(datafile
))) ok
= 0;
673 * for the next tokens - which may be empty - I have to check for empty
674 * tokens first because the next_token function will skip all empty
682 } else if (!next_token(&p
,helpfile
,":",sizeof(helpfile
))) ok
= 0;
686 /* language monitor */
690 } else if (!next_token(&p
,langmon
,":",sizeof(langmon
))) ok
= 0;
693 /* default data type */
694 if (ok
&& !next_token(&p
,datatype
,":",sizeof(datatype
))) ok
= 0;
697 PACKI(desc
,"W",0x0400); /* don't know */
698 PACKS(desc
,"z",lp_printerdriver(snum
)); /* long printer name */
699 PACKS(desc
,"z",driver
); /* Driverfile Name */
700 PACKS(desc
,"z",datafile
); /* Datafile name */
701 PACKS(desc
,"z",langmon
); /* language monitor */
702 PACKS(desc
,"z",lp_driverlocation(snum
)); /* share to retrieve files */
703 PACKS(desc
,"z",datatype
); /* default data type */
704 PACKS(desc
,"z",helpfile
); /* helpfile name */
705 PACKS(desc
,"z",driver
); /* driver name */
706 DEBUG(3,("Driver:%s:\n",driver
));
707 DEBUG(3,("Data File:%s:\n",datafile
));
708 DEBUG(3,("Language Monitor:%s:\n",langmon
));
709 DEBUG(3,("Data Type:%s:\n",datatype
));
710 DEBUG(3,("Help File:%s:\n",helpfile
));
711 PACKI(desc
,"N",count
); /* number of files to copy */
712 for (i
=0;i
<count
;i
++)
714 /* no need to check return value here - it was already tested in
715 * get_printerdrivernumber
717 next_token(&p
,tok
,",",sizeof(tok
));
718 PACKS(desc
,"z",tok
); /* driver files to copy */
719 DEBUG(3,("file:%s:\n",tok
));
722 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
723 SERVICE(snum
),count
));
725 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
726 desc
->errcode
=NERR_notsupported
;
732 /* This function returns the number of files for a given driver */
733 static int get_printerdrivernumber(int snum
)
741 pstrcpy(fname
,lp_driverfile());
743 DEBUG(4,("In get_printerdrivernumber: %s\n",fname
));
744 f
=sys_fopen(fname
,"r");
746 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname
,strerror(errno
)));
750 if((p
=(char *)malloc(8192*sizeof(char))) == NULL
) {
751 DEBUG(3,("get_printerdrivernumber: malloc fail !\n"));
756 q
=p
; /* need it to free memory because p change ! */
758 /* lookup the long printer driver name in the file description */
759 while (!feof(f
) && !ok
)
761 p
= q
; /* reset string pointer */
763 if (next_token(&p
,tok
,":",sizeof(tok
)) &&
764 (!strncmp(tok
,lp_printerdriver(snum
),strlen(lp_printerdriver(snum
)))))
773 if (*p
++ == ':') i
--;
778 /* count the number of files */
779 while (next_token(&p
,tok
,",",sizeof(tok
)))
787 static BOOL
api_DosPrintQGetInfo(connection_struct
*conn
,
788 uint16 vuid
, char *param
,char *data
,
789 int mdrcnt
,int mprcnt
,
790 char **rdata
,char **rparam
,
791 int *rdata_len
,int *rparam_len
)
793 char *str1
= param
+2;
794 char *str2
= skip_string(str1
,1);
795 char *p
= skip_string(str2
,1);
801 struct pack_desc desc
;
802 print_queue_struct
*queue
=NULL
;
803 print_status_struct status
;
805 bzero(&status
,sizeof(status
));
806 bzero(&desc
,sizeof(desc
));
808 p
= skip_string(p
,1);
812 /* remove any trailing username */
813 if ((p
= strchr(QueueName
,'%'))) *p
= 0;
815 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel
,QueueName
));
817 /* check it's a supported varient */
818 if (!prefix_ok(str1
,"zWrLh")) return False
;
819 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
821 * Patch from Scott Moomaw <scott@bridgewater.edu>
822 * to return the 'invalid info level' error if an
823 * unknown level was requested.
827 *rparam
= REALLOC(*rparam
,*rparam_len
);
828 SSVALS(*rparam
,0,ERROR_INVALID_LEVEL
);
834 snum
= lp_servicenumber(QueueName
);
835 if (snum
< 0 && pcap_printername_ok(QueueName
,NULL
)) {
836 int pnum
= lp_servicenumber(PRINTERS_NAME
);
838 lp_add_printer(QueueName
,pnum
);
839 snum
= lp_servicenumber(QueueName
);
843 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
846 count
= get_printerdrivernumber(snum
);
847 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
849 count
= get_printqueue(snum
, conn
,&queue
,&status
);
852 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
854 desc
.buflen
= mdrcnt
;
855 if (init_package(&desc
,1,count
)) {
856 desc
.subcount
= count
;
857 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
858 } else if(uLevel
== 0) {
860 * This is a *disgusting* hack.
861 * This is *so* bad that even I'm embarrassed (and I
862 * have no shame). Here's the deal :
863 * Until we get the correct SPOOLSS code into smbd
864 * then when we're running with NT SMB support then
865 * NT makes this call with a level of zero, and then
866 * immediately follows it with an open request to
867 * the \\SRVSVC pipe. If we allow that open to
868 * succeed then NT barfs when it cannot open the
869 * \\SPOOLSS pipe immediately after and continually
870 * whines saying "Printer name is invalid" forever
871 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
872 * to fail, then NT downgrades to using the downlevel code
873 * and everything works as well as before. I hate
874 * myself for adding this code.... JRA.
877 fail_next_srvsvc_open();
880 *rdata_len
= desc
.usedlen
;
883 *rparam
= REALLOC(*rparam
,*rparam_len
);
884 SSVALS(*rparam
,0,desc
.errcode
);
886 SSVAL(*rparam
,4,desc
.neededlen
);
888 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
890 if (queue
) free(queue
);
896 /****************************************************************************
897 view list of all print jobs on all queues
898 ****************************************************************************/
899 static BOOL
api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
, char* param
, char* data
,
900 int mdrcnt
, int mprcnt
,
901 char **rdata
, char** rparam
,
902 int *rdata_len
, int *rparam_len
)
904 char *param_format
= param
+2;
905 char *output_format1
= skip_string(param_format
,1);
906 char *p
= skip_string(output_format1
,1);
907 int uLevel
= SVAL(p
,0);
908 char *output_format2
= p
+ 4;
909 int services
= lp_numservices();
911 struct pack_desc desc
;
912 print_queue_struct
**queue
= NULL
;
913 print_status_struct
*status
= NULL
;
914 int* subcntarr
= NULL
;
915 int queuecnt
, subcnt
=0, succnt
=0;
917 bzero(&desc
,sizeof(desc
));
919 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
921 if (!prefix_ok(param_format
,"WrLeh")) return False
;
922 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
924 * Patch from Scott Moomaw <scott@bridgewater.edu>
925 * to return the 'invalid info level' error if an
926 * unknown level was requested.
930 *rparam
= REALLOC(*rparam
,*rparam_len
);
931 SSVALS(*rparam
,0,ERROR_INVALID_LEVEL
);
938 for (i
= 0; i
< services
; i
++)
939 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
942 if((queue
= (print_queue_struct
**)malloc(queuecnt
*sizeof(print_queue_struct
*))) == NULL
) {
943 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
946 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
947 if((status
= (print_status_struct
*)malloc(queuecnt
*sizeof(print_status_struct
))) == NULL
) {
948 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
951 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
952 if((subcntarr
= (int*)malloc(queuecnt
*sizeof(int))) == NULL
) {
953 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
958 for (i
= 0; i
< services
; i
++)
959 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
960 subcntarr
[n
] = get_printqueue(i
, conn
,&queue
[n
],&status
[n
]);
961 subcnt
+= subcntarr
[n
];
965 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
967 desc
.buflen
= mdrcnt
;
969 if (init_package(&desc
,queuecnt
,subcnt
)) {
972 for (i
= 0; i
< services
; i
++)
973 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
974 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
976 if (desc
.errcode
== NERR_Success
) succnt
= n
;
980 if (subcntarr
) free(subcntarr
);
982 *rdata_len
= desc
.usedlen
;
984 *rparam
= REALLOC(*rparam
,*rparam_len
);
985 SSVALS(*rparam
,0,desc
.errcode
);
987 SSVAL(*rparam
,4,succnt
);
988 SSVAL(*rparam
,6,queuecnt
);
990 for (i
= 0; i
< queuecnt
; i
++) {
991 if (queue
&& queue
[i
]) free(queue
[i
]);
994 if (queue
) free(queue
);
995 if (status
) free(status
);
1000 /****************************************************************************
1001 get info level for a server list query
1002 ****************************************************************************/
1003 static BOOL
check_server_info(int uLevel
, char* id
)
1007 if (strcmp(id
,"B16") != 0) return False
;
1010 if (strcmp(id
,"B16BBDz") != 0) return False
;
1018 struct srv_info_struct
1028 /*******************************************************************
1029 get server info lists from the files saved by nmbd. Return the
1031 ******************************************************************/
1032 static int get_server_info(uint32 servertype
,
1033 struct srv_info_struct
**servers
,
1041 BOOL local_list_only
;
1043 pstrcpy(fname
,lp_lockdir());
1044 trim_string(fname
,NULL
,"/");
1046 pstrcat(fname
,SERVER_LIST
);
1048 f
= sys_fopen(fname
,"r");
1051 DEBUG(4,("Can't open %s - %s\n",fname
,strerror(errno
)));
1055 /* request for everything is code for request all servers */
1056 if (servertype
== SV_TYPE_ALL
)
1057 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1059 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1061 DEBUG(4,("Servertype search: %8x\n",servertype
));
1066 struct srv_info_struct
*s
;
1071 fgets(line
,sizeof(line
)-1,f
);
1072 if (!*line
) continue;
1074 if (count
== alloced
) {
1076 (*servers
) = (struct srv_info_struct
*)
1077 Realloc(*servers
,sizeof(**servers
)*alloced
);
1078 if (!(*servers
)) return(0);
1079 bzero((char *)((*servers
)+count
),sizeof(**servers
)*(alloced
-count
));
1081 s
= &(*servers
)[count
];
1083 if (!next_token(&ptr
,s
->name
, NULL
, sizeof(s
->name
))) continue;
1084 if (!next_token(&ptr
,stype
, NULL
, sizeof(stype
))) continue;
1085 if (!next_token(&ptr
,s
->comment
, NULL
, sizeof(s
->comment
))) continue;
1086 if (!next_token(&ptr
,s
->domain
, NULL
, sizeof(s
->domain
))) {
1087 /* this allows us to cope with an old nmbd */
1088 pstrcpy(s
->domain
,global_myworkgroup
);
1091 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1092 DEBUG(4,("r:host file "));
1096 /* Filter the servers/domains we return based on what was asked for. */
1098 /* Check to see if we are being asked for a local list only. */
1099 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1100 DEBUG(4,("r: local list only"));
1104 /* doesn't match up: don't want it */
1105 if (!(servertype
& s
->type
)) {
1106 DEBUG(4,("r:serv type "));
1110 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1111 (s
->type
& SV_TYPE_DOMAIN_ENUM
))
1113 DEBUG(4,("s: dom mismatch "));
1117 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1122 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1123 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1127 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1128 s
->name
, s
->type
, s
->comment
, s
->domain
));
1130 s
->server_added
= True
;
1135 DEBUG(4,("%20s %8x %25s %15s\n",
1136 s
->name
, s
->type
, s
->comment
, s
->domain
));
1145 /*******************************************************************
1146 fill in a server info structure
1147 ******************************************************************/
1148 static int fill_srv_info(struct srv_info_struct
*service
,
1149 int uLevel
, char **buf
, int *buflen
,
1150 char **stringbuf
, int *stringspace
, char *baseaddr
)
1159 case 0: struct_len
= 16; break;
1160 case 1: struct_len
= 26; break;
1170 len
= strlen(service
->comment
)+1;
1174 if (buflen
) *buflen
= struct_len
;
1175 if (stringspace
) *stringspace
= len
;
1176 return struct_len
+ len
;
1181 if (*buflen
< struct_len
) return -1;
1189 p2
= p
+ struct_len
;
1190 l2
= *buflen
- struct_len
;
1192 if (!baseaddr
) baseaddr
= p
;
1197 StrnCpy(p
,service
->name
,15);
1201 StrnCpy(p
,service
->name
,15);
1202 SIVAL(p
,18,service
->type
);
1203 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1204 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1210 *buf
= p
+ struct_len
;
1211 *buflen
-= struct_len
;
1224 static BOOL
srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1226 return(strcmp(s1
->name
,s2
->name
));
1229 /****************************************************************************
1230 view list of servers available (or possibly domains). The info is
1231 extracted from lists saved by nmbd on the local host
1232 ****************************************************************************/
1233 static BOOL
api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1234 int mdrcnt
, int mprcnt
, char **rdata
,
1235 char **rparam
, int *rdata_len
, int *rparam_len
)
1237 char *str1
= param
+2;
1238 char *str2
= skip_string(str1
,1);
1239 char *p
= skip_string(str2
,1);
1240 int uLevel
= SVAL(p
,0);
1241 int buf_len
= SVAL(p
,2);
1242 uint32 servertype
= IVAL(p
,4);
1244 int data_len
, fixed_len
, string_len
;
1245 int f_len
= 0, s_len
= 0;
1246 struct srv_info_struct
*servers
=NULL
;
1247 int counted
=0,total
=0;
1250 BOOL domain_request
;
1253 /* If someone sets all the bits they don't really mean to set
1254 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1257 if (servertype
== SV_TYPE_ALL
)
1258 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1260 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1261 any other bit (they may just set this bit on it's own) they
1262 want all the locally seen servers. However this bit can be
1263 set on its own so set the requested servers to be
1264 ALL - DOMAIN_ENUM. */
1266 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1267 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1269 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1270 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1274 if (!prefix_ok(str1
,"WrLehD")) return False
;
1275 if (!check_server_info(uLevel
,str2
)) return False
;
1277 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1278 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1279 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1281 if (strcmp(str1
, "WrLehDz") == 0) {
1282 StrnCpy(domain
, p
, sizeof(fstring
)-1);
1284 StrnCpy(domain
, global_myworkgroup
, sizeof(fstring
)-1);
1287 if (lp_browse_list())
1288 total
= get_server_info(servertype
,&servers
,domain
);
1290 data_len
= fixed_len
= string_len
= 0;
1293 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1296 char *lastname
=NULL
;
1298 for (i
=0;i
<total
;i
++)
1300 struct srv_info_struct
*s
= &servers
[i
];
1301 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1303 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1304 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1305 s
->name
, s
->type
, s
->comment
, s
->domain
));
1307 if (data_len
<= buf_len
) {
1310 string_len
+= s_len
;
1317 *rdata_len
= fixed_len
+ string_len
;
1318 *rdata
= REALLOC(*rdata
,*rdata_len
);
1319 bzero(*rdata
,*rdata_len
);
1321 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1327 char *lastname
=NULL
;
1328 int count2
= counted
;
1329 for (i
= 0; i
< total
&& count2
;i
++)
1331 struct srv_info_struct
*s
= &servers
[i
];
1332 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1334 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1335 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1336 s
->name
, s
->type
, s
->comment
, s
->domain
));
1342 *rparam
= REALLOC(*rparam
,*rparam_len
);
1343 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1345 SSVAL(*rparam
,4,counted
);
1346 SSVAL(*rparam
,6,counted
+missed
);
1348 if (servers
) free(servers
);
1350 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1351 domain
,uLevel
,counted
,counted
+missed
));
1356 /****************************************************************************
1357 command 0x34 - suspected of being a "Lookup Names" stub api
1358 ****************************************************************************/
1359 static BOOL
api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1360 int mdrcnt
, int mprcnt
, char **rdata
,
1361 char **rparam
, int *rdata_len
, int *rparam_len
)
1363 char *str1
= param
+2;
1364 char *str2
= skip_string(str1
,1);
1365 char *p
= skip_string(str2
,1);
1366 int uLevel
= SVAL(p
,0);
1367 int buf_len
= SVAL(p
,2);
1371 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1372 str1
, str2
, p
, uLevel
, buf_len
));
1374 if (!prefix_ok(str1
,"zWrLeh")) return False
;
1379 *rparam
= REALLOC(*rparam
,*rparam_len
);
1381 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1383 SSVAL(*rparam
,4,counted
);
1384 SSVAL(*rparam
,6,counted
+missed
);
1389 /****************************************************************************
1390 get info about a share
1391 ****************************************************************************/
1392 static BOOL
check_share_info(int uLevel
, char* id
)
1396 if (strcmp(id
,"B13") != 0) return False
;
1399 if (strcmp(id
,"B13BWz") != 0) return False
;
1402 if (strcmp(id
,"B13BWzWWWzB9B") != 0) return False
;
1405 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False
;
1407 default: return False
;
1412 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1413 char** buf
, int* buflen
,
1414 char** stringbuf
, int* stringspace
, char* baseaddr
)
1423 case 0: struct_len
= 13; break;
1424 case 1: struct_len
= 20; break;
1425 case 2: struct_len
= 40; break;
1426 case 91: struct_len
= 68; break;
1434 if (uLevel
> 0) len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1435 if (uLevel
> 1) len
+= strlen(lp_pathname(snum
)) + 1;
1436 if (buflen
) *buflen
= struct_len
;
1437 if (stringspace
) *stringspace
= len
;
1438 return struct_len
+ len
;
1443 if ((*buflen
) < struct_len
) return -1;
1451 p2
= p
+ struct_len
;
1452 l2
= (*buflen
) - struct_len
;
1454 if (!baseaddr
) baseaddr
= p
;
1456 StrnCpy(p
,lp_servicename(snum
),13);
1462 type
= STYPE_DISKTREE
;
1463 if (lp_print_ok(snum
)) type
= STYPE_PRINTQ
;
1464 if (strequal("IPC$",lp_servicename(snum
))) type
= STYPE_IPC
;
1465 SSVAL(p
,14,type
); /* device type */
1466 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1467 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1472 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1473 SSVALS(p
,22,-1); /* max uses */
1474 SSVAL(p
,24,1); /* current uses */
1475 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1476 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1477 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1482 memset(p
+40,0,SHPWLEN
+2);
1494 (*buf
) = p
+ struct_len
;
1495 (*buflen
) -= struct_len
;
1497 (*stringspace
) = l2
;
1507 static BOOL
api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1508 int mdrcnt
,int mprcnt
,
1509 char **rdata
,char **rparam
,
1510 int *rdata_len
,int *rparam_len
)
1512 char *str1
= param
+2;
1513 char *str2
= skip_string(str1
,1);
1514 char *netname
= skip_string(str2
,1);
1515 char *p
= skip_string(netname
,1);
1516 int uLevel
= SVAL(p
,0);
1517 int snum
= find_service(netname
);
1519 if (snum
< 0) return False
;
1521 /* check it's a supported varient */
1522 if (!prefix_ok(str1
,"zWrLh")) return False
;
1523 if (!check_share_info(uLevel
,str2
)) return False
;
1525 *rdata
= REALLOC(*rdata
,mdrcnt
);
1527 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1528 if (*rdata_len
< 0) return False
;
1531 *rparam
= REALLOC(*rparam
,*rparam_len
);
1532 SSVAL(*rparam
,0,NERR_Success
);
1533 SSVAL(*rparam
,2,0); /* converter word */
1534 SSVAL(*rparam
,4,*rdata_len
);
1539 /****************************************************************************
1540 view list of shares available
1541 ****************************************************************************/
1542 static BOOL
api_RNetShareEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1543 int mdrcnt
,int mprcnt
,
1544 char **rdata
,char **rparam
,
1545 int *rdata_len
,int *rparam_len
)
1547 char *str1
= param
+2;
1548 char *str2
= skip_string(str1
,1);
1549 char *p
= skip_string(str2
,1);
1550 int uLevel
= SVAL(p
,0);
1551 int buf_len
= SVAL(p
,2);
1553 int count
=lp_numservices();
1554 int total
=0,counted
=0;
1555 BOOL missed
= False
;
1557 int data_len
, fixed_len
, string_len
;
1558 int f_len
= 0, s_len
= 0;
1560 if (!prefix_ok(str1
,"WrLeh")) return False
;
1561 if (!check_share_info(uLevel
,str2
)) return False
;
1563 data_len
= fixed_len
= string_len
= 0;
1564 for (i
=0;i
<count
;i
++)
1565 if (lp_browseable(i
) && lp_snum_ok(i
))
1568 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1569 if (data_len
<= buf_len
)
1573 string_len
+= s_len
;
1578 *rdata_len
= fixed_len
+ string_len
;
1579 *rdata
= REALLOC(*rdata
,*rdata_len
);
1580 memset(*rdata
,0,*rdata_len
);
1582 p2
= (*rdata
) + fixed_len
; /* auxillery data (strings) will go here */
1586 for (i
= 0; i
< count
;i
++)
1587 if (lp_browseable(i
) && lp_snum_ok(i
))
1588 if (fill_share_info(conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0)
1592 *rparam
= REALLOC(*rparam
,*rparam_len
);
1593 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1595 SSVAL(*rparam
,4,counted
);
1596 SSVAL(*rparam
,6,total
);
1598 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1599 counted
,total
,uLevel
,
1600 buf_len
,*rdata_len
,mdrcnt
));
1606 /****************************************************************************
1607 get the time of day info
1608 ****************************************************************************/
1609 static BOOL
api_NetRemoteTOD(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
)
1616 *rparam
= REALLOC(*rparam
,*rparam_len
);
1619 *rdata
= REALLOC(*rdata
,*rdata_len
);
1621 SSVAL(*rparam
,0,NERR_Success
);
1622 SSVAL(*rparam
,2,0); /* converter word */
1628 time_t unixdate
= time(NULL
);
1630 put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
1631 by NT in a "net time" operation,
1632 it seems to ignore the one below */
1634 /* the client expects to get localtime, not GMT, in this bit
1635 (I think, this needs testing) */
1636 t
= LocalTime(&unixdate
);
1638 SIVAL(p
,4,0); /* msecs ? */
1639 CVAL(p
,8) = t
->tm_hour
;
1640 CVAL(p
,9) = t
->tm_min
;
1641 CVAL(p
,10) = t
->tm_sec
;
1642 CVAL(p
,11) = 0; /* hundredths of seconds */
1643 SSVALS(p
,12,TimeDiff(unixdate
)/60); /* timezone in minutes from GMT */
1644 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
1645 CVAL(p
,16) = t
->tm_mday
;
1646 CVAL(p
,17) = t
->tm_mon
+ 1;
1647 SSVAL(p
,18,1900+t
->tm_year
);
1648 CVAL(p
,20) = t
->tm_wday
;
1655 /****************************************************************************
1656 set the user password
1657 ****************************************************************************/
1658 static BOOL
api_SetUserPassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1659 int mdrcnt
,int mprcnt
,
1660 char **rdata
,char **rparam
,
1661 int *rdata_len
,int *rparam_len
)
1663 char *p
= skip_string(param
+2,2);
1665 fstring pass1
,pass2
;
1669 p
= skip_string(p
,1);
1672 memcpy(pass2
,p
+16,16);
1675 *rparam
= REALLOC(*rparam
,*rparam_len
);
1679 SSVAL(*rparam
,0,NERR_badpass
);
1680 SSVAL(*rparam
,2,0); /* converter word */
1682 DEBUG(3,("Set password for <%s>\n",user
));
1685 * Pass the user through the NT -> unix user mapping
1689 (void)map_username(user
);
1692 * Do any UNIX username case mangling.
1694 (void)Get_Pwnam( user
, True
);
1697 * Attempt the plaintext password change first.
1698 * Older versions of Windows seem to do this.
1701 if (password_ok(user
, pass1
,strlen(pass1
),NULL
) &&
1702 chgpasswd(user
,pass1
,pass2
,False
))
1704 SSVAL(*rparam
,0,NERR_Success
);
1708 * If the plaintext change failed, attempt
1709 * the encrypted. NT will generate this
1710 * after trying the samr method.
1713 if(SVAL(*rparam
,0) != NERR_Success
)
1715 struct smb_passwd
*sampw
= NULL
;
1717 if(check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &sampw
) &&
1718 change_lanman_password(sampw
,(unsigned char *)pass1
,(unsigned char *)pass2
))
1720 SSVAL(*rparam
,0,NERR_Success
);
1724 bzero(pass1
,sizeof(fstring
));
1725 bzero(pass2
,sizeof(fstring
));
1730 /****************************************************************************
1731 Set the user password (SamOEM version - gets plaintext).
1732 ****************************************************************************/
1734 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1735 int mdrcnt
,int mprcnt
,
1736 char **rdata
,char **rparam
,
1737 int *rdata_len
,int *rparam_len
)
1740 char *p
= param
+ 2;
1742 *rparam
= REALLOC(*rparam
,*rparam_len
);
1746 SSVAL(*rparam
,0,NERR_badpass
);
1749 * Check the parameter definition is correct.
1751 if(!strequal(param
+ 2, "zsT")) {
1752 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param
+ 2));
1755 p
= skip_string(p
, 1);
1757 if(!strequal(p
, "B516B16")) {
1758 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
1761 p
= skip_string(p
,1);
1764 p
= skip_string(p
,1);
1766 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
1769 * Pass the user through the NT -> unix user mapping
1773 (void)map_username(user
);
1776 * Do any UNIX username case mangling.
1778 (void)Get_Pwnam( user
, True
);
1780 if (pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
))
1782 SSVAL(*rparam
,0,NERR_Success
);
1788 /****************************************************************************
1791 ****************************************************************************/
1792 static BOOL
api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1793 int mdrcnt
,int mprcnt
,
1794 char **rdata
,char **rparam
,
1795 int *rdata_len
,int *rparam_len
)
1797 int function
= SVAL(param
,0);
1798 char *str1
= param
+2;
1799 char *str2
= skip_string(str1
,1);
1800 char *p
= skip_string(str2
,1);
1804 printjob_decode(SVAL(p
,0), &snum
, &jobid
);
1806 /* check it's a supported varient */
1807 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
1811 *rparam
= REALLOC(*rparam
,*rparam_len
);
1815 SSVAL(*rparam
,0,NERR_Success
);
1817 if (snum
>= 0 && VALID_SNUM(snum
))
1819 print_queue_struct
*queue
=NULL
;
1821 count
= get_printqueue(snum
,conn
,&queue
,NULL
);
1823 for (i
=0;i
<count
;i
++)
1824 if ((queue
[i
].job
&0xFF) == jobid
)
1827 case 81: /* delete */
1828 DEBUG(3,("Deleting queue entry %d\n",queue
[i
].job
));
1829 del_printqueue(conn
,snum
,queue
[i
].job
);
1831 case 82: /* pause */
1832 case 83: /* resume */
1833 DEBUG(3,("%s queue entry %d\n",
1834 (function
==82?"pausing":"resuming"),queue
[i
].job
));
1835 status_printjob(conn
,snum
,queue
[i
].job
,
1836 (function
==82?LPQ_PAUSED
:LPQ_QUEUED
));
1843 SSVAL(*rparam
,0,NERR_JobNotFound
);
1845 if (queue
) free(queue
);
1848 SSVAL(*rparam
,2,0); /* converter word */
1853 /****************************************************************************
1854 Purge a print queue - or pause or resume it.
1855 ****************************************************************************/
1856 static BOOL
api_WPrintQueuePurge(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1857 int mdrcnt
,int mprcnt
,
1858 char **rdata
,char **rparam
,
1859 int *rdata_len
,int *rparam_len
)
1861 int function
= SVAL(param
,0);
1862 char *str1
= param
+2;
1863 char *str2
= skip_string(str1
,1);
1864 char *QueueName
= skip_string(str2
,1);
1867 /* check it's a supported varient */
1868 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
1872 *rparam
= REALLOC(*rparam
,*rparam_len
);
1876 SSVAL(*rparam
,0,NERR_Success
);
1877 SSVAL(*rparam
,2,0); /* converter word */
1879 snum
= lp_servicenumber(QueueName
);
1880 if (snum
< 0 && pcap_printername_ok(QueueName
,NULL
)) {
1881 int pnum
= lp_servicenumber(PRINTERS_NAME
);
1883 lp_add_printer(QueueName
,pnum
);
1884 snum
= lp_servicenumber(QueueName
);
1888 if (snum
>= 0 && VALID_SNUM(snum
)) {
1892 case 74: /* Pause queue */
1893 case 75: /* Resume queue */
1894 status_printqueue(conn
,snum
,(function
==74?LPSTAT_STOPPED
:LPSTAT_OK
));
1895 DEBUG(3,("Print queue %s, queue=%s\n",
1896 (function
==74?"pause":"resume"),QueueName
));
1898 case 103: /* Purge */
1900 print_queue_struct
*queue
=NULL
;
1902 count
= get_printqueue(snum
,conn
,&queue
,NULL
);
1903 for (i
= 0; i
< count
; i
++)
1904 del_printqueue(conn
,snum
,queue
[i
].job
);
1906 if (queue
) free(queue
);
1907 DEBUG(3,("Print queue purge, queue=%s\n",QueueName
));
1917 /****************************************************************************
1918 set the property of a print job (undocumented?)
1919 ? function = 0xb -> set name of print job
1920 ? function = 0x6 -> move print job up/down
1921 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1922 or <WWsTP> <WB21BB16B10zWWzDDz>
1923 ****************************************************************************/
1924 static int check_printjob_info(struct pack_desc
* desc
,
1925 int uLevel
, char* id
)
1927 desc
->subformat
= NULL
;
1929 case 0: desc
->format
= "W"; break;
1930 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
1931 case 2: desc
->format
= "WWzWWDDzz"; break;
1932 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
1933 default: return False
;
1935 if (strcmp(desc
->format
,id
) != 0) return False
;
1939 static BOOL
api_PrintJobInfo(connection_struct
*conn
,uint16 vuid
,char *param
,char *data
,
1940 int mdrcnt
,int mprcnt
,
1941 char **rdata
,char **rparam
,
1942 int *rdata_len
,int *rparam_len
)
1944 struct pack_desc desc
;
1945 char *str1
= param
+2;
1946 char *str2
= skip_string(str1
,1);
1947 char *p
= skip_string(str2
,1);
1949 int uLevel
= SVAL(p
,2);
1950 int function
= SVAL(p
,4); /* what is this ?? */
1955 printjob_decode(SVAL(p
,0), &snum
, &jobid
);
1958 *rparam
= REALLOC(*rparam
,*rparam_len
);
1962 /* check it's a supported varient */
1963 if ((strcmp(str1
,"WWsTP")) ||
1964 (!check_printjob_info(&desc
,uLevel
,str2
)))
1968 case 0x6: /* change job place in the queue,
1969 data gives the new place */
1970 if (snum
>= 0 && VALID_SNUM(snum
)) {
1971 print_queue_struct
*queue
=NULL
;
1975 count
= get_printqueue(snum
,conn
,&queue
,NULL
);
1976 for (i
=0;i
<count
;i
++) /* find job */
1977 if ((queue
[i
].job
&0xFF) == jobid
) break;
1980 desc
.errcode
=NERR_JobNotFound
;
1981 if (queue
) free(queue
);
1983 desc
.errcode
=NERR_Success
;
1987 int place
= SVAL(data
,0);
1988 /* we currently have no way of
1989 doing this. Can any unix do it? */
1990 if (i
< place
) /* move down */;
1991 else if (i
> place
) /* move up */;
1994 desc
.errcode
=NERR_notsupported
; /* not yet
1996 if (queue
) free(queue
);
1999 desc
.errcode
=NERR_JobNotFound
;
2003 case 0xb: /* change print job name, data gives the name */
2004 /* jobid, snum should be zero */
2005 if (isalpha((int)*s
)) {
2008 while (l
<64 && *s
) {
2009 if (issafe(*s
)) name
[l
++] = *s
;
2014 DEBUG(3,("Setting print name to %s\n",name
));
2016 fsp
= file_find_print();
2019 connection_struct
*fconn
= fsp
->conn
;
2022 if (!become_user(fconn
,vuid
) ||
2023 !become_service(fconn
,True
))
2026 if (dos_rename(fsp
->fsp_name
,name
) == 0) {
2027 string_set(&fsp
->fsp_name
,name
);
2032 desc
.errcode
=NERR_Success
;
2035 default: /* not implemented */
2039 SSVALS(*rparam
,0,desc
.errcode
);
2040 SSVAL(*rparam
,2,0); /* converter word */
2046 /****************************************************************************
2047 get info about the server
2048 ****************************************************************************/
2049 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2050 int mdrcnt
,int mprcnt
,
2051 char **rdata
,char **rparam
,
2052 int *rdata_len
,int *rparam_len
)
2054 char *str1
= param
+2;
2055 char *str2
= skip_string(str1
,1);
2056 char *p
= skip_string(str2
,1);
2057 int uLevel
= SVAL(p
,0);
2061 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2063 /* check it's a supported varient */
2064 if (!prefix_ok(str1
,"WrLh")) return False
;
2067 if (strcmp(str2
,"B16") != 0) return False
;
2071 if (strcmp(str2
,"B16BBDz") != 0) return False
;
2075 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2080 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2085 if (strcmp(str2
,"DN") != 0) return False
;
2089 if (strcmp(str2
,"B16BBDzWWzzz") != 0) return False
;
2092 default: return False
;
2095 *rdata_len
= mdrcnt
;
2096 *rdata
= REALLOC(*rdata
,*rdata_len
);
2099 p2
= p
+ struct_len
;
2101 StrnCpy(p
,local_machine
,16);
2107 struct srv_info_struct
*servers
=NULL
;
2110 uint32 servertype
= lp_default_server_announce();
2112 pstrcpy(comment
,lp_serverstring());
2114 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,global_myworkgroup
))>0) {
2115 for (i
=0;i
<count
;i
++)
2116 if (strequal(servers
[i
].name
,local_machine
))
2118 servertype
= servers
[i
].type
;
2119 pstrcpy(comment
,servers
[i
].comment
);
2122 if (servers
) free(servers
);
2124 SCVAL(p
,0,lp_major_announce_version());
2125 SCVAL(p
,1,lp_minor_announce_version());
2126 SIVAL(p
,2,servertype
);
2128 if (mdrcnt
== struct_len
) {
2131 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2132 standard_sub(conn
,comment
);
2133 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2134 p2
= skip_string(p2
,1);
2139 return False
; /* not yet implemented */
2142 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2145 *rparam
= REALLOC(*rparam
,*rparam_len
);
2146 SSVAL(*rparam
,0,NERR_Success
);
2147 SSVAL(*rparam
,2,0); /* converter word */
2148 SSVAL(*rparam
,4,*rdata_len
);
2154 /****************************************************************************
2155 get info about the server
2156 ****************************************************************************/
2157 static BOOL
api_NetWkstaGetInfo(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 char *str1
= param
+2;
2163 char *str2
= skip_string(str1
,1);
2164 char *p
= skip_string(str2
,1);
2166 extern pstring sesssetup_user
;
2167 int level
= SVAL(p
,0);
2169 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2172 *rparam
= REALLOC(*rparam
,*rparam_len
);
2174 /* check it's a supported varient */
2175 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz")))
2178 *rdata_len
= mdrcnt
+ 1024;
2179 *rdata
= REALLOC(*rdata
,*rdata_len
);
2181 SSVAL(*rparam
,0,NERR_Success
);
2182 SSVAL(*rparam
,2,0); /* converter word */
2188 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2189 pstrcpy(p2
,local_machine
);
2191 p2
= skip_string(p2
,1);
2194 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2195 pstrcpy(p2
,sesssetup_user
);
2196 p2
= skip_string(p2
,1);
2199 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2200 pstrcpy(p2
,global_myworkgroup
);
2202 p2
= skip_string(p2
,1);
2205 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2206 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2209 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2210 pstrcpy(p2
,global_myworkgroup
); /* don't know. login domain?? */
2211 p2
= skip_string(p2
,1);
2214 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
2216 p2
= skip_string(p2
,1);
2219 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2221 SSVAL(*rparam
,4,*rdata_len
);
2226 /****************************************************************************
2227 get info about a user
2229 struct user_info_11 {
2230 char usri11_name[21]; 0-20
2232 char *usri11_comment; 22-25
2233 char *usri11_usr_comment; 26-29
2234 unsigned short usri11_priv; 30-31
2235 unsigned long usri11_auth_flags; 32-35
2236 long usri11_password_age; 36-39
2237 char *usri11_homedir; 40-43
2238 char *usri11_parms; 44-47
2239 long usri11_last_logon; 48-51
2240 long usri11_last_logoff; 52-55
2241 unsigned short usri11_bad_pw_count; 56-57
2242 unsigned short usri11_num_logons; 58-59
2243 char *usri11_logon_server; 60-63
2244 unsigned short usri11_country_code; 64-65
2245 char *usri11_workstations; 66-69
2246 unsigned long usri11_max_storage; 70-73
2247 unsigned short usri11_units_per_week; 74-75
2248 unsigned char *usri11_logon_hours; 76-79
2249 unsigned short usri11_code_page; 80-81
2254 usri11_name specifies the user name for which information is retireved
2256 usri11_pad aligns the next data structure element to a word boundary
2258 usri11_comment is a null terminated ASCII comment
2260 usri11_user_comment is a null terminated ASCII comment about the user
2262 usri11_priv specifies the level of the privilege assigned to the user.
2263 The possible values are:
2265 Name Value Description
2266 USER_PRIV_GUEST 0 Guest privilege
2267 USER_PRIV_USER 1 User privilege
2268 USER_PRV_ADMIN 2 Administrator privilege
2270 usri11_auth_flags specifies the account operator privileges. The
2271 possible values are:
2273 Name Value Description
2274 AF_OP_PRINT 0 Print operator
2277 Leach, Naik [Page 28]
\f
2280 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2283 AF_OP_COMM 1 Communications operator
2284 AF_OP_SERVER 2 Server operator
2285 AF_OP_ACCOUNTS 3 Accounts operator
2288 usri11_password_age specifies how many seconds have elapsed since the
2289 password was last changed.
2291 usri11_home_dir points to a null terminated ASCII string that contains
2292 the path name of the user's home directory.
2294 usri11_parms points to a null terminated ASCII string that is set
2295 aside for use by applications.
2297 usri11_last_logon specifies the time when the user last logged on.
2298 This value is stored as the number of seconds elapsed since
2299 00:00:00, January 1, 1970.
2301 usri11_last_logoff specifies the time when the user last logged off.
2302 This value is stored as the number of seconds elapsed since
2303 00:00:00, January 1, 1970. A value of 0 means the last logoff
2306 usri11_bad_pw_count specifies the number of incorrect passwords
2307 entered since the last successful logon.
2309 usri11_log1_num_logons specifies the number of times this user has
2310 logged on. A value of -1 means the number of logons is unknown.
2312 usri11_logon_server points to a null terminated ASCII string that
2313 contains the name of the server to which logon requests are sent.
2314 A null string indicates logon requests should be sent to the
2317 usri11_country_code specifies the country code for the user's language
2320 usri11_workstations points to a null terminated ASCII string that
2321 contains the names of workstations the user may log on from.
2322 There may be up to 8 workstations, with the names separated by
2323 commas. A null strings indicates there are no restrictions.
2325 usri11_max_storage specifies the maximum amount of disk space the user
2326 can occupy. A value of 0xffffffff indicates there are no
2329 usri11_units_per_week specifies the equal number of time units into
2330 which a week is divided. This value must be equal to 168.
2332 usri11_logon_hours points to a 21 byte (168 bits) string that
2333 specifies the time during which the user can log on. Each bit
2334 represents one unique hour in a week. The first bit (bit 0, word
2335 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2339 Leach, Naik [Page 29]
\f
2342 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2345 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2346 are no restrictions.
2348 usri11_code_page specifies the code page for the user's language of
2351 All of the pointers in this data structure need to be treated
2352 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2353 to be ignored. The converter word returned in the parameters section
2354 needs to be subtracted from the lower 16 bits to calculate an offset
2355 into the return buffer where this ASCII string resides.
2357 There is no auxiliary data in the response.
2359 ****************************************************************************/
2361 #define usri11_name 0
2362 #define usri11_pad 21
2363 #define usri11_comment 22
2364 #define usri11_usr_comment 26
2365 #define usri11_full_name 30
2366 #define usri11_priv 34
2367 #define usri11_auth_flags 36
2368 #define usri11_password_age 40
2369 #define usri11_homedir 44
2370 #define usri11_parms 48
2371 #define usri11_last_logon 52
2372 #define usri11_last_logoff 56
2373 #define usri11_bad_pw_count 60
2374 #define usri11_num_logons 62
2375 #define usri11_logon_server 64
2376 #define usri11_country_code 68
2377 #define usri11_workstations 70
2378 #define usri11_max_storage 74
2379 #define usri11_units_per_week 78
2380 #define usri11_logon_hours 80
2381 #define usri11_code_page 84
2382 #define usri11_end 86
2384 #define USER_PRIV_GUEST 0
2385 #define USER_PRIV_USER 1
2386 #define USER_PRIV_ADMIN 2
2388 #define AF_OP_PRINT 0
2389 #define AF_OP_COMM 1
2390 #define AF_OP_SERVER 2
2391 #define AF_OP_ACCOUNTS 3
2394 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2395 int mdrcnt
,int mprcnt
,
2396 char **rdata
,char **rparam
,
2397 int *rdata_len
,int *rparam_len
)
2399 char *str1
= param
+2;
2400 char *str2
= skip_string(str1
,1);
2401 char *UserName
= skip_string(str2
,1);
2402 char *p
= skip_string(UserName
,1);
2403 int uLevel
= SVAL(p
,0);
2406 /* get NIS home of a previously validated user - simeon */
2407 /* With share level security vuid will always be zero.
2408 Don't depend on vuser being non-null !!. JRA */
2409 user_struct
*vuser
= get_valid_user_struct(vuid
);
2411 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
, vuser
->name
));
2414 *rparam
= REALLOC(*rparam
,*rparam_len
);
2416 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
2418 /* check it's a supported variant */
2419 if (strcmp(str1
,"zWrLh") != 0) return False
;
2422 case 0: p2
= "B21"; break;
2423 case 1: p2
= "B21BB16DWzzWz"; break;
2424 case 2: p2
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2425 case 10: p2
= "B21Bzzz"; break;
2426 case 11: p2
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2427 default: return False
;
2430 if (strcmp(p2
,str2
) != 0) return False
;
2432 *rdata_len
= mdrcnt
+ 1024;
2433 *rdata
= REALLOC(*rdata
,*rdata_len
);
2435 SSVAL(*rparam
,0,NERR_Success
);
2436 SSVAL(*rparam
,2,0); /* converter word */
2439 p2
= p
+ usri11_end
;
2442 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
2446 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
2451 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
2452 pstrcpy(p2
,"Comment");
2453 p2
= skip_string(p2
,1);
2455 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
2456 pstrcpy(p2
,"UserComment");
2457 p2
= skip_string(p2
,1);
2459 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2460 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
2461 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->real_name
: UserName
));
2462 p2
= skip_string(p2
,1);
2465 if (uLevel
== 11) /* modelled after NTAS 3.51 reply */
2467 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2468 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
2469 SIVALS(p
,usri11_password_age
,-1); /* password age */
2470 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
2471 pstrcpy(p2
, lp_logon_path());
2472 p2
= skip_string(p2
,1);
2473 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
2475 p2
= skip_string(p2
,1);
2476 SIVAL(p
,usri11_last_logon
,0); /* last logon */
2477 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
2478 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
2479 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
2480 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
2481 pstrcpy(p2
,"\\\\*");
2482 p2
= skip_string(p2
,1);
2483 SSVAL(p
,usri11_country_code
,0); /* country code */
2485 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
2487 p2
= skip_string(p2
,1);
2489 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
2490 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
2491 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
2493 /* a simple way to get logon hours at all times. */
2495 SCVAL(p2
,21,0); /* fix zero termination */
2496 p2
= skip_string(p2
,1);
2498 SSVAL(p
,usri11_code_page
,0); /* code page */
2500 if (uLevel
== 1 || uLevel
== 2)
2502 memset(p
+22,' ',16); /* password */
2503 SIVALS(p
,38,-1); /* password age */
2505 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2506 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
2507 pstrcpy(p2
,lp_logon_path());
2508 p2
= skip_string(p2
,1);
2509 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
2511 SSVAL(p
,52,0); /* flags */
2512 SIVAL(p
,54,0); /* script_path */
2515 SIVAL(p
,60,0); /* auth_flags */
2516 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
2517 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->real_name
: UserName
));
2518 p2
= skip_string(p2
,1);
2519 SIVAL(p
,68,0); /* urs_comment */
2520 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
2522 p2
= skip_string(p2
,1);
2523 SIVAL(p
,76,0); /* workstations */
2524 SIVAL(p
,80,0); /* last_logon */
2525 SIVAL(p
,84,0); /* last_logoff */
2526 SIVALS(p
,88,-1); /* acct_expires */
2527 SIVALS(p
,92,-1); /* max_storage */
2528 SSVAL(p
,96,168); /* units_per_week */
2529 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
2532 SSVALS(p
,102,-1); /* bad_pw_count */
2533 SSVALS(p
,104,-1); /* num_logons */
2534 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
2535 pstrcpy(p2
,"\\\\%L");
2536 standard_sub_basic(p2
);
2537 p2
= skip_string(p2
,1);
2538 SSVAL(p
,110,49); /* country_code */
2539 SSVAL(p
,112,860); /* code page */
2543 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2545 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
2550 /*******************************************************************
2551 get groups that a user is a member of
2552 ******************************************************************/
2553 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2554 int mdrcnt
,int mprcnt
,
2555 char **rdata
,char **rparam
,
2556 int *rdata_len
,int *rparam_len
)
2558 char *str1
= param
+2;
2559 char *str2
= skip_string(str1
,1);
2560 char *UserName
= skip_string(str2
,1);
2561 char *p
= skip_string(UserName
,1);
2562 int uLevel
= SVAL(p
,0);
2567 *rparam
= REALLOC(*rparam
,*rparam_len
);
2569 /* check it's a supported varient */
2570 if (strcmp(str1
,"zWrLeh") != 0) return False
;
2572 case 0: p2
= "B21"; break;
2573 default: return False
;
2575 if (strcmp(p2
,str2
) != 0) return False
;
2577 *rdata_len
= mdrcnt
+ 1024;
2578 *rdata
= REALLOC(*rdata
,*rdata_len
);
2580 SSVAL(*rparam
,0,NERR_Success
);
2581 SSVAL(*rparam
,2,0); /* converter word */
2585 /* XXXX we need a real SAM database some day */
2586 pstrcpy(p
,"Users"); p
+= 21; count
++;
2587 pstrcpy(p
,"Domain Users"); p
+= 21; count
++;
2588 pstrcpy(p
,"Guests"); p
+= 21; count
++;
2589 pstrcpy(p
,"Domain Guests"); p
+= 21; count
++;
2591 *rdata_len
= PTR_DIFF(p
,*rdata
);
2593 SSVAL(*rparam
,4,count
); /* is this right?? */
2594 SSVAL(*rparam
,6,count
); /* is this right?? */
2600 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2601 int mdrcnt
,int mprcnt
,
2602 char **rdata
,char **rparam
,
2603 int *rdata_len
,int *rparam_len
)
2605 char *str1
= param
+2;
2606 char *str2
= skip_string(str1
,1);
2607 char *p
= skip_string(str2
,1);
2609 struct pack_desc desc
;
2616 bzero(&desc
,sizeof(desc
));
2618 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
2620 /* check it's a supported varient */
2621 if (strcmp(str1
,"OOWb54WrLh") != 0) return False
;
2622 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) return False
;
2623 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2625 desc
.buflen
= mdrcnt
;
2626 desc
.subformat
= NULL
;
2629 if (init_package(&desc
,1,0))
2631 PACKI(&desc
,"W",0); /* code */
2632 PACKS(&desc
,"B21",name
); /* eff. name */
2633 PACKS(&desc
,"B",""); /* pad */
2635 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2636 PACKI(&desc
,"D",0); /* auth flags XXX */
2637 PACKI(&desc
,"W",0); /* num logons */
2638 PACKI(&desc
,"W",0); /* bad pw count */
2639 PACKI(&desc
,"D",0); /* last logon */
2640 PACKI(&desc
,"D",-1); /* last logoff */
2641 PACKI(&desc
,"D",-1); /* logoff time */
2642 PACKI(&desc
,"D",-1); /* kickoff time */
2643 PACKI(&desc
,"D",0); /* password age */
2644 PACKI(&desc
,"D",0); /* password can change */
2645 PACKI(&desc
,"D",-1); /* password must change */
2648 fstrcpy(mypath
,"\\\\");
2649 fstrcat(mypath
,local_machine
);
2651 PACKS(&desc
,"z",mypath
); /* computer */
2653 PACKS(&desc
,"z",global_myworkgroup
);/* domain */
2655 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2656 /* made sure all macros are fully substituted and available */
2657 logon_script
= lp_logon_script();
2658 standard_sub( conn
, logon_script
);
2659 PACKS(&desc
,"z", logon_script
); /* script path */
2660 /* End of JHT mods */
2662 PACKI(&desc
,"D",0x00000000); /* reserved */
2665 *rdata_len
= desc
.usedlen
;
2667 *rparam
= REALLOC(*rparam
,*rparam_len
);
2668 SSVALS(*rparam
,0,desc
.errcode
);
2670 SSVAL(*rparam
,4,desc
.neededlen
);
2672 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
2677 /****************************************************************************
2678 api_WAccessGetUserPerms
2679 ****************************************************************************/
2680 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2681 int mdrcnt
,int mprcnt
,
2682 char **rdata
,char **rparam
,
2683 int *rdata_len
,int *rparam_len
)
2685 char *str1
= param
+2;
2686 char *str2
= skip_string(str1
,1);
2687 char *user
= skip_string(str2
,1);
2688 char *resource
= skip_string(user
,1);
2690 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
2692 /* check it's a supported varient */
2693 if (strcmp(str1
,"zzh") != 0) return False
;
2694 if (strcmp(str2
,"") != 0) return False
;
2697 *rparam
= REALLOC(*rparam
,*rparam_len
);
2698 SSVALS(*rparam
,0,0); /* errorcode */
2699 SSVAL(*rparam
,2,0); /* converter word */
2700 SSVAL(*rparam
,4,0x7f); /* permission flags */
2705 /****************************************************************************
2706 api_WPrintJobEnumerate
2707 ****************************************************************************/
2708 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2709 int mdrcnt
,int mprcnt
,
2710 char **rdata
,char **rparam
,
2711 int *rdata_len
,int *rparam_len
)
2713 char *str1
= param
+2;
2714 char *str2
= skip_string(str1
,1);
2715 char *p
= skip_string(str2
,1);
2721 struct pack_desc desc
;
2722 print_queue_struct
*queue
=NULL
;
2723 print_status_struct status
;
2727 bzero(&desc
,sizeof(desc
));
2728 bzero(&status
,sizeof(status
));
2730 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
2732 /* check it's a supported varient */
2733 if (strcmp(str1
,"WWrLh") != 0) return False
;
2734 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2736 printjob_decode(SVAL(p
,0), &snum
, &job
);
2738 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2740 count
= get_printqueue(snum
,conn
,&queue
,&status
);
2741 for (i
= 0; i
< count
; i
++) {
2742 if ((queue
[i
].job
& 0xFF) == job
) break;
2744 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2746 desc
.buflen
= mdrcnt
;
2748 if (init_package(&desc
,1,0)) {
2750 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
2751 *rdata_len
= desc
.usedlen
;
2754 desc
.errcode
= NERR_JobNotFound
;
2760 *rparam
= REALLOC(*rparam
,*rparam_len
);
2761 SSVALS(*rparam
,0,desc
.errcode
);
2763 SSVAL(*rparam
,4,desc
.neededlen
);
2765 if (queue
) free(queue
);
2767 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
2771 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2772 int mdrcnt
,int mprcnt
,
2773 char **rdata
,char **rparam
,
2774 int *rdata_len
,int *rparam_len
)
2776 char *str1
= param
+2;
2777 char *str2
= skip_string(str1
,1);
2778 char *p
= skip_string(str2
,1);
2784 struct pack_desc desc
;
2785 print_queue_struct
*queue
=NULL
;
2786 print_status_struct status
;
2788 bzero(&desc
,sizeof(desc
));
2789 bzero(&status
,sizeof(status
));
2791 p
= skip_string(p
,1);
2794 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
2796 /* check it's a supported varient */
2797 if (strcmp(str1
,"zWrLeh") != 0) return False
;
2798 if (uLevel
> 2) return False
; /* defined only for uLevel 0,1,2 */
2799 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2801 snum
= lp_servicenumber(name
);
2802 if (snum
< 0 && pcap_printername_ok(name
,NULL
)) {
2803 int pnum
= lp_servicenumber(PRINTERS_NAME
);
2805 lp_add_printer(name
,pnum
);
2806 snum
= lp_servicenumber(name
);
2810 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2812 count
= get_printqueue(snum
,conn
,&queue
,&status
);
2813 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2815 desc
.buflen
= mdrcnt
;
2817 if (init_package(&desc
,count
,0)) {
2819 for (i
= 0; i
< count
; i
++) {
2820 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
2821 if (desc
.errcode
== NERR_Success
) succnt
= i
+1;
2825 *rdata_len
= desc
.usedlen
;
2828 *rparam
= REALLOC(*rparam
,*rparam_len
);
2829 SSVALS(*rparam
,0,desc
.errcode
);
2831 SSVAL(*rparam
,4,succnt
);
2832 SSVAL(*rparam
,6,count
);
2834 if (queue
) free(queue
);
2836 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
2840 static int check_printdest_info(struct pack_desc
* desc
,
2841 int uLevel
, char* id
)
2843 desc
->subformat
= NULL
;
2845 case 0: desc
->format
= "B9"; break;
2846 case 1: desc
->format
= "B9B21WWzW"; break;
2847 case 2: desc
->format
= "z"; break;
2848 case 3: desc
->format
= "zzzWWzzzWW"; break;
2849 default: return False
;
2851 if (strcmp(desc
->format
,id
) != 0) return False
;
2855 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
2856 struct pack_desc
* desc
)
2859 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
2860 buf
[sizeof(buf
)-1] = 0;
2863 PACKS(desc
,"B9",buf
); /* szName */
2865 PACKS(desc
,"B21",""); /* szUserName */
2866 PACKI(desc
,"W",0); /* uJobId */
2867 PACKI(desc
,"W",0); /* fsStatus */
2868 PACKS(desc
,"z",""); /* pszStatus */
2869 PACKI(desc
,"W",0); /* time */
2872 if (uLevel
== 2 || uLevel
== 3) {
2873 PACKS(desc
,"z",buf
); /* pszPrinterName */
2875 PACKS(desc
,"z",""); /* pszUserName */
2876 PACKS(desc
,"z",""); /* pszLogAddr */
2877 PACKI(desc
,"W",0); /* uJobId */
2878 PACKI(desc
,"W",0); /* fsStatus */
2879 PACKS(desc
,"z",""); /* pszStatus */
2880 PACKS(desc
,"z",""); /* pszComment */
2881 PACKS(desc
,"z","NULL"); /* pszDrivers */
2882 PACKI(desc
,"W",0); /* time */
2883 PACKI(desc
,"W",0); /* pad1 */
2888 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2889 int mdrcnt
,int mprcnt
,
2890 char **rdata
,char **rparam
,
2891 int *rdata_len
,int *rparam_len
)
2893 char *str1
= param
+2;
2894 char *str2
= skip_string(str1
,1);
2895 char *p
= skip_string(str2
,1);
2896 char* PrinterName
= p
;
2898 struct pack_desc desc
;
2901 bzero(&desc
,sizeof(desc
));
2903 p
= skip_string(p
,1);
2906 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
2908 /* check it's a supported varient */
2909 if (strcmp(str1
,"zWrLh") != 0) return False
;
2910 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
2912 snum
= lp_servicenumber(PrinterName
);
2913 if (snum
< 0 && pcap_printername_ok(PrinterName
,NULL
)) {
2914 int pnum
= lp_servicenumber(PRINTERS_NAME
);
2916 lp_add_printer(PrinterName
,pnum
);
2917 snum
= lp_servicenumber(PrinterName
);
2923 desc
.errcode
= NERR_DestNotFound
;
2927 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2929 desc
.buflen
= mdrcnt
;
2930 if (init_package(&desc
,1,0)) {
2931 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
2933 *rdata_len
= desc
.usedlen
;
2937 *rparam
= REALLOC(*rparam
,*rparam_len
);
2938 SSVALS(*rparam
,0,desc
.errcode
);
2940 SSVAL(*rparam
,4,desc
.neededlen
);
2942 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
2946 static BOOL
api_WPrintDestEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2947 int mdrcnt
,int mprcnt
,
2948 char **rdata
,char **rparam
,
2949 int *rdata_len
,int *rparam_len
)
2951 char *str1
= param
+2;
2952 char *str2
= skip_string(str1
,1);
2953 char *p
= skip_string(str2
,1);
2957 struct pack_desc desc
;
2958 int services
= lp_numservices();
2960 bzero(&desc
,sizeof(desc
));
2964 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
2966 /* check it's a supported varient */
2967 if (strcmp(str1
,"WrLeh") != 0) return False
;
2968 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
2971 for (i
= 0; i
< services
; i
++)
2972 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
2975 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2977 desc
.buflen
= mdrcnt
;
2978 if (init_package(&desc
,queuecnt
,0)) {
2981 for (i
= 0; i
< services
; i
++) {
2982 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
2983 fill_printdest_info(conn
,i
,uLevel
,&desc
);
2985 if (desc
.errcode
== NERR_Success
) succnt
= n
;
2990 *rdata_len
= desc
.usedlen
;
2993 *rparam
= REALLOC(*rparam
,*rparam_len
);
2994 SSVALS(*rparam
,0,desc
.errcode
);
2996 SSVAL(*rparam
,4,succnt
);
2997 SSVAL(*rparam
,6,queuecnt
);
2999 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3003 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3004 int mdrcnt
,int mprcnt
,
3005 char **rdata
,char **rparam
,
3006 int *rdata_len
,int *rparam_len
)
3008 char *str1
= param
+2;
3009 char *str2
= skip_string(str1
,1);
3010 char *p
= skip_string(str2
,1);
3013 struct pack_desc desc
;
3015 bzero(&desc
,sizeof(desc
));
3019 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
3021 /* check it's a supported varient */
3022 if (strcmp(str1
,"WrLeh") != 0) return False
;
3023 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) return False
;
3025 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3027 desc
.buflen
= mdrcnt
;
3028 if (init_package(&desc
,1,0)) {
3029 PACKS(&desc
,"B41","NULL");
3032 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3034 *rdata_len
= desc
.usedlen
;
3037 *rparam
= REALLOC(*rparam
,*rparam_len
);
3038 SSVALS(*rparam
,0,desc
.errcode
);
3040 SSVAL(*rparam
,4,succnt
);
3043 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
3047 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3048 int mdrcnt
,int mprcnt
,
3049 char **rdata
,char **rparam
,
3050 int *rdata_len
,int *rparam_len
)
3052 char *str1
= param
+2;
3053 char *str2
= skip_string(str1
,1);
3054 char *p
= skip_string(str2
,1);
3057 struct pack_desc desc
;
3059 bzero(&desc
,sizeof(desc
));
3063 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
3065 /* check it's a supported varient */
3066 if (strcmp(str1
,"WrLeh") != 0) return False
;
3067 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) return False
;
3069 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3071 desc
.buflen
= mdrcnt
;
3073 if (init_package(&desc
,1,0)) {
3074 PACKS(&desc
,"B13","lpd");
3077 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3079 *rdata_len
= desc
.usedlen
;
3082 *rparam
= REALLOC(*rparam
,*rparam_len
);
3083 SSVALS(*rparam
,0,desc
.errcode
);
3085 SSVAL(*rparam
,4,succnt
);
3088 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
3092 static BOOL
api_WPrintPortEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3093 int mdrcnt
,int mprcnt
,
3094 char **rdata
,char **rparam
,
3095 int *rdata_len
,int *rparam_len
)
3097 char *str1
= param
+2;
3098 char *str2
= skip_string(str1
,1);
3099 char *p
= skip_string(str2
,1);
3102 struct pack_desc desc
;
3104 bzero(&desc
,sizeof(desc
));
3108 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
3110 /* check it's a supported varient */
3111 if (strcmp(str1
,"WrLeh") != 0) return False
;
3112 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) return False
;
3114 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3115 bzero(&desc
,sizeof(desc
));
3117 desc
.buflen
= mdrcnt
;
3119 if (init_package(&desc
,1,0)) {
3120 PACKS(&desc
,"B13","lp0");
3123 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3125 *rdata_len
= desc
.usedlen
;
3128 *rparam
= REALLOC(*rparam
,*rparam_len
);
3129 SSVALS(*rparam
,0,desc
.errcode
);
3131 SSVAL(*rparam
,4,succnt
);
3134 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
3138 static void api_rpc_trans_reply(char *outbuf
,
3142 send_trans_reply(outbuf
, p
->rhdr
.data
, NULL
, NULL
, 0, p
->file_offset
);
3144 if (mem_buf_len(p
->rhdr
.data
) <= p
->file_offset
)
3146 /* all of data was sent: no need to wait for SMBreadX calls */
3147 mem_free_data(p
->rhdr
.data
);
3148 mem_free_data(p
->rdata
.data
);
3149 mem_free_data(p
->rdata_i
.data
);
3153 /****************************************************************************
3154 WaitNamedPipeHandleState
3155 ****************************************************************************/
3156 static BOOL
api_WNPHS(char *outbuf
, pipes_struct
*p
, char *param
)
3160 if (!param
) return False
;
3162 priority
= param
[0] + (param
[1] << 8);
3163 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority
));
3165 if (wait_rpc_pipe_hnd_state(p
, priority
))
3167 /* now send the reply */
3168 send_trans_reply(outbuf
, NULL
, NULL
, NULL
, 0, p
->file_offset
);
3176 /****************************************************************************
3177 SetNamedPipeHandleState
3178 ****************************************************************************/
3179 static BOOL
api_SNPHS(char *outbuf
, pipes_struct
*p
, char *param
)
3183 if (!param
) return False
;
3185 id
= param
[0] + (param
[1] << 8);
3186 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id
));
3188 if (set_rpc_pipe_hnd_state(p
, id
))
3190 /* now send the reply */
3191 send_trans_reply(outbuf
, NULL
, NULL
, NULL
, 0, p
->file_offset
);
3199 /****************************************************************************
3200 when no reply is generated, indicate unsupported.
3201 ****************************************************************************/
3202 static BOOL
api_no_reply(char *outbuf
, int max_rdata_len
)
3204 struct mem_buf rparam
;
3206 mem_init(&rparam
, 0);
3207 mem_alloc_data(&rparam
, 4);
3209 rparam
.offset
.start
= 0;
3210 rparam
.offset
.end
= 4;
3213 SSVAL(rparam
.data
,0,NERR_notsupported
);
3214 SSVAL(rparam
.data
,2,0); /* converter word */
3216 DEBUG(3,("Unsupported API fd command\n"));
3218 /* now send the reply */
3219 send_trans_reply(outbuf
, NULL
, &rparam
, NULL
, 0, max_rdata_len
);
3221 mem_free_data(&rparam
);
3226 /****************************************************************************
3227 handle remote api calls delivered to a named pipe already opened.
3228 ****************************************************************************/
3229 static int api_fd_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,
3230 uint16
*setup
,char *data
,char *params
,
3231 int suwcnt
,int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
3237 pipes_struct
*p
= NULL
;
3240 DEBUG(5,("api_fd_reply\n"));
3242 /* make a static data parsing structure from the api_fd_reply data */
3243 prs_init(&pd
, 0, 4, 0, True
);
3244 mem_create(pd
.data
, data
, 0, tdscnt
, 0, False
);
3246 /* First find out the name of this file. */
3249 DEBUG(0,("Unexpected named pipe transaction.\n"));
3253 /* Get the file handle and hence the file name. */
3255 subcommand
= setup
[0];
3256 p
= get_rpc_pipe(pnum
);
3260 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3261 subcommand
, p
->name
, pnum
));
3263 /* record maximum data length that can be transmitted in an SMBtrans */
3264 p
->file_offset
= mdrcnt
;
3266 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3267 p
, p
->file_offset
));
3273 /* dce/rpc command */
3274 reply
= rpc_command(p
, &pd
);
3277 api_rpc_trans_reply(outbuf
, p
, &pd
);
3283 /* Wait Named Pipe Handle state */
3284 reply
= api_WNPHS(outbuf
, p
, params
);
3289 /* Set Named Pipe Handle state */
3290 reply
= api_SNPHS(outbuf
, p
, params
);
3297 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum
));
3300 mem_free_data(pd
.data
);
3304 return api_no_reply(outbuf
, mdrcnt
);
3309 /****************************************************************************
3310 the buffer was too small
3311 ****************************************************************************/
3312 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3313 int mdrcnt
,int mprcnt
,
3314 char **rdata
,char **rparam
,
3315 int *rdata_len
,int *rparam_len
)
3317 *rparam_len
= MIN(*rparam_len
,mprcnt
);
3318 *rparam
= REALLOC(*rparam
,*rparam_len
);
3322 SSVAL(*rparam
,0,NERR_BufTooSmall
);
3324 DEBUG(3,("Supplied buffer too small in API command\n"));
3330 /****************************************************************************
3331 the request is not supported
3332 ****************************************************************************/
3333 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3334 int mdrcnt
,int mprcnt
,
3335 char **rdata
,char **rparam
,
3336 int *rdata_len
,int *rparam_len
)
3339 *rparam
= REALLOC(*rparam
,*rparam_len
);
3343 SSVAL(*rparam
,0,NERR_notsupported
);
3344 SSVAL(*rparam
,2,0); /* converter word */
3346 DEBUG(3,("Unsupported API command\n"));
3358 BOOL (*fn
)(connection_struct
*,uint16
,char *,char *,
3359 int,int,char **,char **,int *,int *);
3361 } api_commands
[] = {
3362 {"RNetShareEnum", 0, api_RNetShareEnum
,0},
3363 {"RNetShareGetInfo", 1, api_RNetShareGetInfo
,0},
3364 {"RNetServerGetInfo", 13, api_RNetServerGetInfo
,0},
3365 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers
,0},
3366 {"RNetUserGetInfo", 56, api_RNetUserGetInfo
,0},
3367 {"NetUserGetGroups", 59, api_NetUserGetGroups
,0},
3368 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo
,0},
3369 {"DosPrintQEnum", 69, api_DosPrintQEnum
,0},
3370 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo
,0},
3371 {"WPrintQueuePause", 74, api_WPrintQueuePurge
,0},
3372 {"WPrintQueueResume", 75, api_WPrintQueuePurge
,0},
3373 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate
,0},
3374 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo
,0},
3375 {"RDosPrintJobDel", 81, api_RDosPrintJobDel
,0},
3376 {"RDosPrintJobPause", 82, api_RDosPrintJobDel
,0},
3377 {"RDosPrintJobResume",83, api_RDosPrintJobDel
,0},
3378 {"WPrintDestEnum", 84, api_WPrintDestEnum
,0},
3379 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo
,0},
3380 {"NetRemoteTOD", 91, api_NetRemoteTOD
,0},
3381 {"WPrintQueuePurge", 103, api_WPrintQueuePurge
,0},
3382 {"NetServerEnum", 104, api_RNetServerEnum
,0},
3383 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms
,0},
3384 {"SetUserPassword", 115, api_SetUserPassword
,0},
3385 {"WWkstaUserLogon", 132, api_WWkstaUserLogon
,0},
3386 {"PrintJobInfo", 147, api_PrintJobInfo
,0},
3387 {"WPrintDriverEnum", 205, api_WPrintDriverEnum
,0},
3388 {"WPrintQProcEnum", 206, api_WPrintQProcEnum
,0},
3389 {"WPrintPortEnum", 207, api_WPrintPortEnum
,0},
3390 {"SamOEMChangePassword", 214, api_SamOEMChangePassword
,0},
3391 {NULL
, -1, api_Unsupported
,0}};
3394 /****************************************************************************
3395 handle remote api calls
3396 ****************************************************************************/
3397 static int api_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,char *data
,char *params
,
3398 int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
3401 struct mem_buf rdata_buf
;
3402 struct mem_buf rparam_buf
;
3404 char *rparam
= NULL
;
3410 SMB_ASSERT(params
!= 0);
3412 api_command
= SVAL(params
,0);
3414 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3417 skip_string(params
+2,1),
3418 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
3420 for (i
=0;api_commands
[i
].name
;i
++)
3421 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
)
3423 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
3427 rdata
= (char *)malloc(1024); if (rdata
) bzero(rdata
,1024);
3428 rparam
= (char *)malloc(1024); if (rparam
) bzero(rparam
,1024);
3430 if(!rdata
|| !rparam
) {
3431 DEBUG(0,("api_reply: malloc fail !\n"));
3435 reply
= api_commands
[i
].fn(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3436 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3439 if (rdata_len
> mdrcnt
||
3440 rparam_len
> mprcnt
)
3442 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3443 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3447 /* if we get False back then it's actually unsupported */
3449 api_Unsupported(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3450 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3453 mem_create(&rdata_buf
, rdata
, 0, rdata_len
, 0, False
);
3454 mem_create(&rparam_buf
, rparam
, 0, rparam_len
, 0, False
);
3456 /* now send the reply */
3457 send_trans_reply(outbuf
, &rdata_buf
, &rparam_buf
, NULL
, 0, 0);
3459 if (rdata
) free(rdata
);
3460 if (rparam
) free(rparam
);
3465 /****************************************************************************
3466 handle named pipe commands
3467 ****************************************************************************/
3468 static int named_pipe(connection_struct
*conn
,uint16 vuid
, char *outbuf
,char *name
,
3469 uint16
*setup
,char *data
,char *params
,
3470 int suwcnt
,int tdscnt
,int tpscnt
,
3471 int msrcnt
,int mdrcnt
,int mprcnt
)
3473 DEBUG(3,("named pipe command on <%s> name\n", name
));
3475 if (strequal(name
,"LANMAN"))
3477 return api_reply(conn
,vuid
,outbuf
,data
,params
,tdscnt
,tpscnt
,mdrcnt
,mprcnt
);
3480 if (strequal(name
,"WKSSVC") ||
3481 strequal(name
,"SRVSVC") ||
3482 strequal(name
,"WINREG") ||
3483 strequal(name
,"SAMR") ||
3484 strequal(name
,"LSARPC"))
3486 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
3487 return api_fd_reply(conn
,vuid
,outbuf
,setup
,data
,params
,suwcnt
,tdscnt
,tpscnt
,mdrcnt
,mprcnt
);
3490 if (strlen(name
) < 1)
3492 return api_fd_reply(conn
,vuid
,outbuf
,setup
,data
,params
,suwcnt
,tdscnt
,tpscnt
,mdrcnt
,mprcnt
);
3497 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup
[0],(int)setup
[1]));
3504 /****************************************************************************
3506 ****************************************************************************/
3507 int reply_trans(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int bufsize
)
3510 int name_offset
= 0;
3511 char *data
=NULL
,*params
=NULL
;
3514 uint16 vuid
= SVAL(inbuf
,smb_uid
);
3515 int tpscnt
= SVAL(inbuf
,smb_vwv0
);
3516 int tdscnt
= SVAL(inbuf
,smb_vwv1
);
3517 int mprcnt
= SVAL(inbuf
,smb_vwv2
);
3518 int mdrcnt
= SVAL(inbuf
,smb_vwv3
);
3519 int msrcnt
= CVAL(inbuf
,smb_vwv4
);
3520 BOOL close_on_completion
= BITSETW(inbuf
+smb_vwv5
,0);
3521 BOOL one_way
= BITSETW(inbuf
+smb_vwv5
,1);
3522 int pscnt
= SVAL(inbuf
,smb_vwv9
);
3523 int psoff
= SVAL(inbuf
,smb_vwv10
);
3524 int dscnt
= SVAL(inbuf
,smb_vwv11
);
3525 int dsoff
= SVAL(inbuf
,smb_vwv12
);
3526 int suwcnt
= CVAL(inbuf
,smb_vwv13
);
3528 bzero(name
, sizeof(name
));
3529 fstrcpy(name
,smb_buf(inbuf
));
3531 if (dscnt
> tdscnt
|| pscnt
> tpscnt
) {
3532 exit_server("invalid trans parameters\n");
3536 if((data
= (char *)malloc(tdscnt
)) == NULL
) {
3537 DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt
));
3538 return(ERROR(ERRDOS
,ERRnomem
));
3540 memcpy(data
,smb_base(inbuf
)+dsoff
,dscnt
);
3544 if((params
= (char *)malloc(tpscnt
)) == NULL
) {
3545 DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt
));
3546 return(ERROR(ERRDOS
,ERRnomem
));
3548 memcpy(params
,smb_base(inbuf
)+psoff
,pscnt
);
3553 if((setup
= (uint16
*)malloc(suwcnt
*sizeof(uint16
))) == NULL
) {
3554 DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", suwcnt
* sizeof(uint16
)));
3555 return(ERROR(ERRDOS
,ERRnomem
));
3557 for (i
=0;i
<suwcnt
;i
++)
3558 setup
[i
] = SVAL(inbuf
,smb_vwv14
+i
*SIZEOFWORD
);
3562 if (pscnt
< tpscnt
|| dscnt
< tdscnt
) {
3563 /* We need to send an interim response then receive the rest
3564 of the parameter/data bytes */
3565 outsize
= set_message(outbuf
,0,0,True
);
3567 send_smb(Client
,outbuf
);
3570 /* receive the rest of the trans packet */
3571 while (pscnt
< tpscnt
|| dscnt
< tdscnt
) {
3573 int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
3575 ret
= receive_next_smb(inbuf
,bufsize
,SMB_SECONDARY_WAIT
);
3577 if ((ret
&& (CVAL(inbuf
, smb_com
) != SMBtrans
)) || !ret
) {
3579 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3581 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3582 (smb_read_error
== READ_ERROR
) ? "error" : "timeout" ));
3584 if (params
) free(params
);
3585 if (data
) free(data
);
3586 if (setup
) free(setup
);
3587 return(ERROR(ERRSRV
,ERRerror
));
3592 tpscnt
= SVAL(inbuf
,smb_vwv0
);
3593 tdscnt
= SVAL(inbuf
,smb_vwv1
);
3595 pcnt
= SVAL(inbuf
,smb_vwv2
);
3596 poff
= SVAL(inbuf
,smb_vwv3
);
3597 pdisp
= SVAL(inbuf
,smb_vwv4
);
3599 dcnt
= SVAL(inbuf
,smb_vwv5
);
3600 doff
= SVAL(inbuf
,smb_vwv6
);
3601 ddisp
= SVAL(inbuf
,smb_vwv7
);
3606 if (dscnt
> tdscnt
|| pscnt
> tpscnt
) {
3607 exit_server("invalid trans parameters\n");
3611 memcpy(params
+pdisp
,smb_base(inbuf
)+poff
,pcnt
);
3613 memcpy(data
+ddisp
,smb_base(inbuf
)+doff
,dcnt
);
3617 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3618 name
,tdscnt
,tpscnt
,suwcnt
));
3621 * WinCE wierdness....
3624 if (name
[0] == '\\' && (StrnCaseCmp(&name
[1],local_machine
,
3625 strlen(local_machine
)) == 0)) {
3626 name_offset
= strlen(local_machine
)+1;
3629 if (strncmp(&name
[name_offset
],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3630 DEBUG(5,("calling named_pipe\n"));
3631 outsize
= named_pipe(conn
,vuid
,outbuf
,
3632 name
+name_offset
+strlen("\\PIPE\\"),setup
,data
,params
,
3633 suwcnt
,tdscnt
,tpscnt
,msrcnt
,mdrcnt
,mprcnt
);
3635 DEBUG(3,("invalid pipe name\n"));
3640 if (data
) free(data
);
3641 if (params
) free(params
);
3642 if (setup
) free(setup
);
3644 if (close_on_completion
)
3645 close_cnum(conn
,vuid
);
3651 return(ERROR(ERRSRV
,ERRnosupport
));