preparing for release of 2.0.0beta3
[Samba.git] / source / smbd / ipc.c
blob3be2091e69174a1a010eac468222231c8e0618df
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1998
7 SMB Version handling
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
29 #include "includes.h"
30 #include "nterr.h"
32 #ifdef CHECK_TYPES
33 #undef CHECK_TYPES
34 #endif
35 #define CHECK_TYPES 0
37 extern int DEBUGLEVEL;
38 extern int max_send;
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 */
62 extern int Client;
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)
78 pstring buf;
79 int l;
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);
86 StrnCpy(*dst,buf,*n);
87 l = strlen(*dst) + 1;
88 (*dst) += l;
89 (*n) -= l;
90 return l;
93 static int CopyAndAdvance(char** dst, char* src, int* n)
95 int l;
96 if (!src || !dst || !n || !(*dst)) return(0);
97 StrnCpy(*dst,src,*n);
98 l = strlen(*dst) + 1;
99 (*dst) += l;
100 (*n) -= l;
101 return l;
104 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
106 pstring buf;
107 if (!s) return(0);
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)
116 static pstring buf;
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);
121 return &buf[0];
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 /****************************************************************************
158 send a trans reply
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)
165 int i;
166 int this_ldata,this_lparam;
167 int tot_data=0,tot_param=0;
168 int align;
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,
196 rparam , rdata,
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]);
215 show_msg(outbuf);
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,
231 rparam , rdata,
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);
243 show_msg(outbuf);
244 send_smb(Client,outbuf);
246 tot_data += this_ldata;
247 tot_param += this_lparam;
251 struct pack_desc {
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 */
263 int errcode;
266 static int get_counter(char** p)
268 int i, n;
269 if (!p || !(*p)) return(1);
270 if (!isdigit((int)**p)) return 1;
271 for (n = 0;;) {
272 i = **p;
273 if (isdigit(i))
274 n = 10 * n + (i - '0');
275 else
276 return n;
277 (*p)++;
281 static int getlen(char* p)
283 int n = 0;
284 if (!p) return(0);
285 while (*p) {
286 switch( *p++ ) {
287 case 'W': /* word (2 byte) */
288 n += 2;
289 break;
290 case 'N': /* count of substructures (word) at end */
291 n += 2;
292 break;
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) */
296 n += 4;
297 break;
298 case 'b': /* offset to data (with counter) (4 byte) */
299 n += 4;
300 get_counter(&p);
301 break;
302 case 'B': /* byte (with optional counter) */
303 n += get_counter(&p);
304 break;
307 return n;
310 static BOOL init_package(struct pack_desc* p, int count, int subcount)
312 int n = p->buflen;
313 int i;
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;
320 p->neededlen = 0;
321 p->usedlen = 0;
322 p->subcount = 0;
323 p->curpos = p->format;
324 if (i > n) {
325 p->neededlen = i;
326 i = n = 0;
327 p->errcode = ERRmoredata;
329 else
330 p->errcode = NERR_Success;
331 p->buflen = i;
332 n -= i;
333 p->stringbuf = p->base + i;
334 p->stringlen = n;
335 return(p->errcode == NERR_Success);
338 #ifdef HAVE_STDARG_H
339 static int package(struct pack_desc* p, ...)
341 #else
342 static int package(va_alist)
343 va_dcl
345 struct pack_desc* p;
346 #endif
347 va_list args;
348 int needed=0, stringneeded;
349 char* str=NULL;
350 int is_string=0, stringused;
351 int32 temp;
353 #ifdef HAVE_STDARG_H
354 va_start(args,p);
355 #else
356 va_start(args);
357 p = va_arg(args,struct pack_desc *);
358 #endif
360 if (!*p->curpos) {
361 if (!p->subcount)
362 p->curpos = p->format;
363 else {
364 p->curpos = p->subformat;
365 p->subcount--;
368 #if CHECK_TYPES
369 str = va_arg(args,char*);
370 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
371 #endif
372 stringneeded = -1;
374 if (!p->curpos) return(0);
376 switch( *p->curpos++ ) {
377 case 'W': /* word (2 byte) */
378 needed = 2;
379 temp = va_arg(args,int);
380 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
381 break;
382 case 'N': /* count of substructures (word) at end */
383 needed = 2;
384 p->subcount = va_arg(args,int);
385 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
386 break;
387 case 'D': /* double word (4 byte) */
388 needed = 4;
389 temp = va_arg(args,int);
390 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
391 break;
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);
398 break;
399 case 'z': /* offset to zero terminated string (4 byte) */
400 str = va_arg(args,char*);
401 stringneeded = (str ? strlen(str)+1 : 0);
402 is_string = 1;
403 break;
404 case 'l': /* offset to user data (4 byte) */
405 str = va_arg(args,char*);
406 stringneeded = va_arg(args,int);
407 is_string = 0;
408 break;
409 case 'b': /* offset to data (with counter) (4 byte) */
410 str = va_arg(args,char*);
411 stringneeded = get_counter(&p->curpos);
412 is_string = 0;
413 break;
415 va_end(args);
416 if (stringneeded >= 0) {
417 needed = 4;
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;
424 if (!stringused)
425 SIVAL(p->structbuf,0,0);
426 else {
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;
440 p->buflen -= needed;
441 p->usedlen += needed;
443 else {
444 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
446 return 1;
449 #if CHECK_TYPES
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)
452 #else
453 #define PACK(desc,t,v) package(desc,v)
454 #define PACKl(desc,t,v,l) package(desc,v,l)
455 #endif
457 static void PACKI(struct pack_desc* desc,char *t,int v)
459 PACK(desc,t,v);
462 static void PACKS(struct pack_desc* desc,char *t,char *v)
464 PACK(desc,t,v);
468 /****************************************************************************
469 get a print queue
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;
486 switch( uLevel ) {
487 case 0:
488 desc->format = "B13";
489 break;
490 case 1:
491 desc->format = "B13BWWWzzzzzWW";
492 break;
493 case 2:
494 desc->format = "B13BWWWzzzzzWN";
495 desc->subformat = "WB21BB16B10zWWzDDz";
496 break;
497 case 3:
498 desc->format = "zWWWWzzzzWWzzl";
499 break;
500 case 4:
501 desc->format = "zWWWWzzzzWNzzl";
502 desc->subformat = "WWzWWDDzz";
503 break;
504 case 5:
505 desc->format = "z";
506 break;
507 case 52:
508 desc->format = "WzzzzzzzzN";
509 desc->subformat = "z";
510 break;
511 default: return False;
513 if (strcmp(desc->format,id1) != 0) return False;
514 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
515 return True;
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 */
525 t -= TimeDiff(t);
527 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
528 if (uLevel == 1) {
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 */
550 if (uLevel == 3) {
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)
570 switch (uLevel) {
571 case 1:
572 case 2:
573 PACKS(desc,"B13",SERVICE(snum));
574 break;
575 case 3:
576 case 4:
577 case 5:
578 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
579 break;
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 */
591 if (snum < 0) {
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 */
598 } else {
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 */
615 } else {
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) {
625 int i;
626 for (i=0;i<count;i++)
627 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
630 if (uLevel==52) {
631 int i,ok=0;
632 pstring tok,driver,datafile,langmon,helpfile,datatype;
633 char *p,*q;
634 FILE *f;
635 pstring fname;
637 pstrcpy(fname,lp_driverfile());
638 f=sys_fopen(fname,"r");
639 if (!f) {
640 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
641 desc->errcode=NERR_notsupported;
642 return;
645 if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
646 DEBUG(0,("fill_printq_info: malloc fail !\n"));
647 desc->errcode=NERR_notsupported;
648 fclose(f);
649 return;
652 bzero(p, 8192*sizeof(char));
653 q=p;
655 /* lookup the long printer driver name in the file description */
656 while (f && !feof(f) && !ok)
658 p = q; /* reset string pointer */
659 fgets(p,8191,f);
660 p[strlen(p)-1]='\0';
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)))))
664 ok=1;
666 fclose(f);
668 /* driver file name */
669 if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0;
670 /* data file name */
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
675 * token fields
677 if (ok) {
678 /* help file */
679 if (*p == ':') {
680 *helpfile = '\0';
681 p++;
682 } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0;
685 if (ok) {
686 /* language monitor */
687 if (*p == ':') {
688 *langmon = '\0';
689 p++;
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;
696 if (ok) {
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));
724 } else {
725 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
726 desc->errcode=NERR_notsupported;
728 free(q);
732 /* This function returns the number of files for a given driver */
733 static int get_printerdrivernumber(int snum)
735 int i=0,ok=0;
736 pstring tok;
737 char *p,*q;
738 FILE *f;
739 pstring fname;
741 pstrcpy(fname,lp_driverfile());
743 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
744 f=sys_fopen(fname,"r");
745 if (!f) {
746 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
747 return(0);
750 if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
751 DEBUG(3,("get_printerdrivernumber: malloc fail !\n"));
752 fclose(f);
753 return 0;
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 */
762 fgets(p,8191,f);
763 if (next_token(&p,tok,":",sizeof(tok)) &&
764 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
765 ok=1;
767 fclose(f);
769 if (ok) {
770 /* skip 5 fields */
771 i = 5;
772 while (*p && i) {
773 if (*p++ == ':') i--;
775 if (!*p || i)
776 return(0);
778 /* count the number of files */
779 while (next_token(&p,tok,",",sizeof(tok)))
780 i++;
782 free(q);
784 return(i);
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);
796 char *QueueName = p;
797 int uLevel;
798 int count=0;
799 int snum;
800 char* str3;
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);
809 uLevel = SVAL(p,0);
810 str3 = p + 4;
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.
825 *rdata_len = 0;
826 *rparam_len = 6;
827 *rparam = REALLOC(*rparam,*rparam_len);
828 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
829 SSVAL(*rparam,2,0);
830 SSVAL(*rparam,4,0);
831 return(True);
834 snum = lp_servicenumber(QueueName);
835 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
836 int pnum = lp_servicenumber(PRINTERS_NAME);
837 if (pnum >= 0) {
838 lp_add_printer(QueueName,pnum);
839 snum = lp_servicenumber(QueueName);
843 if (snum < 0 || !VALID_SNUM(snum)) return(False);
845 if (uLevel==52) {
846 count = get_printerdrivernumber(snum);
847 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
848 } else {
849 count = get_printqueue(snum, conn,&queue,&status);
852 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
853 desc.base = *rdata;
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;
882 *rparam_len = 6;
883 *rparam = REALLOC(*rparam,*rparam_len);
884 SSVALS(*rparam,0,desc.errcode);
885 SSVAL(*rparam,2,0);
886 SSVAL(*rparam,4,desc.neededlen);
888 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
890 if (queue) free(queue);
892 return(True);
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();
910 int i, n;
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.
928 *rdata_len = 0;
929 *rparam_len = 6;
930 *rparam = REALLOC(*rparam,*rparam_len);
931 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
932 SSVAL(*rparam,2,0);
933 SSVAL(*rparam,4,0);
934 return(True);
937 queuecnt = 0;
938 for (i = 0; i < services; i++)
939 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
940 queuecnt++;
941 if (uLevel > 0) {
942 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
943 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
944 return False;
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"));
949 return False;
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"));
954 return False;
956 subcnt = 0;
957 n = 0;
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];
962 n++;
965 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
966 desc.base = *rdata;
967 desc.buflen = mdrcnt;
969 if (init_package(&desc,queuecnt,subcnt)) {
970 n = 0;
971 succnt = 0;
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]);
975 n++;
976 if (desc.errcode == NERR_Success) succnt = n;
980 if (subcntarr) free(subcntarr);
982 *rdata_len = desc.usedlen;
983 *rparam_len = 8;
984 *rparam = REALLOC(*rparam,*rparam_len);
985 SSVALS(*rparam,0,desc.errcode);
986 SSVAL(*rparam,2,0);
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);
997 return True;
1000 /****************************************************************************
1001 get info level for a server list query
1002 ****************************************************************************/
1003 static BOOL check_server_info(int uLevel, char* id)
1005 switch( uLevel ) {
1006 case 0:
1007 if (strcmp(id,"B16") != 0) return False;
1008 break;
1009 case 1:
1010 if (strcmp(id,"B16BBDz") != 0) return False;
1011 break;
1012 default:
1013 return False;
1015 return True;
1018 struct srv_info_struct
1020 fstring name;
1021 uint32 type;
1022 fstring comment;
1023 fstring domain;
1024 BOOL server_added;
1028 /*******************************************************************
1029 get server info lists from the files saved by nmbd. Return the
1030 number of entries
1031 ******************************************************************/
1032 static int get_server_info(uint32 servertype,
1033 struct srv_info_struct **servers,
1034 char *domain)
1036 FILE *f;
1037 pstring fname;
1038 int count=0;
1039 int alloced=0;
1040 pstring line;
1041 BOOL local_list_only;
1043 pstrcpy(fname,lp_lockdir());
1044 trim_string(fname,NULL,"/");
1045 pstrcat(fname,"/");
1046 pstrcat(fname,SERVER_LIST);
1048 f = sys_fopen(fname,"r");
1050 if (!f) {
1051 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1052 return(0);
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));
1063 while (!feof(f))
1065 fstring stype;
1066 struct srv_info_struct *s;
1067 char *ptr = line;
1068 BOOL ok = True;
1069 *ptr = 0;
1071 fgets(line,sizeof(line)-1,f);
1072 if (!*line) continue;
1074 if (count == alloced) {
1075 alloced += 10;
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 "));
1093 ok = False;
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"));
1101 ok = False;
1104 /* doesn't match up: don't want it */
1105 if (!(servertype & s->type)) {
1106 DEBUG(4,("r:serv type "));
1107 ok = False;
1110 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1111 (s->type & SV_TYPE_DOMAIN_ENUM))
1113 DEBUG(4,("s: dom mismatch "));
1114 ok = False;
1117 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1119 ok = False;
1122 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1123 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1125 if (ok)
1127 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1128 s->name, s->type, s->comment, s->domain));
1130 s->server_added = True;
1131 count++;
1133 else
1135 DEBUG(4,("%20s %8x %25s %15s\n",
1136 s->name, s->type, s->comment, s->domain));
1140 fclose(f);
1141 return(count);
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)
1152 int struct_len;
1153 char* p;
1154 char* p2;
1155 int l2;
1156 int len;
1158 switch (uLevel) {
1159 case 0: struct_len = 16; break;
1160 case 1: struct_len = 26; break;
1161 default: return -1;
1164 if (!buf)
1166 len = 0;
1167 switch (uLevel)
1169 case 1:
1170 len = strlen(service->comment)+1;
1171 break;
1174 if (buflen) *buflen = struct_len;
1175 if (stringspace) *stringspace = len;
1176 return struct_len + len;
1179 len = struct_len;
1180 p = *buf;
1181 if (*buflen < struct_len) return -1;
1182 if (stringbuf)
1184 p2 = *stringbuf;
1185 l2 = *stringspace;
1187 else
1189 p2 = p + struct_len;
1190 l2 = *buflen - struct_len;
1192 if (!baseaddr) baseaddr = p;
1194 switch (uLevel)
1196 case 0:
1197 StrnCpy(p,service->name,15);
1198 break;
1200 case 1:
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);
1205 break;
1208 if (stringbuf)
1210 *buf = p + struct_len;
1211 *buflen -= struct_len;
1212 *stringbuf = p2;
1213 *stringspace = l2;
1215 else
1217 *buf = p2;
1218 *buflen -= len;
1220 return 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);
1243 char *p2;
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;
1248 int i,missed;
1249 fstring domain;
1250 BOOL domain_request;
1251 BOOL local_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
1255 known servers. */
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);
1272 p += 8;
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);
1283 } else {
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;
1291 missed = 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;
1302 lastname = s->name;
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) {
1308 counted++;
1309 fixed_len += f_len;
1310 string_len += s_len;
1311 } else {
1312 missed++;
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 */
1322 p = *rdata;
1323 f_len = fixed_len;
1324 s_len = string_len;
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;
1333 lastname = s->name;
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));
1337 count2--;
1341 *rparam_len = 8;
1342 *rparam = REALLOC(*rparam,*rparam_len);
1343 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1344 SSVAL(*rparam,2,0);
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));
1353 return(True);
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);
1368 int counted=0;
1369 int missed=0;
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;
1376 *rdata_len = 0;
1378 *rparam_len = 8;
1379 *rparam = REALLOC(*rparam,*rparam_len);
1381 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1382 SSVAL(*rparam,2,0);
1383 SSVAL(*rparam,4,counted);
1384 SSVAL(*rparam,6,counted+missed);
1386 return(True);
1389 /****************************************************************************
1390 get info about a share
1391 ****************************************************************************/
1392 static BOOL check_share_info(int uLevel, char* id)
1394 switch( uLevel ) {
1395 case 0:
1396 if (strcmp(id,"B13") != 0) return False;
1397 break;
1398 case 1:
1399 if (strcmp(id,"B13BWz") != 0) return False;
1400 break;
1401 case 2:
1402 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1403 break;
1404 case 91:
1405 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1406 break;
1407 default: return False;
1409 return True;
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)
1416 int struct_len;
1417 char* p;
1418 char* p2;
1419 int l2;
1420 int len;
1422 switch( uLevel ) {
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;
1427 default: return -1;
1431 if (!buf)
1433 len = 0;
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;
1441 len = struct_len;
1442 p = *buf;
1443 if ((*buflen) < struct_len) return -1;
1444 if (stringbuf)
1446 p2 = *stringbuf;
1447 l2 = *stringspace;
1449 else
1451 p2 = p + struct_len;
1452 l2 = (*buflen) - struct_len;
1454 if (!baseaddr) baseaddr = p;
1456 StrnCpy(p,lp_servicename(snum),13);
1458 if (uLevel > 0)
1460 int type;
1461 CVAL(p,13) = 0;
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);
1470 if (uLevel > 1)
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 */
1480 if (uLevel > 2)
1482 memset(p+40,0,SHPWLEN+2);
1483 SSVAL(p,50,0);
1484 SIVAL(p,52,0);
1485 SSVAL(p,56,0);
1486 SSVAL(p,58,0);
1487 SIVAL(p,60,0);
1488 SSVAL(p,64,0);
1489 SSVAL(p,66,0);
1492 if (stringbuf)
1494 (*buf) = p + struct_len;
1495 (*buflen) -= struct_len;
1496 (*stringbuf) = p2;
1497 (*stringspace) = l2;
1499 else
1501 (*buf) = p2;
1502 (*buflen) -= len;
1504 return len;
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);
1526 p = *rdata;
1527 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1528 if (*rdata_len < 0) return False;
1530 *rparam_len = 6;
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);
1536 return(True);
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);
1552 char *p2;
1553 int count=lp_numservices();
1554 int total=0,counted=0;
1555 BOOL missed = False;
1556 int i;
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))
1567 total++;
1568 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1569 if (data_len <= buf_len)
1571 counted++;
1572 fixed_len += f_len;
1573 string_len += s_len;
1575 else
1576 missed = True;
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 */
1583 p = *rdata;
1584 f_len = fixed_len;
1585 s_len = string_len;
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)
1589 break;
1591 *rparam_len = 8;
1592 *rparam = REALLOC(*rparam,*rparam_len);
1593 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1594 SSVAL(*rparam,2,0);
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));
1601 return(True);
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)
1614 char *p;
1615 *rparam_len = 4;
1616 *rparam = REALLOC(*rparam,*rparam_len);
1618 *rdata_len = 21;
1619 *rdata = REALLOC(*rdata,*rdata_len);
1621 SSVAL(*rparam,0,NERR_Success);
1622 SSVAL(*rparam,2,0); /* converter word */
1624 p = *rdata;
1627 struct tm *t;
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;
1652 return(True);
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);
1664 fstring user;
1665 fstring pass1,pass2;
1667 fstrcpy(user,p);
1669 p = skip_string(p,1);
1671 memcpy(pass1,p,16);
1672 memcpy(pass2,p+16,16);
1674 *rparam_len = 4;
1675 *rparam = REALLOC(*rparam,*rparam_len);
1677 *rdata_len = 0;
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
1686 * function.
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));
1727 return(True);
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)
1739 fstring user;
1740 char *p = param + 2;
1741 *rparam_len = 2;
1742 *rparam = REALLOC(*rparam,*rparam_len);
1744 *rdata_len = 0;
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));
1753 return False;
1755 p = skip_string(p, 1);
1757 if(!strequal(p, "B516B16")) {
1758 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1759 return False;
1761 p = skip_string(p,1);
1763 fstrcpy(user,p);
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
1770 * function.
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);
1785 return(True);
1788 /****************************************************************************
1789 delete a print job
1790 Form: <W> <>
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);
1801 int jobid, snum;
1802 int i, count;
1804 printjob_decode(SVAL(p,0), &snum, &jobid);
1806 /* check it's a supported varient */
1807 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1808 return(False);
1810 *rparam_len = 4;
1811 *rparam = REALLOC(*rparam,*rparam_len);
1813 *rdata_len = 0;
1815 SSVAL(*rparam,0,NERR_Success);
1817 if (snum >= 0 && VALID_SNUM(snum))
1819 print_queue_struct *queue=NULL;
1820 lpq_reset(snum);
1821 count = get_printqueue(snum,conn,&queue,NULL);
1823 for (i=0;i<count;i++)
1824 if ((queue[i].job&0xFF) == jobid)
1826 switch (function) {
1827 case 81: /* delete */
1828 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1829 del_printqueue(conn,snum,queue[i].job);
1830 break;
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));
1837 break;
1839 break;
1842 if (i==count)
1843 SSVAL(*rparam,0,NERR_JobNotFound);
1845 if (queue) free(queue);
1848 SSVAL(*rparam,2,0); /* converter word */
1850 return(True);
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);
1865 int snum;
1867 /* check it's a supported varient */
1868 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1869 return(False);
1871 *rparam_len = 4;
1872 *rparam = REALLOC(*rparam,*rparam_len);
1874 *rdata_len = 0;
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);
1882 if (pnum >= 0) {
1883 lp_add_printer(QueueName,pnum);
1884 snum = lp_servicenumber(QueueName);
1888 if (snum >= 0 && VALID_SNUM(snum)) {
1889 lpq_reset(snum);
1891 switch (function) {
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));
1897 break;
1898 case 103: /* Purge */
1900 print_queue_struct *queue=NULL;
1901 int i, count;
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));
1908 break;
1913 return(True);
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;
1928 switch( uLevel ) {
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;
1936 return True;
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);
1948 int jobid, snum;
1949 int uLevel = SVAL(p,2);
1950 int function = SVAL(p,4); /* what is this ?? */
1951 int i;
1952 char *s = data;
1953 files_struct *fsp;
1955 printjob_decode(SVAL(p,0), &snum, &jobid);
1957 *rparam_len = 4;
1958 *rparam = REALLOC(*rparam,*rparam_len);
1960 *rdata_len = 0;
1962 /* check it's a supported varient */
1963 if ((strcmp(str1,"WWsTP")) ||
1964 (!check_printjob_info(&desc,uLevel,str2)))
1965 return(False);
1967 switch (function) {
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;
1972 int count;
1974 lpq_reset(snum);
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;
1979 if (i==count) {
1980 desc.errcode=NERR_JobNotFound;
1981 if (queue) free(queue);
1982 } else {
1983 desc.errcode=NERR_Success;
1984 i++;
1985 #if 0
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 */;
1993 #endif
1994 desc.errcode=NERR_notsupported; /* not yet
1995 supported */
1996 if (queue) free(queue);
1998 } else {
1999 desc.errcode=NERR_JobNotFound;
2001 break;
2003 case 0xb: /* change print job name, data gives the name */
2004 /* jobid, snum should be zero */
2005 if (isalpha((int)*s)) {
2006 pstring name;
2007 int l = 0;
2008 while (l<64 && *s) {
2009 if (issafe(*s)) name[l++] = *s;
2010 s++;
2012 name[l] = 0;
2014 DEBUG(3,("Setting print name to %s\n",name));
2016 fsp = file_find_print();
2018 if (fsp) {
2019 connection_struct *fconn = fsp->conn;
2020 unbecome_user();
2022 if (!become_user(fconn,vuid) ||
2023 !become_service(fconn,True))
2024 break;
2026 if (dos_rename(fsp->fsp_name,name) == 0) {
2027 string_set(&fsp->fsp_name,name);
2029 break;
2032 desc.errcode=NERR_Success;
2033 break;
2035 default: /* not implemented */
2036 return False;
2039 SSVALS(*rparam,0,desc.errcode);
2040 SSVAL(*rparam,2,0); /* converter word */
2042 return(True);
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);
2058 char *p2;
2059 int struct_len;
2061 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2063 /* check it's a supported varient */
2064 if (!prefix_ok(str1,"WrLh")) return False;
2065 switch( uLevel ) {
2066 case 0:
2067 if (strcmp(str2,"B16") != 0) return False;
2068 struct_len = 16;
2069 break;
2070 case 1:
2071 if (strcmp(str2,"B16BBDz") != 0) return False;
2072 struct_len = 26;
2073 break;
2074 case 2:
2075 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2076 != 0) return False;
2077 struct_len = 134;
2078 break;
2079 case 3:
2080 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2081 != 0) return False;
2082 struct_len = 144;
2083 break;
2084 case 20:
2085 if (strcmp(str2,"DN") != 0) return False;
2086 struct_len = 6;
2087 break;
2088 case 50:
2089 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2090 struct_len = 42;
2091 break;
2092 default: return False;
2095 *rdata_len = mdrcnt;
2096 *rdata = REALLOC(*rdata,*rdata_len);
2098 p = *rdata;
2099 p2 = p + struct_len;
2100 if (uLevel != 20) {
2101 StrnCpy(p,local_machine,16);
2102 strupper(p);
2104 p += 16;
2105 if (uLevel > 0)
2107 struct srv_info_struct *servers=NULL;
2108 int i,count;
2109 pstring comment;
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) {
2129 SIVAL(p,6,0);
2130 } else {
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);
2137 if (uLevel > 1)
2139 return False; /* not yet implemented */
2142 *rdata_len = PTR_DIFF(p2,*rdata);
2144 *rparam_len = 6;
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);
2150 return(True);
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);
2165 char *p2;
2166 extern pstring sesssetup_user;
2167 int level = SVAL(p,0);
2169 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2171 *rparam_len = 6;
2172 *rparam = REALLOC(*rparam,*rparam_len);
2174 /* check it's a supported varient */
2175 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2176 return(False);
2178 *rdata_len = mdrcnt + 1024;
2179 *rdata = REALLOC(*rdata,*rdata_len);
2181 SSVAL(*rparam,0,NERR_Success);
2182 SSVAL(*rparam,2,0); /* converter word */
2184 p = *rdata;
2185 p2 = p + 22;
2188 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2189 pstrcpy(p2,local_machine);
2190 strupper(p2);
2191 p2 = skip_string(p2,1);
2192 p += 4;
2194 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2195 pstrcpy(p2,sesssetup_user);
2196 p2 = skip_string(p2,1);
2197 p += 4;
2199 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2200 pstrcpy(p2,global_myworkgroup);
2201 strupper(p2);
2202 p2 = skip_string(p2,1);
2203 p += 4;
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 */
2207 p += 2;
2209 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2210 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2211 p2 = skip_string(p2,1);
2212 p += 4;
2214 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2215 pstrcpy(p2,"");
2216 p2 = skip_string(p2,1);
2217 p += 4;
2219 *rdata_len = PTR_DIFF(p2,*rdata);
2221 SSVAL(*rparam,4,*rdata_len);
2223 return(True);
2226 /****************************************************************************
2227 get info about a user
2229 struct user_info_11 {
2230 char usri11_name[21]; 0-20
2231 char usri11_pad; 21
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
2252 where:
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
2304 time is unknown.
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
2315 domain controller.
2317 usri11_country_code specifies the country code for the user's language
2318 of choice.
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
2327 restrictions.
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
2349 choice
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);
2404 char *p2;
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);
2410 if(vuser != NULL)
2411 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name));
2413 *rparam_len = 6;
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;
2420 switch( uLevel )
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 */
2438 p = *rdata;
2439 p2 = p + usri11_end;
2441 memset(p,0,21);
2442 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2444 if (uLevel > 0)
2446 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2447 *p2 = 0;
2449 if (uLevel >= 10)
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 */
2474 pstrcpy(p2,"");
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 */
2486 pstrcpy(p2,"");
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. */
2494 memset(p2,0xff,21);
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 */
2504 SSVAL(p,42,
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 */
2510 *p2++ = 0;
2511 SSVAL(p,52,0); /* flags */
2512 SIVAL(p,54,0); /* script_path */
2513 if (uLevel == 2)
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 */
2521 pstrcpy(p2,"");
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 */
2530 memset(p2,-1,21);
2531 p2 += 21;
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?? */
2547 return(True);
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);
2563 char *p2;
2564 int count=0;
2566 *rparam_len = 8;
2567 *rparam = REALLOC(*rparam,*rparam_len);
2569 /* check it's a supported varient */
2570 if (strcmp(str1,"zWrLeh") != 0) return False;
2571 switch( uLevel ) {
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 */
2583 p = *rdata;
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?? */
2596 return(True);
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);
2608 int uLevel;
2609 struct pack_desc desc;
2610 char* name;
2611 char* logon_script;
2613 uLevel = SVAL(p,0);
2614 name = p + 2;
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);
2624 desc.base = *rdata;
2625 desc.buflen = mdrcnt;
2626 desc.subformat = NULL;
2627 desc.format = str2;
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 */
2634 PACKI(&desc,"W",
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 */
2647 fstring mypath;
2648 fstrcpy(mypath,"\\\\");
2649 fstrcat(mypath,local_machine);
2650 strupper(mypath);
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;
2666 *rparam_len = 6;
2667 *rparam = REALLOC(*rparam,*rparam_len);
2668 SSVALS(*rparam,0,desc.errcode);
2669 SSVAL(*rparam,2,0);
2670 SSVAL(*rparam,4,desc.neededlen);
2672 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2673 return(True);
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;
2696 *rparam_len = 6;
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 */
2702 return(True);
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);
2716 int uLevel;
2717 int count;
2718 int i;
2719 int snum;
2720 int job;
2721 struct pack_desc desc;
2722 print_queue_struct *queue=NULL;
2723 print_status_struct status;
2725 uLevel = SVAL(p,2);
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);
2745 desc.base = *rdata;
2746 desc.buflen = mdrcnt;
2748 if (init_package(&desc,1,0)) {
2749 if (i < count) {
2750 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2751 *rdata_len = desc.usedlen;
2753 else {
2754 desc.errcode = NERR_JobNotFound;
2755 *rdata_len = 0;
2759 *rparam_len = 6;
2760 *rparam = REALLOC(*rparam,*rparam_len);
2761 SSVALS(*rparam,0,desc.errcode);
2762 SSVAL(*rparam,2,0);
2763 SSVAL(*rparam,4,desc.neededlen);
2765 if (queue) free(queue);
2767 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2768 return(True);
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);
2779 char* name = p;
2780 int uLevel;
2781 int count;
2782 int i, succnt=0;
2783 int snum;
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);
2792 uLevel = SVAL(p,0);
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);
2804 if (pnum >= 0) {
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);
2814 desc.base = *rdata;
2815 desc.buflen = mdrcnt;
2817 if (init_package(&desc,count,0)) {
2818 succnt = 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;
2827 *rparam_len = 8;
2828 *rparam = REALLOC(*rparam,*rparam_len);
2829 SSVALS(*rparam,0,desc.errcode);
2830 SSVAL(*rparam,2,0);
2831 SSVAL(*rparam,4,succnt);
2832 SSVAL(*rparam,6,count);
2834 if (queue) free(queue);
2836 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2837 return(True);
2840 static int check_printdest_info(struct pack_desc* desc,
2841 int uLevel, char* id)
2843 desc->subformat = NULL;
2844 switch( uLevel ) {
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;
2852 return True;
2855 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2856 struct pack_desc* desc)
2858 char buf[100];
2859 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2860 buf[sizeof(buf)-1] = 0;
2861 strupper(buf);
2862 if (uLevel <= 1) {
2863 PACKS(desc,"B9",buf); /* szName */
2864 if (uLevel == 1) {
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 */
2874 if (uLevel == 3) {
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;
2897 int uLevel;
2898 struct pack_desc desc;
2899 int snum;
2901 bzero(&desc,sizeof(desc));
2903 p = skip_string(p,1);
2904 uLevel = SVAL(p,0);
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);
2915 if (pnum >= 0) {
2916 lp_add_printer(PrinterName,pnum);
2917 snum = lp_servicenumber(PrinterName);
2921 if (snum < 0) {
2922 *rdata_len = 0;
2923 desc.errcode = NERR_DestNotFound;
2924 desc.neededlen = 0;
2926 else {
2927 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2928 desc.base = *rdata;
2929 desc.buflen = mdrcnt;
2930 if (init_package(&desc,1,0)) {
2931 fill_printdest_info(conn,snum,uLevel,&desc);
2933 *rdata_len = desc.usedlen;
2936 *rparam_len = 6;
2937 *rparam = REALLOC(*rparam,*rparam_len);
2938 SSVALS(*rparam,0,desc.errcode);
2939 SSVAL(*rparam,2,0);
2940 SSVAL(*rparam,4,desc.neededlen);
2942 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2943 return(True);
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);
2954 int uLevel;
2955 int queuecnt;
2956 int i, n, succnt=0;
2957 struct pack_desc desc;
2958 int services = lp_numservices();
2960 bzero(&desc,sizeof(desc));
2962 uLevel = SVAL(p,0);
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;
2970 queuecnt = 0;
2971 for (i = 0; i < services; i++)
2972 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2973 queuecnt++;
2975 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2976 desc.base = *rdata;
2977 desc.buflen = mdrcnt;
2978 if (init_package(&desc,queuecnt,0)) {
2979 succnt = 0;
2980 n = 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);
2984 n++;
2985 if (desc.errcode == NERR_Success) succnt = n;
2990 *rdata_len = desc.usedlen;
2992 *rparam_len = 8;
2993 *rparam = REALLOC(*rparam,*rparam_len);
2994 SSVALS(*rparam,0,desc.errcode);
2995 SSVAL(*rparam,2,0);
2996 SSVAL(*rparam,4,succnt);
2997 SSVAL(*rparam,6,queuecnt);
2999 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3000 return(True);
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);
3011 int uLevel;
3012 int succnt;
3013 struct pack_desc desc;
3015 bzero(&desc,sizeof(desc));
3017 uLevel = SVAL(p,0);
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);
3026 desc.base = *rdata;
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;
3036 *rparam_len = 8;
3037 *rparam = REALLOC(*rparam,*rparam_len);
3038 SSVALS(*rparam,0,desc.errcode);
3039 SSVAL(*rparam,2,0);
3040 SSVAL(*rparam,4,succnt);
3041 SSVAL(*rparam,6,1);
3043 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3044 return(True);
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);
3055 int uLevel;
3056 int succnt;
3057 struct pack_desc desc;
3059 bzero(&desc,sizeof(desc));
3061 uLevel = SVAL(p,0);
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);
3070 desc.base = *rdata;
3071 desc.buflen = mdrcnt;
3072 desc.format = str2;
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;
3081 *rparam_len = 8;
3082 *rparam = REALLOC(*rparam,*rparam_len);
3083 SSVALS(*rparam,0,desc.errcode);
3084 SSVAL(*rparam,2,0);
3085 SSVAL(*rparam,4,succnt);
3086 SSVAL(*rparam,6,1);
3088 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3089 return(True);
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);
3100 int uLevel;
3101 int succnt;
3102 struct pack_desc desc;
3104 bzero(&desc,sizeof(desc));
3106 uLevel = SVAL(p,0);
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));
3116 desc.base = *rdata;
3117 desc.buflen = mdrcnt;
3118 desc.format = str2;
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;
3127 *rparam_len = 8;
3128 *rparam = REALLOC(*rparam,*rparam_len);
3129 SSVALS(*rparam,0,desc.errcode);
3130 SSVAL(*rparam,2,0);
3131 SSVAL(*rparam,4,succnt);
3132 SSVAL(*rparam,6,1);
3134 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3135 return(True);
3138 static void api_rpc_trans_reply(char *outbuf,
3139 pipes_struct *p,
3140 prs_struct *pd)
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)
3158 uint16 priority;
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);
3170 return True;
3172 return False;
3176 /****************************************************************************
3177 SetNamedPipeHandleState
3178 ****************************************************************************/
3179 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3181 uint16 id;
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);
3193 return True;
3195 return False;
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;
3212 /* unsupported */
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);
3223 return(-1);
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)
3233 BOOL reply = False;
3235 int pnum;
3236 int subcommand;
3237 pipes_struct *p = NULL;
3238 prs_struct pd;
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. */
3247 if (suwcnt != 2)
3249 DEBUG(0,("Unexpected named pipe transaction.\n"));
3250 return(-1);
3253 /* Get the file handle and hence the file name. */
3254 pnum = setup[1];
3255 subcommand = setup[0];
3256 p = get_rpc_pipe(pnum);
3258 if (p != NULL)
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));
3269 switch (subcommand)
3271 case 0x26:
3273 /* dce/rpc command */
3274 reply = rpc_command(p, &pd);
3275 if (reply)
3277 api_rpc_trans_reply(outbuf, p, &pd);
3279 break;
3281 case 0x53:
3283 /* Wait Named Pipe Handle state */
3284 reply = api_WNPHS(outbuf, p, params);
3285 break;
3287 case 0x01:
3289 /* Set Named Pipe Handle state */
3290 reply = api_SNPHS(outbuf, p, params);
3291 break;
3295 else
3297 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3300 mem_free_data(pd.data);
3302 if (!reply)
3304 return api_no_reply(outbuf, mdrcnt);
3306 return -1;
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);
3320 *rdata_len = 0;
3322 SSVAL(*rparam,0,NERR_BufTooSmall);
3324 DEBUG(3,("Supplied buffer too small in API command\n"));
3326 return(True);
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)
3338 *rparam_len = 4;
3339 *rparam = REALLOC(*rparam,*rparam_len);
3341 *rdata_len = 0;
3343 SSVAL(*rparam,0,NERR_notsupported);
3344 SSVAL(*rparam,2,0); /* converter word */
3346 DEBUG(3,("Unsupported API command\n"));
3348 return(True);
3354 struct
3356 char *name;
3357 int id;
3358 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3359 int,int,char **,char **,int *,int *);
3360 int flags;
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)
3400 int api_command;
3401 struct mem_buf rdata_buf;
3402 struct mem_buf rparam_buf;
3403 char *rdata = NULL;
3404 char *rparam = NULL;
3405 int rdata_len = 0;
3406 int rparam_len = 0;
3407 BOOL reply=False;
3408 int i;
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",
3415 api_command,
3416 params+2,
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));
3424 break;
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"));
3432 return -1;
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 */
3448 if (!reply)
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);
3462 return(-1);
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);
3495 if (setup)
3497 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3500 return 0;
3504 /****************************************************************************
3505 reply to a SMBtrans
3506 ****************************************************************************/
3507 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
3509 fstring name;
3510 int name_offset = 0;
3511 char *data=NULL,*params=NULL;
3512 uint16 *setup=NULL;
3513 int outsize = 0;
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");
3535 if (tdscnt) {
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);
3543 if (tpscnt) {
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);
3551 if (suwcnt) {
3552 int i;
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);
3566 show_msg(outbuf);
3567 send_smb(Client,outbuf);
3570 /* receive the rest of the trans packet */
3571 while (pscnt < tpscnt || dscnt < tdscnt) {
3572 BOOL ret;
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) {
3578 if(ret) {
3579 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3580 } else {
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));
3590 show_msg(inbuf);
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);
3603 pscnt += pcnt;
3604 dscnt += dcnt;
3606 if (dscnt > tdscnt || pscnt > tpscnt) {
3607 exit_server("invalid trans parameters\n");
3610 if (pcnt)
3611 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3612 if (dcnt)
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);
3634 } else {
3635 DEBUG(3,("invalid pipe name\n"));
3636 outsize = 0;
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);
3647 if (one_way)
3648 return(-1);
3650 if (outsize == 0)
3651 return(ERROR(ERRSRV,ERRnosupport));
3653 return(outsize);