added file from 2.0 branch
[Samba/gebeck_regimport.git] / source / smbd / ipc.c
blob41892504adcaebde1fa777d24060266b18dacce7
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)) return False;
821 snum = lp_servicenumber(QueueName);
822 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
823 int pnum = lp_servicenumber(PRINTERS_NAME);
824 if (pnum >= 0) {
825 lp_add_printer(QueueName,pnum);
826 snum = lp_servicenumber(QueueName);
830 if (snum < 0 || !VALID_SNUM(snum)) return(False);
832 if (uLevel==52) {
833 count = get_printerdrivernumber(snum);
834 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
835 } else {
836 count = get_printqueue(snum, conn,&queue,&status);
839 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
840 desc.base = *rdata;
841 desc.buflen = mdrcnt;
842 if (init_package(&desc,1,count)) {
843 desc.subcount = count;
844 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
845 } else if(uLevel == 0) {
847 * This is a *disgusting* hack.
848 * This is *so* bad that even I'm embarrassed (and I
849 * have no shame). Here's the deal :
850 * Until we get the correct SPOOLSS code into smbd
851 * then when we're running with NT SMB support then
852 * NT makes this call with a level of zero, and then
853 * immediately follows it with an open request to
854 * the \\SRVSVC pipe. If we allow that open to
855 * succeed then NT barfs when it cannot open the
856 * \\SPOOLSS pipe immediately after and continually
857 * whines saying "Printer name is invalid" forever
858 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
859 * to fail, then NT downgrades to using the downlevel code
860 * and everything works as well as before. I hate
861 * myself for adding this code.... JRA.
864 fail_next_srvsvc_open();
867 *rdata_len = desc.usedlen;
869 *rparam_len = 6;
870 *rparam = REALLOC(*rparam,*rparam_len);
871 SSVALS(*rparam,0,desc.errcode);
872 SSVAL(*rparam,2,0);
873 SSVAL(*rparam,4,desc.neededlen);
875 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
877 if (queue) free(queue);
879 return(True);
883 /****************************************************************************
884 view list of all print jobs on all queues
885 ****************************************************************************/
886 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
887 int mdrcnt, int mprcnt,
888 char **rdata, char** rparam,
889 int *rdata_len, int *rparam_len)
891 char *param_format = param+2;
892 char *output_format1 = skip_string(param_format,1);
893 char *p = skip_string(output_format1,1);
894 int uLevel = SVAL(p,0);
895 char *output_format2 = p + 4;
896 int services = lp_numservices();
897 int i, n;
898 struct pack_desc desc;
899 print_queue_struct **queue = NULL;
900 print_status_struct *status = NULL;
901 int* subcntarr = NULL;
902 int queuecnt, subcnt=0, succnt=0;
904 bzero(&desc,sizeof(desc));
906 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
908 if (!prefix_ok(param_format,"WrLeh")) return False;
909 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
910 return False;
911 queuecnt = 0;
912 for (i = 0; i < services; i++)
913 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
914 queuecnt++;
915 if (uLevel > 0) {
916 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
917 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
918 return False;
920 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
921 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
922 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
923 return False;
925 memset(status,0,queuecnt*sizeof(print_status_struct));
926 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
927 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
928 return False;
930 subcnt = 0;
931 n = 0;
932 for (i = 0; i < services; i++)
933 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
934 subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]);
935 subcnt += subcntarr[n];
936 n++;
939 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
940 desc.base = *rdata;
941 desc.buflen = mdrcnt;
943 if (init_package(&desc,queuecnt,subcnt)) {
944 n = 0;
945 succnt = 0;
946 for (i = 0; i < services; i++)
947 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
948 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
949 n++;
950 if (desc.errcode == NERR_Success) succnt = n;
954 if (subcntarr) free(subcntarr);
956 *rdata_len = desc.usedlen;
957 *rparam_len = 8;
958 *rparam = REALLOC(*rparam,*rparam_len);
959 SSVALS(*rparam,0,desc.errcode);
960 SSVAL(*rparam,2,0);
961 SSVAL(*rparam,4,succnt);
962 SSVAL(*rparam,6,queuecnt);
964 for (i = 0; i < queuecnt; i++) {
965 if (queue && queue[i]) free(queue[i]);
968 if (queue) free(queue);
969 if (status) free(status);
971 return True;
974 /****************************************************************************
975 get info level for a server list query
976 ****************************************************************************/
977 static BOOL check_server_info(int uLevel, char* id)
979 switch( uLevel ) {
980 case 0:
981 if (strcmp(id,"B16") != 0) return False;
982 break;
983 case 1:
984 if (strcmp(id,"B16BBDz") != 0) return False;
985 break;
986 default:
987 return False;
989 return True;
992 struct srv_info_struct
994 fstring name;
995 uint32 type;
996 fstring comment;
997 fstring domain;
998 BOOL server_added;
1002 /*******************************************************************
1003 get server info lists from the files saved by nmbd. Return the
1004 number of entries
1005 ******************************************************************/
1006 static int get_server_info(uint32 servertype,
1007 struct srv_info_struct **servers,
1008 char *domain)
1010 FILE *f;
1011 pstring fname;
1012 int count=0;
1013 int alloced=0;
1014 pstring line;
1015 BOOL local_list_only;
1017 pstrcpy(fname,lp_lockdir());
1018 trim_string(fname,NULL,"/");
1019 pstrcat(fname,"/");
1020 pstrcat(fname,SERVER_LIST);
1022 f = sys_fopen(fname,"r");
1024 if (!f) {
1025 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1026 return(0);
1029 /* request for everything is code for request all servers */
1030 if (servertype == SV_TYPE_ALL)
1031 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1033 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1035 DEBUG(4,("Servertype search: %8x\n",servertype));
1037 while (!feof(f))
1039 fstring stype;
1040 struct srv_info_struct *s;
1041 char *ptr = line;
1042 BOOL ok = True;
1043 *ptr = 0;
1045 fgets(line,sizeof(line)-1,f);
1046 if (!*line) continue;
1048 if (count == alloced) {
1049 alloced += 10;
1050 (*servers) = (struct srv_info_struct *)
1051 Realloc(*servers,sizeof(**servers)*alloced);
1052 if (!(*servers)) return(0);
1053 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
1055 s = &(*servers)[count];
1057 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1058 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1059 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1060 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1061 /* this allows us to cope with an old nmbd */
1062 pstrcpy(s->domain,global_myworkgroup);
1065 if (sscanf(stype,"%X",&s->type) != 1) {
1066 DEBUG(4,("r:host file "));
1067 ok = False;
1070 /* Filter the servers/domains we return based on what was asked for. */
1072 /* Check to see if we are being asked for a local list only. */
1073 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1074 DEBUG(4,("r: local list only"));
1075 ok = False;
1078 /* doesn't match up: don't want it */
1079 if (!(servertype & s->type)) {
1080 DEBUG(4,("r:serv type "));
1081 ok = False;
1084 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1085 (s->type & SV_TYPE_DOMAIN_ENUM))
1087 DEBUG(4,("s: dom mismatch "));
1088 ok = False;
1091 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1093 ok = False;
1096 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1097 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1099 if (ok)
1101 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1102 s->name, s->type, s->comment, s->domain));
1104 s->server_added = True;
1105 count++;
1107 else
1109 DEBUG(4,("%20s %8x %25s %15s\n",
1110 s->name, s->type, s->comment, s->domain));
1114 fclose(f);
1115 return(count);
1119 /*******************************************************************
1120 fill in a server info structure
1121 ******************************************************************/
1122 static int fill_srv_info(struct srv_info_struct *service,
1123 int uLevel, char **buf, int *buflen,
1124 char **stringbuf, int *stringspace, char *baseaddr)
1126 int struct_len;
1127 char* p;
1128 char* p2;
1129 int l2;
1130 int len;
1132 switch (uLevel) {
1133 case 0: struct_len = 16; break;
1134 case 1: struct_len = 26; break;
1135 default: return -1;
1138 if (!buf)
1140 len = 0;
1141 switch (uLevel)
1143 case 1:
1144 len = strlen(service->comment)+1;
1145 break;
1148 if (buflen) *buflen = struct_len;
1149 if (stringspace) *stringspace = len;
1150 return struct_len + len;
1153 len = struct_len;
1154 p = *buf;
1155 if (*buflen < struct_len) return -1;
1156 if (stringbuf)
1158 p2 = *stringbuf;
1159 l2 = *stringspace;
1161 else
1163 p2 = p + struct_len;
1164 l2 = *buflen - struct_len;
1166 if (!baseaddr) baseaddr = p;
1168 switch (uLevel)
1170 case 0:
1171 StrnCpy(p,service->name,15);
1172 break;
1174 case 1:
1175 StrnCpy(p,service->name,15);
1176 SIVAL(p,18,service->type);
1177 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1178 len += CopyAndAdvance(&p2,service->comment,&l2);
1179 break;
1182 if (stringbuf)
1184 *buf = p + struct_len;
1185 *buflen -= struct_len;
1186 *stringbuf = p2;
1187 *stringspace = l2;
1189 else
1191 *buf = p2;
1192 *buflen -= len;
1194 return len;
1198 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1200 return(strcmp(s1->name,s2->name));
1203 /****************************************************************************
1204 view list of servers available (or possibly domains). The info is
1205 extracted from lists saved by nmbd on the local host
1206 ****************************************************************************/
1207 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1208 int mdrcnt, int mprcnt, char **rdata,
1209 char **rparam, int *rdata_len, int *rparam_len)
1211 char *str1 = param+2;
1212 char *str2 = skip_string(str1,1);
1213 char *p = skip_string(str2,1);
1214 int uLevel = SVAL(p,0);
1215 int buf_len = SVAL(p,2);
1216 uint32 servertype = IVAL(p,4);
1217 char *p2;
1218 int data_len, fixed_len, string_len;
1219 int f_len = 0, s_len = 0;
1220 struct srv_info_struct *servers=NULL;
1221 int counted=0,total=0;
1222 int i,missed;
1223 fstring domain;
1224 BOOL domain_request;
1225 BOOL local_request;
1227 /* If someone sets all the bits they don't really mean to set
1228 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1229 known servers. */
1231 if (servertype == SV_TYPE_ALL)
1232 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1234 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1235 any other bit (they may just set this bit on it's own) they
1236 want all the locally seen servers. However this bit can be
1237 set on its own so set the requested servers to be
1238 ALL - DOMAIN_ENUM. */
1240 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1241 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1243 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1244 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1246 p += 8;
1248 if (!prefix_ok(str1,"WrLehD")) return False;
1249 if (!check_server_info(uLevel,str2)) return False;
1251 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1252 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1253 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1255 if (strcmp(str1, "WrLehDz") == 0) {
1256 StrnCpy(domain, p, sizeof(fstring)-1);
1257 } else {
1258 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1261 if (lp_browse_list())
1262 total = get_server_info(servertype,&servers,domain);
1264 data_len = fixed_len = string_len = 0;
1265 missed = 0;
1267 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1270 char *lastname=NULL;
1272 for (i=0;i<total;i++)
1274 struct srv_info_struct *s = &servers[i];
1275 if (lastname && strequal(lastname,s->name)) continue;
1276 lastname = s->name;
1277 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1278 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1279 s->name, s->type, s->comment, s->domain));
1281 if (data_len <= buf_len) {
1282 counted++;
1283 fixed_len += f_len;
1284 string_len += s_len;
1285 } else {
1286 missed++;
1291 *rdata_len = fixed_len + string_len;
1292 *rdata = REALLOC(*rdata,*rdata_len);
1293 bzero(*rdata,*rdata_len);
1295 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1296 p = *rdata;
1297 f_len = fixed_len;
1298 s_len = string_len;
1301 char *lastname=NULL;
1302 int count2 = counted;
1303 for (i = 0; i < total && count2;i++)
1305 struct srv_info_struct *s = &servers[i];
1306 if (lastname && strequal(lastname,s->name)) continue;
1307 lastname = s->name;
1308 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1309 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1310 s->name, s->type, s->comment, s->domain));
1311 count2--;
1315 *rparam_len = 8;
1316 *rparam = REALLOC(*rparam,*rparam_len);
1317 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1318 SSVAL(*rparam,2,0);
1319 SSVAL(*rparam,4,counted);
1320 SSVAL(*rparam,6,counted+missed);
1322 if (servers) free(servers);
1324 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1325 domain,uLevel,counted,counted+missed));
1327 return(True);
1330 /****************************************************************************
1331 command 0x34 - suspected of being a "Lookup Names" stub api
1332 ****************************************************************************/
1333 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1334 int mdrcnt, int mprcnt, char **rdata,
1335 char **rparam, int *rdata_len, int *rparam_len)
1337 char *str1 = param+2;
1338 char *str2 = skip_string(str1,1);
1339 char *p = skip_string(str2,1);
1340 int uLevel = SVAL(p,0);
1341 int buf_len = SVAL(p,2);
1342 int counted=0;
1343 int missed=0;
1345 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1346 str1, str2, p, uLevel, buf_len));
1348 if (!prefix_ok(str1,"zWrLeh")) return False;
1350 *rdata_len = 0;
1351 *rdata = NULL;
1353 *rparam_len = 8;
1354 *rparam = REALLOC(*rparam,*rparam_len);
1356 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1357 SSVAL(*rparam,2,0);
1358 SSVAL(*rparam,4,counted);
1359 SSVAL(*rparam,6,counted+missed);
1361 return(True);
1364 /****************************************************************************
1365 get info about a share
1366 ****************************************************************************/
1367 static BOOL check_share_info(int uLevel, char* id)
1369 switch( uLevel ) {
1370 case 0:
1371 if (strcmp(id,"B13") != 0) return False;
1372 break;
1373 case 1:
1374 if (strcmp(id,"B13BWz") != 0) return False;
1375 break;
1376 case 2:
1377 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1378 break;
1379 case 91:
1380 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1381 break;
1382 default: return False;
1384 return True;
1387 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1388 char** buf, int* buflen,
1389 char** stringbuf, int* stringspace, char* baseaddr)
1391 int struct_len;
1392 char* p;
1393 char* p2;
1394 int l2;
1395 int len;
1397 switch( uLevel ) {
1398 case 0: struct_len = 13; break;
1399 case 1: struct_len = 20; break;
1400 case 2: struct_len = 40; break;
1401 case 91: struct_len = 68; break;
1402 default: return -1;
1406 if (!buf)
1408 len = 0;
1409 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1410 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1411 if (buflen) *buflen = struct_len;
1412 if (stringspace) *stringspace = len;
1413 return struct_len + len;
1416 len = struct_len;
1417 p = *buf;
1418 if ((*buflen) < struct_len) return -1;
1419 if (stringbuf)
1421 p2 = *stringbuf;
1422 l2 = *stringspace;
1424 else
1426 p2 = p + struct_len;
1427 l2 = (*buflen) - struct_len;
1429 if (!baseaddr) baseaddr = p;
1431 StrnCpy(p,lp_servicename(snum),13);
1433 if (uLevel > 0)
1435 int type;
1436 CVAL(p,13) = 0;
1437 type = STYPE_DISKTREE;
1438 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1439 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1440 SSVAL(p,14,type); /* device type */
1441 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1442 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1445 if (uLevel > 1)
1447 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1448 SSVALS(p,22,-1); /* max uses */
1449 SSVAL(p,24,1); /* current uses */
1450 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1451 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1452 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1455 if (uLevel > 2)
1457 memset(p+40,0,SHPWLEN+2);
1458 SSVAL(p,50,0);
1459 SIVAL(p,52,0);
1460 SSVAL(p,56,0);
1461 SSVAL(p,58,0);
1462 SIVAL(p,60,0);
1463 SSVAL(p,64,0);
1464 SSVAL(p,66,0);
1467 if (stringbuf)
1469 (*buf) = p + struct_len;
1470 (*buflen) -= struct_len;
1471 (*stringbuf) = p2;
1472 (*stringspace) = l2;
1474 else
1476 (*buf) = p2;
1477 (*buflen) -= len;
1479 return len;
1482 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1483 int mdrcnt,int mprcnt,
1484 char **rdata,char **rparam,
1485 int *rdata_len,int *rparam_len)
1487 char *str1 = param+2;
1488 char *str2 = skip_string(str1,1);
1489 char *netname = skip_string(str2,1);
1490 char *p = skip_string(netname,1);
1491 int uLevel = SVAL(p,0);
1492 int snum = find_service(netname);
1494 if (snum < 0) return False;
1496 /* check it's a supported varient */
1497 if (!prefix_ok(str1,"zWrLh")) return False;
1498 if (!check_share_info(uLevel,str2)) return False;
1500 *rdata = REALLOC(*rdata,mdrcnt);
1501 p = *rdata;
1502 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1503 if (*rdata_len < 0) return False;
1505 *rparam_len = 6;
1506 *rparam = REALLOC(*rparam,*rparam_len);
1507 SSVAL(*rparam,0,NERR_Success);
1508 SSVAL(*rparam,2,0); /* converter word */
1509 SSVAL(*rparam,4,*rdata_len);
1511 return(True);
1514 /****************************************************************************
1515 view list of shares available
1516 ****************************************************************************/
1517 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1518 int mdrcnt,int mprcnt,
1519 char **rdata,char **rparam,
1520 int *rdata_len,int *rparam_len)
1522 char *str1 = param+2;
1523 char *str2 = skip_string(str1,1);
1524 char *p = skip_string(str2,1);
1525 int uLevel = SVAL(p,0);
1526 int buf_len = SVAL(p,2);
1527 char *p2;
1528 int count=lp_numservices();
1529 int total=0,counted=0;
1530 BOOL missed = False;
1531 int i;
1532 int data_len, fixed_len, string_len;
1533 int f_len = 0, s_len = 0;
1535 if (!prefix_ok(str1,"WrLeh")) return False;
1536 if (!check_share_info(uLevel,str2)) return False;
1538 data_len = fixed_len = string_len = 0;
1539 for (i=0;i<count;i++)
1540 if (lp_browseable(i) && lp_snum_ok(i))
1542 total++;
1543 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1544 if (data_len <= buf_len)
1546 counted++;
1547 fixed_len += f_len;
1548 string_len += s_len;
1550 else
1551 missed = True;
1553 *rdata_len = fixed_len + string_len;
1554 *rdata = REALLOC(*rdata,*rdata_len);
1555 memset(*rdata,0,*rdata_len);
1557 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1558 p = *rdata;
1559 f_len = fixed_len;
1560 s_len = string_len;
1561 for (i = 0; i < count;i++)
1562 if (lp_browseable(i) && lp_snum_ok(i))
1563 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1564 break;
1566 *rparam_len = 8;
1567 *rparam = REALLOC(*rparam,*rparam_len);
1568 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1569 SSVAL(*rparam,2,0);
1570 SSVAL(*rparam,4,counted);
1571 SSVAL(*rparam,6,total);
1573 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1574 counted,total,uLevel,
1575 buf_len,*rdata_len,mdrcnt));
1576 return(True);
1581 /****************************************************************************
1582 get the time of day info
1583 ****************************************************************************/
1584 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1585 int mdrcnt,int mprcnt,
1586 char **rdata,char **rparam,
1587 int *rdata_len,int *rparam_len)
1589 char *p;
1590 *rparam_len = 4;
1591 *rparam = REALLOC(*rparam,*rparam_len);
1593 *rdata_len = 21;
1594 *rdata = REALLOC(*rdata,*rdata_len);
1596 SSVAL(*rparam,0,NERR_Success);
1597 SSVAL(*rparam,2,0); /* converter word */
1599 p = *rdata;
1602 struct tm *t;
1603 time_t unixdate = time(NULL);
1605 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1606 by NT in a "net time" operation,
1607 it seems to ignore the one below */
1609 /* the client expects to get localtime, not GMT, in this bit
1610 (I think, this needs testing) */
1611 t = LocalTime(&unixdate);
1613 SIVAL(p,4,0); /* msecs ? */
1614 CVAL(p,8) = t->tm_hour;
1615 CVAL(p,9) = t->tm_min;
1616 CVAL(p,10) = t->tm_sec;
1617 CVAL(p,11) = 0; /* hundredths of seconds */
1618 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1619 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1620 CVAL(p,16) = t->tm_mday;
1621 CVAL(p,17) = t->tm_mon + 1;
1622 SSVAL(p,18,1900+t->tm_year);
1623 CVAL(p,20) = t->tm_wday;
1627 return(True);
1630 /****************************************************************************
1631 set the user password
1632 ****************************************************************************/
1633 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1634 int mdrcnt,int mprcnt,
1635 char **rdata,char **rparam,
1636 int *rdata_len,int *rparam_len)
1638 char *p = skip_string(param+2,2);
1639 fstring user;
1640 fstring pass1,pass2;
1642 fstrcpy(user,p);
1644 p = skip_string(p,1);
1646 memcpy(pass1,p,16);
1647 memcpy(pass2,p+16,16);
1649 *rparam_len = 4;
1650 *rparam = REALLOC(*rparam,*rparam_len);
1652 *rdata_len = 0;
1654 SSVAL(*rparam,0,NERR_badpass);
1655 SSVAL(*rparam,2,0); /* converter word */
1657 DEBUG(3,("Set password for <%s>\n",user));
1660 * Pass the user through the NT -> unix user mapping
1661 * function.
1664 (void)map_username(user);
1667 * Do any UNIX username case mangling.
1669 (void)Get_Pwnam( user, True);
1672 * Attempt the plaintext password change first.
1673 * Older versions of Windows seem to do this.
1676 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1677 chgpasswd(user,pass1,pass2,False))
1679 SSVAL(*rparam,0,NERR_Success);
1683 * If the plaintext change failed, attempt
1684 * the encrypted. NT will generate this
1685 * after trying the samr method.
1688 if(SVAL(*rparam,0) != NERR_Success)
1690 struct smb_passwd *sampw = NULL;
1692 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1693 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1695 SSVAL(*rparam,0,NERR_Success);
1699 bzero(pass1,sizeof(fstring));
1700 bzero(pass2,sizeof(fstring));
1702 return(True);
1705 /****************************************************************************
1706 Set the user password (SamOEM version - gets plaintext).
1707 ****************************************************************************/
1709 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1710 int mdrcnt,int mprcnt,
1711 char **rdata,char **rparam,
1712 int *rdata_len,int *rparam_len)
1714 fstring user;
1715 char *p = param + 2;
1716 *rparam_len = 2;
1717 *rparam = REALLOC(*rparam,*rparam_len);
1719 *rdata_len = 0;
1721 SSVAL(*rparam,0,NERR_badpass);
1724 * Check the parameter definition is correct.
1726 if(!strequal(param + 2, "zsT")) {
1727 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1728 return False;
1730 p = skip_string(p, 1);
1732 if(!strequal(p, "B516B16")) {
1733 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1734 return False;
1736 p = skip_string(p,1);
1738 fstrcpy(user,p);
1739 p = skip_string(p,1);
1741 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1744 * Pass the user through the NT -> unix user mapping
1745 * function.
1748 (void)map_username(user);
1751 * Do any UNIX username case mangling.
1753 (void)Get_Pwnam( user, True);
1755 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1757 SSVAL(*rparam,0,NERR_Success);
1760 return(True);
1763 /****************************************************************************
1764 delete a print job
1765 Form: <W> <>
1766 ****************************************************************************/
1767 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1768 int mdrcnt,int mprcnt,
1769 char **rdata,char **rparam,
1770 int *rdata_len,int *rparam_len)
1772 int function = SVAL(param,0);
1773 char *str1 = param+2;
1774 char *str2 = skip_string(str1,1);
1775 char *p = skip_string(str2,1);
1776 int jobid, snum;
1777 int i, count;
1779 printjob_decode(SVAL(p,0), &snum, &jobid);
1781 /* check it's a supported varient */
1782 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1783 return(False);
1785 *rparam_len = 4;
1786 *rparam = REALLOC(*rparam,*rparam_len);
1788 *rdata_len = 0;
1790 SSVAL(*rparam,0,NERR_Success);
1792 if (snum >= 0 && VALID_SNUM(snum))
1794 print_queue_struct *queue=NULL;
1795 lpq_reset(snum);
1796 count = get_printqueue(snum,conn,&queue,NULL);
1798 for (i=0;i<count;i++)
1799 if ((queue[i].job&0xFF) == jobid)
1801 switch (function) {
1802 case 81: /* delete */
1803 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1804 del_printqueue(conn,snum,queue[i].job);
1805 break;
1806 case 82: /* pause */
1807 case 83: /* resume */
1808 DEBUG(3,("%s queue entry %d\n",
1809 (function==82?"pausing":"resuming"),queue[i].job));
1810 status_printjob(conn,snum,queue[i].job,
1811 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1812 break;
1814 break;
1817 if (i==count)
1818 SSVAL(*rparam,0,NERR_JobNotFound);
1820 if (queue) free(queue);
1823 SSVAL(*rparam,2,0); /* converter word */
1825 return(True);
1828 /****************************************************************************
1829 Purge a print queue - or pause or resume it.
1830 ****************************************************************************/
1831 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1832 int mdrcnt,int mprcnt,
1833 char **rdata,char **rparam,
1834 int *rdata_len,int *rparam_len)
1836 int function = SVAL(param,0);
1837 char *str1 = param+2;
1838 char *str2 = skip_string(str1,1);
1839 char *QueueName = skip_string(str2,1);
1840 int snum;
1842 /* check it's a supported varient */
1843 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1844 return(False);
1846 *rparam_len = 4;
1847 *rparam = REALLOC(*rparam,*rparam_len);
1849 *rdata_len = 0;
1851 SSVAL(*rparam,0,NERR_Success);
1852 SSVAL(*rparam,2,0); /* converter word */
1854 snum = lp_servicenumber(QueueName);
1855 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1856 int pnum = lp_servicenumber(PRINTERS_NAME);
1857 if (pnum >= 0) {
1858 lp_add_printer(QueueName,pnum);
1859 snum = lp_servicenumber(QueueName);
1863 if (snum >= 0 && VALID_SNUM(snum)) {
1864 lpq_reset(snum);
1866 switch (function) {
1867 case 74: /* Pause queue */
1868 case 75: /* Resume queue */
1869 status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
1870 DEBUG(3,("Print queue %s, queue=%s\n",
1871 (function==74?"pause":"resume"),QueueName));
1872 break;
1873 case 103: /* Purge */
1875 print_queue_struct *queue=NULL;
1876 int i, count;
1877 count = get_printqueue(snum,conn,&queue,NULL);
1878 for (i = 0; i < count; i++)
1879 del_printqueue(conn,snum,queue[i].job);
1881 if (queue) free(queue);
1882 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1883 break;
1888 return(True);
1892 /****************************************************************************
1893 set the property of a print job (undocumented?)
1894 ? function = 0xb -> set name of print job
1895 ? function = 0x6 -> move print job up/down
1896 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1897 or <WWsTP> <WB21BB16B10zWWzDDz>
1898 ****************************************************************************/
1899 static int check_printjob_info(struct pack_desc* desc,
1900 int uLevel, char* id)
1902 desc->subformat = NULL;
1903 switch( uLevel ) {
1904 case 0: desc->format = "W"; break;
1905 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1906 case 2: desc->format = "WWzWWDDzz"; break;
1907 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1908 default: return False;
1910 if (strcmp(desc->format,id) != 0) return False;
1911 return True;
1914 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1915 int mdrcnt,int mprcnt,
1916 char **rdata,char **rparam,
1917 int *rdata_len,int *rparam_len)
1919 struct pack_desc desc;
1920 char *str1 = param+2;
1921 char *str2 = skip_string(str1,1);
1922 char *p = skip_string(str2,1);
1923 int jobid, snum;
1924 int uLevel = SVAL(p,2);
1925 int function = SVAL(p,4); /* what is this ?? */
1926 int i;
1927 char *s = data;
1928 files_struct *fsp;
1930 printjob_decode(SVAL(p,0), &snum, &jobid);
1932 *rparam_len = 4;
1933 *rparam = REALLOC(*rparam,*rparam_len);
1935 *rdata_len = 0;
1937 /* check it's a supported varient */
1938 if ((strcmp(str1,"WWsTP")) ||
1939 (!check_printjob_info(&desc,uLevel,str2)))
1940 return(False);
1942 switch (function) {
1943 case 0x6: /* change job place in the queue,
1944 data gives the new place */
1945 if (snum >= 0 && VALID_SNUM(snum)) {
1946 print_queue_struct *queue=NULL;
1947 int count;
1949 lpq_reset(snum);
1950 count = get_printqueue(snum,conn,&queue,NULL);
1951 for (i=0;i<count;i++) /* find job */
1952 if ((queue[i].job&0xFF) == jobid) break;
1954 if (i==count) {
1955 desc.errcode=NERR_JobNotFound;
1956 if (queue) free(queue);
1957 } else {
1958 desc.errcode=NERR_Success;
1959 i++;
1960 #if 0
1962 int place= SVAL(data,0);
1963 /* we currently have no way of
1964 doing this. Can any unix do it? */
1965 if (i < place) /* move down */;
1966 else if (i > place ) /* move up */;
1968 #endif
1969 desc.errcode=NERR_notsupported; /* not yet
1970 supported */
1971 if (queue) free(queue);
1973 } else {
1974 desc.errcode=NERR_JobNotFound;
1976 break;
1978 case 0xb: /* change print job name, data gives the name */
1979 /* jobid, snum should be zero */
1980 if (isalpha((int)*s)) {
1981 pstring name;
1982 int l = 0;
1983 while (l<64 && *s) {
1984 if (issafe(*s)) name[l++] = *s;
1985 s++;
1987 name[l] = 0;
1989 DEBUG(3,("Setting print name to %s\n",name));
1991 fsp = file_find_print();
1993 if (fsp) {
1994 connection_struct *fconn = fsp->conn;
1995 unbecome_user();
1997 if (!become_user(fconn,vuid) ||
1998 !become_service(fconn,True))
1999 break;
2001 if (dos_rename(fsp->fsp_name,name) == 0) {
2002 string_set(&fsp->fsp_name,name);
2004 break;
2007 desc.errcode=NERR_Success;
2008 break;
2010 default: /* not implemented */
2011 return False;
2014 SSVALS(*rparam,0,desc.errcode);
2015 SSVAL(*rparam,2,0); /* converter word */
2017 return(True);
2021 /****************************************************************************
2022 get info about the server
2023 ****************************************************************************/
2024 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2025 int mdrcnt,int mprcnt,
2026 char **rdata,char **rparam,
2027 int *rdata_len,int *rparam_len)
2029 char *str1 = param+2;
2030 char *str2 = skip_string(str1,1);
2031 char *p = skip_string(str2,1);
2032 int uLevel = SVAL(p,0);
2033 char *p2;
2034 int struct_len;
2036 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2038 /* check it's a supported varient */
2039 if (!prefix_ok(str1,"WrLh")) return False;
2040 switch( uLevel ) {
2041 case 0:
2042 if (strcmp(str2,"B16") != 0) return False;
2043 struct_len = 16;
2044 break;
2045 case 1:
2046 if (strcmp(str2,"B16BBDz") != 0) return False;
2047 struct_len = 26;
2048 break;
2049 case 2:
2050 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2051 != 0) return False;
2052 struct_len = 134;
2053 break;
2054 case 3:
2055 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2056 != 0) return False;
2057 struct_len = 144;
2058 break;
2059 case 20:
2060 if (strcmp(str2,"DN") != 0) return False;
2061 struct_len = 6;
2062 break;
2063 case 50:
2064 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2065 struct_len = 42;
2066 break;
2067 default: return False;
2070 *rdata_len = mdrcnt;
2071 *rdata = REALLOC(*rdata,*rdata_len);
2073 p = *rdata;
2074 p2 = p + struct_len;
2075 if (uLevel != 20) {
2076 StrnCpy(p,local_machine,16);
2077 strupper(p);
2079 p += 16;
2080 if (uLevel > 0)
2082 struct srv_info_struct *servers=NULL;
2083 int i,count;
2084 pstring comment;
2085 uint32 servertype= lp_default_server_announce();
2087 pstrcpy(comment,lp_serverstring());
2089 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2090 for (i=0;i<count;i++)
2091 if (strequal(servers[i].name,local_machine))
2093 servertype = servers[i].type;
2094 pstrcpy(comment,servers[i].comment);
2097 if (servers) free(servers);
2099 SCVAL(p,0,lp_major_announce_version());
2100 SCVAL(p,1,lp_minor_announce_version());
2101 SIVAL(p,2,servertype);
2103 if (mdrcnt == struct_len) {
2104 SIVAL(p,6,0);
2105 } else {
2106 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2107 standard_sub(conn,comment);
2108 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2109 p2 = skip_string(p2,1);
2112 if (uLevel > 1)
2114 return False; /* not yet implemented */
2117 *rdata_len = PTR_DIFF(p2,*rdata);
2119 *rparam_len = 6;
2120 *rparam = REALLOC(*rparam,*rparam_len);
2121 SSVAL(*rparam,0,NERR_Success);
2122 SSVAL(*rparam,2,0); /* converter word */
2123 SSVAL(*rparam,4,*rdata_len);
2125 return(True);
2129 /****************************************************************************
2130 get info about the server
2131 ****************************************************************************/
2132 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2133 int mdrcnt,int mprcnt,
2134 char **rdata,char **rparam,
2135 int *rdata_len,int *rparam_len)
2137 char *str1 = param+2;
2138 char *str2 = skip_string(str1,1);
2139 char *p = skip_string(str2,1);
2140 char *p2;
2141 extern pstring sesssetup_user;
2142 int level = SVAL(p,0);
2144 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2146 *rparam_len = 6;
2147 *rparam = REALLOC(*rparam,*rparam_len);
2149 /* check it's a supported varient */
2150 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2151 return(False);
2153 *rdata_len = mdrcnt + 1024;
2154 *rdata = REALLOC(*rdata,*rdata_len);
2156 SSVAL(*rparam,0,NERR_Success);
2157 SSVAL(*rparam,2,0); /* converter word */
2159 p = *rdata;
2160 p2 = p + 22;
2163 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2164 pstrcpy(p2,local_machine);
2165 strupper(p2);
2166 p2 = skip_string(p2,1);
2167 p += 4;
2169 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2170 pstrcpy(p2,sesssetup_user);
2171 p2 = skip_string(p2,1);
2172 p += 4;
2174 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2175 pstrcpy(p2,global_myworkgroup);
2176 strupper(p2);
2177 p2 = skip_string(p2,1);
2178 p += 4;
2180 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2181 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2182 p += 2;
2184 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2185 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2186 p2 = skip_string(p2,1);
2187 p += 4;
2189 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2190 pstrcpy(p2,"");
2191 p2 = skip_string(p2,1);
2192 p += 4;
2194 *rdata_len = PTR_DIFF(p2,*rdata);
2196 SSVAL(*rparam,4,*rdata_len);
2198 return(True);
2201 /****************************************************************************
2202 get info about a user
2204 struct user_info_11 {
2205 char usri11_name[21]; 0-20
2206 char usri11_pad; 21
2207 char *usri11_comment; 22-25
2208 char *usri11_usr_comment; 26-29
2209 unsigned short usri11_priv; 30-31
2210 unsigned long usri11_auth_flags; 32-35
2211 long usri11_password_age; 36-39
2212 char *usri11_homedir; 40-43
2213 char *usri11_parms; 44-47
2214 long usri11_last_logon; 48-51
2215 long usri11_last_logoff; 52-55
2216 unsigned short usri11_bad_pw_count; 56-57
2217 unsigned short usri11_num_logons; 58-59
2218 char *usri11_logon_server; 60-63
2219 unsigned short usri11_country_code; 64-65
2220 char *usri11_workstations; 66-69
2221 unsigned long usri11_max_storage; 70-73
2222 unsigned short usri11_units_per_week; 74-75
2223 unsigned char *usri11_logon_hours; 76-79
2224 unsigned short usri11_code_page; 80-81
2227 where:
2229 usri11_name specifies the user name for which information is retireved
2231 usri11_pad aligns the next data structure element to a word boundary
2233 usri11_comment is a null terminated ASCII comment
2235 usri11_user_comment is a null terminated ASCII comment about the user
2237 usri11_priv specifies the level of the privilege assigned to the user.
2238 The possible values are:
2240 Name Value Description
2241 USER_PRIV_GUEST 0 Guest privilege
2242 USER_PRIV_USER 1 User privilege
2243 USER_PRV_ADMIN 2 Administrator privilege
2245 usri11_auth_flags specifies the account operator privileges. The
2246 possible values are:
2248 Name Value Description
2249 AF_OP_PRINT 0 Print operator
2252 Leach, Naik [Page 28] \f
2255 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2258 AF_OP_COMM 1 Communications operator
2259 AF_OP_SERVER 2 Server operator
2260 AF_OP_ACCOUNTS 3 Accounts operator
2263 usri11_password_age specifies how many seconds have elapsed since the
2264 password was last changed.
2266 usri11_home_dir points to a null terminated ASCII string that contains
2267 the path name of the user's home directory.
2269 usri11_parms points to a null terminated ASCII string that is set
2270 aside for use by applications.
2272 usri11_last_logon specifies the time when the user last logged on.
2273 This value is stored as the number of seconds elapsed since
2274 00:00:00, January 1, 1970.
2276 usri11_last_logoff specifies the time when the user last logged off.
2277 This value is stored as the number of seconds elapsed since
2278 00:00:00, January 1, 1970. A value of 0 means the last logoff
2279 time is unknown.
2281 usri11_bad_pw_count specifies the number of incorrect passwords
2282 entered since the last successful logon.
2284 usri11_log1_num_logons specifies the number of times this user has
2285 logged on. A value of -1 means the number of logons is unknown.
2287 usri11_logon_server points to a null terminated ASCII string that
2288 contains the name of the server to which logon requests are sent.
2289 A null string indicates logon requests should be sent to the
2290 domain controller.
2292 usri11_country_code specifies the country code for the user's language
2293 of choice.
2295 usri11_workstations points to a null terminated ASCII string that
2296 contains the names of workstations the user may log on from.
2297 There may be up to 8 workstations, with the names separated by
2298 commas. A null strings indicates there are no restrictions.
2300 usri11_max_storage specifies the maximum amount of disk space the user
2301 can occupy. A value of 0xffffffff indicates there are no
2302 restrictions.
2304 usri11_units_per_week specifies the equal number of time units into
2305 which a week is divided. This value must be equal to 168.
2307 usri11_logon_hours points to a 21 byte (168 bits) string that
2308 specifies the time during which the user can log on. Each bit
2309 represents one unique hour in a week. The first bit (bit 0, word
2310 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2314 Leach, Naik [Page 29] \f
2317 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2320 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2321 are no restrictions.
2323 usri11_code_page specifies the code page for the user's language of
2324 choice
2326 All of the pointers in this data structure need to be treated
2327 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2328 to be ignored. The converter word returned in the parameters section
2329 needs to be subtracted from the lower 16 bits to calculate an offset
2330 into the return buffer where this ASCII string resides.
2332 There is no auxiliary data in the response.
2334 ****************************************************************************/
2336 #define usri11_name 0
2337 #define usri11_pad 21
2338 #define usri11_comment 22
2339 #define usri11_usr_comment 26
2340 #define usri11_full_name 30
2341 #define usri11_priv 34
2342 #define usri11_auth_flags 36
2343 #define usri11_password_age 40
2344 #define usri11_homedir 44
2345 #define usri11_parms 48
2346 #define usri11_last_logon 52
2347 #define usri11_last_logoff 56
2348 #define usri11_bad_pw_count 60
2349 #define usri11_num_logons 62
2350 #define usri11_logon_server 64
2351 #define usri11_country_code 68
2352 #define usri11_workstations 70
2353 #define usri11_max_storage 74
2354 #define usri11_units_per_week 78
2355 #define usri11_logon_hours 80
2356 #define usri11_code_page 84
2357 #define usri11_end 86
2359 #define USER_PRIV_GUEST 0
2360 #define USER_PRIV_USER 1
2361 #define USER_PRIV_ADMIN 2
2363 #define AF_OP_PRINT 0
2364 #define AF_OP_COMM 1
2365 #define AF_OP_SERVER 2
2366 #define AF_OP_ACCOUNTS 3
2369 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2370 int mdrcnt,int mprcnt,
2371 char **rdata,char **rparam,
2372 int *rdata_len,int *rparam_len)
2374 char *str1 = param+2;
2375 char *str2 = skip_string(str1,1);
2376 char *UserName = skip_string(str2,1);
2377 char *p = skip_string(UserName,1);
2378 int uLevel = SVAL(p,0);
2379 char *p2;
2381 /* get NIS home of a previously validated user - simeon */
2382 /* With share level security vuid will always be zero.
2383 Don't depend on vuser being non-null !!. JRA */
2384 user_struct *vuser = get_valid_user_struct(vuid);
2385 if(vuser != NULL)
2386 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name));
2388 *rparam_len = 6;
2389 *rparam = REALLOC(*rparam,*rparam_len);
2391 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2393 /* check it's a supported variant */
2394 if (strcmp(str1,"zWrLh") != 0) return False;
2395 switch( uLevel )
2397 case 0: p2 = "B21"; break;
2398 case 1: p2 = "B21BB16DWzzWz"; break;
2399 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2400 case 10: p2 = "B21Bzzz"; break;
2401 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2402 default: return False;
2405 if (strcmp(p2,str2) != 0) return False;
2407 *rdata_len = mdrcnt + 1024;
2408 *rdata = REALLOC(*rdata,*rdata_len);
2410 SSVAL(*rparam,0,NERR_Success);
2411 SSVAL(*rparam,2,0); /* converter word */
2413 p = *rdata;
2414 p2 = p + usri11_end;
2416 memset(p,0,21);
2417 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2419 if (uLevel > 0)
2421 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2422 *p2 = 0;
2424 if (uLevel >= 10)
2426 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2427 pstrcpy(p2,"Comment");
2428 p2 = skip_string(p2,1);
2430 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2431 pstrcpy(p2,"UserComment");
2432 p2 = skip_string(p2,1);
2434 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2435 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2436 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2437 p2 = skip_string(p2,1);
2440 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2442 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2443 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2444 SIVALS(p,usri11_password_age,-1); /* password age */
2445 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2446 pstrcpy(p2, lp_logon_path());
2447 p2 = skip_string(p2,1);
2448 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2449 pstrcpy(p2,"");
2450 p2 = skip_string(p2,1);
2451 SIVAL(p,usri11_last_logon,0); /* last logon */
2452 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2453 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2454 SSVALS(p,usri11_num_logons,-1); /* num logons */
2455 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2456 pstrcpy(p2,"\\\\*");
2457 p2 = skip_string(p2,1);
2458 SSVAL(p,usri11_country_code,0); /* country code */
2460 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2461 pstrcpy(p2,"");
2462 p2 = skip_string(p2,1);
2464 SIVALS(p,usri11_max_storage,-1); /* max storage */
2465 SSVAL(p,usri11_units_per_week,168); /* units per week */
2466 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2468 /* a simple way to get logon hours at all times. */
2469 memset(p2,0xff,21);
2470 SCVAL(p2,21,0); /* fix zero termination */
2471 p2 = skip_string(p2,1);
2473 SSVAL(p,usri11_code_page,0); /* code page */
2475 if (uLevel == 1 || uLevel == 2)
2477 memset(p+22,' ',16); /* password */
2478 SIVALS(p,38,-1); /* password age */
2479 SSVAL(p,42,
2480 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2481 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2482 pstrcpy(p2,lp_logon_path());
2483 p2 = skip_string(p2,1);
2484 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2485 *p2++ = 0;
2486 SSVAL(p,52,0); /* flags */
2487 SIVAL(p,54,0); /* script_path */
2488 if (uLevel == 2)
2490 SIVAL(p,60,0); /* auth_flags */
2491 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2492 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2493 p2 = skip_string(p2,1);
2494 SIVAL(p,68,0); /* urs_comment */
2495 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2496 pstrcpy(p2,"");
2497 p2 = skip_string(p2,1);
2498 SIVAL(p,76,0); /* workstations */
2499 SIVAL(p,80,0); /* last_logon */
2500 SIVAL(p,84,0); /* last_logoff */
2501 SIVALS(p,88,-1); /* acct_expires */
2502 SIVALS(p,92,-1); /* max_storage */
2503 SSVAL(p,96,168); /* units_per_week */
2504 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2505 memset(p2,-1,21);
2506 p2 += 21;
2507 SSVALS(p,102,-1); /* bad_pw_count */
2508 SSVALS(p,104,-1); /* num_logons */
2509 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2510 pstrcpy(p2,"\\\\%L");
2511 standard_sub_basic(p2);
2512 p2 = skip_string(p2,1);
2513 SSVAL(p,110,49); /* country_code */
2514 SSVAL(p,112,860); /* code page */
2518 *rdata_len = PTR_DIFF(p2,*rdata);
2520 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2522 return(True);
2525 /*******************************************************************
2526 get groups that a user is a member of
2527 ******************************************************************/
2528 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2529 int mdrcnt,int mprcnt,
2530 char **rdata,char **rparam,
2531 int *rdata_len,int *rparam_len)
2533 char *str1 = param+2;
2534 char *str2 = skip_string(str1,1);
2535 char *UserName = skip_string(str2,1);
2536 char *p = skip_string(UserName,1);
2537 int uLevel = SVAL(p,0);
2538 char *p2;
2539 int count=0;
2541 *rparam_len = 8;
2542 *rparam = REALLOC(*rparam,*rparam_len);
2544 /* check it's a supported varient */
2545 if (strcmp(str1,"zWrLeh") != 0) return False;
2546 switch( uLevel ) {
2547 case 0: p2 = "B21"; break;
2548 default: return False;
2550 if (strcmp(p2,str2) != 0) return False;
2552 *rdata_len = mdrcnt + 1024;
2553 *rdata = REALLOC(*rdata,*rdata_len);
2555 SSVAL(*rparam,0,NERR_Success);
2556 SSVAL(*rparam,2,0); /* converter word */
2558 p = *rdata;
2560 /* XXXX we need a real SAM database some day */
2561 pstrcpy(p,"Users"); p += 21; count++;
2562 pstrcpy(p,"Domain Users"); p += 21; count++;
2563 pstrcpy(p,"Guests"); p += 21; count++;
2564 pstrcpy(p,"Domain Guests"); p += 21; count++;
2566 *rdata_len = PTR_DIFF(p,*rdata);
2568 SSVAL(*rparam,4,count); /* is this right?? */
2569 SSVAL(*rparam,6,count); /* is this right?? */
2571 return(True);
2575 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2576 int mdrcnt,int mprcnt,
2577 char **rdata,char **rparam,
2578 int *rdata_len,int *rparam_len)
2580 char *str1 = param+2;
2581 char *str2 = skip_string(str1,1);
2582 char *p = skip_string(str2,1);
2583 int uLevel;
2584 struct pack_desc desc;
2585 char* name;
2586 char* logon_script;
2588 uLevel = SVAL(p,0);
2589 name = p + 2;
2591 bzero(&desc,sizeof(desc));
2593 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2595 /* check it's a supported varient */
2596 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2597 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2598 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2599 desc.base = *rdata;
2600 desc.buflen = mdrcnt;
2601 desc.subformat = NULL;
2602 desc.format = str2;
2604 if (init_package(&desc,1,0))
2606 PACKI(&desc,"W",0); /* code */
2607 PACKS(&desc,"B21",name); /* eff. name */
2608 PACKS(&desc,"B",""); /* pad */
2609 PACKI(&desc,"W",
2610 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2611 PACKI(&desc,"D",0); /* auth flags XXX */
2612 PACKI(&desc,"W",0); /* num logons */
2613 PACKI(&desc,"W",0); /* bad pw count */
2614 PACKI(&desc,"D",0); /* last logon */
2615 PACKI(&desc,"D",-1); /* last logoff */
2616 PACKI(&desc,"D",-1); /* logoff time */
2617 PACKI(&desc,"D",-1); /* kickoff time */
2618 PACKI(&desc,"D",0); /* password age */
2619 PACKI(&desc,"D",0); /* password can change */
2620 PACKI(&desc,"D",-1); /* password must change */
2622 fstring mypath;
2623 fstrcpy(mypath,"\\\\");
2624 fstrcat(mypath,local_machine);
2625 strupper(mypath);
2626 PACKS(&desc,"z",mypath); /* computer */
2628 PACKS(&desc,"z",global_myworkgroup);/* domain */
2630 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2631 /* made sure all macros are fully substituted and available */
2632 logon_script = lp_logon_script();
2633 standard_sub( conn, logon_script );
2634 PACKS(&desc,"z", logon_script); /* script path */
2635 /* End of JHT mods */
2637 PACKI(&desc,"D",0x00000000); /* reserved */
2640 *rdata_len = desc.usedlen;
2641 *rparam_len = 6;
2642 *rparam = REALLOC(*rparam,*rparam_len);
2643 SSVALS(*rparam,0,desc.errcode);
2644 SSVAL(*rparam,2,0);
2645 SSVAL(*rparam,4,desc.neededlen);
2647 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2648 return(True);
2652 /****************************************************************************
2653 api_WAccessGetUserPerms
2654 ****************************************************************************/
2655 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2656 int mdrcnt,int mprcnt,
2657 char **rdata,char **rparam,
2658 int *rdata_len,int *rparam_len)
2660 char *str1 = param+2;
2661 char *str2 = skip_string(str1,1);
2662 char *user = skip_string(str2,1);
2663 char *resource = skip_string(user,1);
2665 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2667 /* check it's a supported varient */
2668 if (strcmp(str1,"zzh") != 0) return False;
2669 if (strcmp(str2,"") != 0) return False;
2671 *rparam_len = 6;
2672 *rparam = REALLOC(*rparam,*rparam_len);
2673 SSVALS(*rparam,0,0); /* errorcode */
2674 SSVAL(*rparam,2,0); /* converter word */
2675 SSVAL(*rparam,4,0x7f); /* permission flags */
2677 return(True);
2680 /****************************************************************************
2681 api_WPrintJobEnumerate
2682 ****************************************************************************/
2683 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2684 int mdrcnt,int mprcnt,
2685 char **rdata,char **rparam,
2686 int *rdata_len,int *rparam_len)
2688 char *str1 = param+2;
2689 char *str2 = skip_string(str1,1);
2690 char *p = skip_string(str2,1);
2691 int uLevel;
2692 int count;
2693 int i;
2694 int snum;
2695 int job;
2696 struct pack_desc desc;
2697 print_queue_struct *queue=NULL;
2698 print_status_struct status;
2700 uLevel = SVAL(p,2);
2702 bzero(&desc,sizeof(desc));
2703 bzero(&status,sizeof(status));
2705 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2707 /* check it's a supported varient */
2708 if (strcmp(str1,"WWrLh") != 0) return False;
2709 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2711 printjob_decode(SVAL(p,0), &snum, &job);
2713 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2715 count = get_printqueue(snum,conn,&queue,&status);
2716 for (i = 0; i < count; i++) {
2717 if ((queue[i].job & 0xFF) == job) break;
2719 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2720 desc.base = *rdata;
2721 desc.buflen = mdrcnt;
2723 if (init_package(&desc,1,0)) {
2724 if (i < count) {
2725 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2726 *rdata_len = desc.usedlen;
2728 else {
2729 desc.errcode = NERR_JobNotFound;
2730 *rdata_len = 0;
2734 *rparam_len = 6;
2735 *rparam = REALLOC(*rparam,*rparam_len);
2736 SSVALS(*rparam,0,desc.errcode);
2737 SSVAL(*rparam,2,0);
2738 SSVAL(*rparam,4,desc.neededlen);
2740 if (queue) free(queue);
2742 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2743 return(True);
2746 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2747 int mdrcnt,int mprcnt,
2748 char **rdata,char **rparam,
2749 int *rdata_len,int *rparam_len)
2751 char *str1 = param+2;
2752 char *str2 = skip_string(str1,1);
2753 char *p = skip_string(str2,1);
2754 char* name = p;
2755 int uLevel;
2756 int count;
2757 int i, succnt=0;
2758 int snum;
2759 struct pack_desc desc;
2760 print_queue_struct *queue=NULL;
2761 print_status_struct status;
2763 bzero(&desc,sizeof(desc));
2764 bzero(&status,sizeof(status));
2766 p = skip_string(p,1);
2767 uLevel = SVAL(p,0);
2769 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2771 /* check it's a supported varient */
2772 if (strcmp(str1,"zWrLeh") != 0) return False;
2773 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2774 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2776 snum = lp_servicenumber(name);
2777 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2778 int pnum = lp_servicenumber(PRINTERS_NAME);
2779 if (pnum >= 0) {
2780 lp_add_printer(name,pnum);
2781 snum = lp_servicenumber(name);
2785 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2787 count = get_printqueue(snum,conn,&queue,&status);
2788 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2789 desc.base = *rdata;
2790 desc.buflen = mdrcnt;
2792 if (init_package(&desc,count,0)) {
2793 succnt = 0;
2794 for (i = 0; i < count; i++) {
2795 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2796 if (desc.errcode == NERR_Success) succnt = i+1;
2800 *rdata_len = desc.usedlen;
2802 *rparam_len = 8;
2803 *rparam = REALLOC(*rparam,*rparam_len);
2804 SSVALS(*rparam,0,desc.errcode);
2805 SSVAL(*rparam,2,0);
2806 SSVAL(*rparam,4,succnt);
2807 SSVAL(*rparam,6,count);
2809 if (queue) free(queue);
2811 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2812 return(True);
2815 static int check_printdest_info(struct pack_desc* desc,
2816 int uLevel, char* id)
2818 desc->subformat = NULL;
2819 switch( uLevel ) {
2820 case 0: desc->format = "B9"; break;
2821 case 1: desc->format = "B9B21WWzW"; break;
2822 case 2: desc->format = "z"; break;
2823 case 3: desc->format = "zzzWWzzzWW"; break;
2824 default: return False;
2826 if (strcmp(desc->format,id) != 0) return False;
2827 return True;
2830 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2831 struct pack_desc* desc)
2833 char buf[100];
2834 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2835 buf[sizeof(buf)-1] = 0;
2836 strupper(buf);
2837 if (uLevel <= 1) {
2838 PACKS(desc,"B9",buf); /* szName */
2839 if (uLevel == 1) {
2840 PACKS(desc,"B21",""); /* szUserName */
2841 PACKI(desc,"W",0); /* uJobId */
2842 PACKI(desc,"W",0); /* fsStatus */
2843 PACKS(desc,"z",""); /* pszStatus */
2844 PACKI(desc,"W",0); /* time */
2847 if (uLevel == 2 || uLevel == 3) {
2848 PACKS(desc,"z",buf); /* pszPrinterName */
2849 if (uLevel == 3) {
2850 PACKS(desc,"z",""); /* pszUserName */
2851 PACKS(desc,"z",""); /* pszLogAddr */
2852 PACKI(desc,"W",0); /* uJobId */
2853 PACKI(desc,"W",0); /* fsStatus */
2854 PACKS(desc,"z",""); /* pszStatus */
2855 PACKS(desc,"z",""); /* pszComment */
2856 PACKS(desc,"z","NULL"); /* pszDrivers */
2857 PACKI(desc,"W",0); /* time */
2858 PACKI(desc,"W",0); /* pad1 */
2863 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2864 int mdrcnt,int mprcnt,
2865 char **rdata,char **rparam,
2866 int *rdata_len,int *rparam_len)
2868 char *str1 = param+2;
2869 char *str2 = skip_string(str1,1);
2870 char *p = skip_string(str2,1);
2871 char* PrinterName = p;
2872 int uLevel;
2873 struct pack_desc desc;
2874 int snum;
2876 bzero(&desc,sizeof(desc));
2878 p = skip_string(p,1);
2879 uLevel = SVAL(p,0);
2881 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2883 /* check it's a supported varient */
2884 if (strcmp(str1,"zWrLh") != 0) return False;
2885 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2887 snum = lp_servicenumber(PrinterName);
2888 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2889 int pnum = lp_servicenumber(PRINTERS_NAME);
2890 if (pnum >= 0) {
2891 lp_add_printer(PrinterName,pnum);
2892 snum = lp_servicenumber(PrinterName);
2896 if (snum < 0) {
2897 *rdata_len = 0;
2898 desc.errcode = NERR_DestNotFound;
2899 desc.neededlen = 0;
2901 else {
2902 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2903 desc.base = *rdata;
2904 desc.buflen = mdrcnt;
2905 if (init_package(&desc,1,0)) {
2906 fill_printdest_info(conn,snum,uLevel,&desc);
2908 *rdata_len = desc.usedlen;
2911 *rparam_len = 6;
2912 *rparam = REALLOC(*rparam,*rparam_len);
2913 SSVALS(*rparam,0,desc.errcode);
2914 SSVAL(*rparam,2,0);
2915 SSVAL(*rparam,4,desc.neededlen);
2917 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2918 return(True);
2921 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2922 int mdrcnt,int mprcnt,
2923 char **rdata,char **rparam,
2924 int *rdata_len,int *rparam_len)
2926 char *str1 = param+2;
2927 char *str2 = skip_string(str1,1);
2928 char *p = skip_string(str2,1);
2929 int uLevel;
2930 int queuecnt;
2931 int i, n, succnt=0;
2932 struct pack_desc desc;
2933 int services = lp_numservices();
2935 bzero(&desc,sizeof(desc));
2937 uLevel = SVAL(p,0);
2939 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2941 /* check it's a supported varient */
2942 if (strcmp(str1,"WrLeh") != 0) return False;
2943 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2945 queuecnt = 0;
2946 for (i = 0; i < services; i++)
2947 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2948 queuecnt++;
2950 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2951 desc.base = *rdata;
2952 desc.buflen = mdrcnt;
2953 if (init_package(&desc,queuecnt,0)) {
2954 succnt = 0;
2955 n = 0;
2956 for (i = 0; i < services; i++) {
2957 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2958 fill_printdest_info(conn,i,uLevel,&desc);
2959 n++;
2960 if (desc.errcode == NERR_Success) succnt = n;
2965 *rdata_len = desc.usedlen;
2967 *rparam_len = 8;
2968 *rparam = REALLOC(*rparam,*rparam_len);
2969 SSVALS(*rparam,0,desc.errcode);
2970 SSVAL(*rparam,2,0);
2971 SSVAL(*rparam,4,succnt);
2972 SSVAL(*rparam,6,queuecnt);
2974 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2975 return(True);
2978 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2979 int mdrcnt,int mprcnt,
2980 char **rdata,char **rparam,
2981 int *rdata_len,int *rparam_len)
2983 char *str1 = param+2;
2984 char *str2 = skip_string(str1,1);
2985 char *p = skip_string(str2,1);
2986 int uLevel;
2987 int succnt;
2988 struct pack_desc desc;
2990 bzero(&desc,sizeof(desc));
2992 uLevel = SVAL(p,0);
2994 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2996 /* check it's a supported varient */
2997 if (strcmp(str1,"WrLeh") != 0) return False;
2998 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3000 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3001 desc.base = *rdata;
3002 desc.buflen = mdrcnt;
3003 if (init_package(&desc,1,0)) {
3004 PACKS(&desc,"B41","NULL");
3007 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3009 *rdata_len = desc.usedlen;
3011 *rparam_len = 8;
3012 *rparam = REALLOC(*rparam,*rparam_len);
3013 SSVALS(*rparam,0,desc.errcode);
3014 SSVAL(*rparam,2,0);
3015 SSVAL(*rparam,4,succnt);
3016 SSVAL(*rparam,6,1);
3018 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3019 return(True);
3022 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3023 int mdrcnt,int mprcnt,
3024 char **rdata,char **rparam,
3025 int *rdata_len,int *rparam_len)
3027 char *str1 = param+2;
3028 char *str2 = skip_string(str1,1);
3029 char *p = skip_string(str2,1);
3030 int uLevel;
3031 int succnt;
3032 struct pack_desc desc;
3034 bzero(&desc,sizeof(desc));
3036 uLevel = SVAL(p,0);
3038 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3040 /* check it's a supported varient */
3041 if (strcmp(str1,"WrLeh") != 0) return False;
3042 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3044 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3045 desc.base = *rdata;
3046 desc.buflen = mdrcnt;
3047 desc.format = str2;
3048 if (init_package(&desc,1,0)) {
3049 PACKS(&desc,"B13","lpd");
3052 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3054 *rdata_len = desc.usedlen;
3056 *rparam_len = 8;
3057 *rparam = REALLOC(*rparam,*rparam_len);
3058 SSVALS(*rparam,0,desc.errcode);
3059 SSVAL(*rparam,2,0);
3060 SSVAL(*rparam,4,succnt);
3061 SSVAL(*rparam,6,1);
3063 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3064 return(True);
3067 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3068 int mdrcnt,int mprcnt,
3069 char **rdata,char **rparam,
3070 int *rdata_len,int *rparam_len)
3072 char *str1 = param+2;
3073 char *str2 = skip_string(str1,1);
3074 char *p = skip_string(str2,1);
3075 int uLevel;
3076 int succnt;
3077 struct pack_desc desc;
3079 bzero(&desc,sizeof(desc));
3081 uLevel = SVAL(p,0);
3083 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3085 /* check it's a supported varient */
3086 if (strcmp(str1,"WrLeh") != 0) return False;
3087 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3089 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3090 bzero(&desc,sizeof(desc));
3091 desc.base = *rdata;
3092 desc.buflen = mdrcnt;
3093 desc.format = str2;
3094 if (init_package(&desc,1,0)) {
3095 PACKS(&desc,"B13","lp0");
3098 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3100 *rdata_len = desc.usedlen;
3102 *rparam_len = 8;
3103 *rparam = REALLOC(*rparam,*rparam_len);
3104 SSVALS(*rparam,0,desc.errcode);
3105 SSVAL(*rparam,2,0);
3106 SSVAL(*rparam,4,succnt);
3107 SSVAL(*rparam,6,1);
3109 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3110 return(True);
3113 static void api_rpc_trans_reply(char *outbuf,
3114 pipes_struct *p,
3115 prs_struct *pd)
3117 send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
3119 if (mem_buf_len(p->rhdr.data) <= p->file_offset)
3121 /* all of data was sent: no need to wait for SMBreadX calls */
3122 mem_free_data(p->rhdr .data);
3123 mem_free_data(p->rdata.data);
3124 mem_free_data(p->rdata_i.data);
3128 /****************************************************************************
3129 WaitNamedPipeHandleState
3130 ****************************************************************************/
3131 static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param)
3133 uint16 priority;
3135 if (!param) return False;
3137 priority = param[0] + (param[1] << 8);
3138 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
3140 if (wait_rpc_pipe_hnd_state(p, priority))
3142 /* now send the reply */
3143 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3145 return True;
3147 return False;
3151 /****************************************************************************
3152 SetNamedPipeHandleState
3153 ****************************************************************************/
3154 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
3156 uint16 id;
3158 if (!param) return False;
3160 id = param[0] + (param[1] << 8);
3161 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
3163 if (set_rpc_pipe_hnd_state(p, id))
3165 /* now send the reply */
3166 send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
3168 return True;
3170 return False;
3174 /****************************************************************************
3175 when no reply is generated, indicate unsupported.
3176 ****************************************************************************/
3177 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3179 struct mem_buf rparam;
3181 mem_init(&rparam, 0);
3182 mem_alloc_data(&rparam, 4);
3184 rparam.offset.start = 0;
3185 rparam.offset.end = 4;
3187 /* unsupported */
3188 SSVAL(rparam.data,0,NERR_notsupported);
3189 SSVAL(rparam.data,2,0); /* converter word */
3191 DEBUG(3,("Unsupported API fd command\n"));
3193 /* now send the reply */
3194 send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
3196 mem_free_data(&rparam);
3198 return(-1);
3201 /****************************************************************************
3202 handle remote api calls delivered to a named pipe already opened.
3203 ****************************************************************************/
3204 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
3205 uint16 *setup,char *data,char *params,
3206 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3208 BOOL reply = False;
3210 int pnum;
3211 int subcommand;
3212 pipes_struct *p = NULL;
3213 prs_struct pd;
3215 DEBUG(5,("api_fd_reply\n"));
3217 /* make a static data parsing structure from the api_fd_reply data */
3218 prs_init(&pd, 0, 4, 0, True);
3219 mem_create(pd.data, data, 0, tdscnt, 0, False);
3221 /* First find out the name of this file. */
3222 if (suwcnt != 2)
3224 DEBUG(0,("Unexpected named pipe transaction.\n"));
3225 return(-1);
3228 /* Get the file handle and hence the file name. */
3229 pnum = setup[1];
3230 subcommand = setup[0];
3231 p = get_rpc_pipe(pnum);
3233 if (p != NULL)
3235 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
3236 subcommand, p->name, pnum));
3238 /* record maximum data length that can be transmitted in an SMBtrans */
3239 p->file_offset = mdrcnt;
3241 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
3242 p, p->file_offset));
3244 switch (subcommand)
3246 case 0x26:
3248 /* dce/rpc command */
3249 reply = rpc_command(p, &pd);
3250 if (reply)
3252 api_rpc_trans_reply(outbuf, p, &pd);
3254 break;
3256 case 0x53:
3258 /* Wait Named Pipe Handle state */
3259 reply = api_WNPHS(outbuf, p, params);
3260 break;
3262 case 0x01:
3264 /* Set Named Pipe Handle state */
3265 reply = api_SNPHS(outbuf, p, params);
3266 break;
3270 else
3272 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3275 mem_free_data(pd.data);
3277 if (!reply)
3279 return api_no_reply(outbuf, mdrcnt);
3281 return -1;
3284 /****************************************************************************
3285 the buffer was too small
3286 ****************************************************************************/
3287 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3288 int mdrcnt,int mprcnt,
3289 char **rdata,char **rparam,
3290 int *rdata_len,int *rparam_len)
3292 *rparam_len = MIN(*rparam_len,mprcnt);
3293 *rparam = REALLOC(*rparam,*rparam_len);
3295 *rdata_len = 0;
3297 SSVAL(*rparam,0,NERR_BufTooSmall);
3299 DEBUG(3,("Supplied buffer too small in API command\n"));
3301 return(True);
3305 /****************************************************************************
3306 the request is not supported
3307 ****************************************************************************/
3308 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3309 int mdrcnt,int mprcnt,
3310 char **rdata,char **rparam,
3311 int *rdata_len,int *rparam_len)
3313 *rparam_len = 4;
3314 *rparam = REALLOC(*rparam,*rparam_len);
3316 *rdata_len = 0;
3318 SSVAL(*rparam,0,NERR_notsupported);
3319 SSVAL(*rparam,2,0); /* converter word */
3321 DEBUG(3,("Unsupported API command\n"));
3323 return(True);
3329 struct
3331 char *name;
3332 int id;
3333 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3334 int,int,char **,char **,int *,int *);
3335 int flags;
3336 } api_commands[] = {
3337 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3338 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3339 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3340 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3341 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3342 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3343 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3344 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3345 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3346 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3347 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3348 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3349 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3350 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3351 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3352 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3353 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3354 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3355 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3356 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3357 {"NetServerEnum", 104, api_RNetServerEnum,0},
3358 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3359 {"SetUserPassword", 115, api_SetUserPassword,0},
3360 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3361 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3362 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3363 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3364 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3365 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3366 {NULL, -1, api_Unsupported,0}};
3369 /****************************************************************************
3370 handle remote api calls
3371 ****************************************************************************/
3372 static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3373 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3375 int api_command;
3376 struct mem_buf rdata_buf;
3377 struct mem_buf rparam_buf;
3378 char *rdata = NULL;
3379 char *rparam = NULL;
3380 int rdata_len = 0;
3381 int rparam_len = 0;
3382 BOOL reply=False;
3383 int i;
3385 SMB_ASSERT(params != 0);
3387 api_command = SVAL(params,0);
3389 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3390 api_command,
3391 params+2,
3392 skip_string(params+2,1),
3393 tdscnt,tpscnt,mdrcnt,mprcnt));
3395 for (i=0;api_commands[i].name;i++)
3396 if (api_commands[i].id == api_command && api_commands[i].fn)
3398 DEBUG(3,("Doing %s\n",api_commands[i].name));
3399 break;
3402 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3403 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3405 if(!rdata || !rparam) {
3406 DEBUG(0,("api_reply: malloc fail !\n"));
3407 return -1;
3410 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3411 &rdata,&rparam,&rdata_len,&rparam_len);
3414 if (rdata_len > mdrcnt ||
3415 rparam_len > mprcnt)
3417 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3418 &rdata,&rparam,&rdata_len,&rparam_len);
3422 /* if we get False back then it's actually unsupported */
3423 if (!reply)
3424 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3425 &rdata,&rparam,&rdata_len,&rparam_len);
3428 mem_create(&rdata_buf , rdata , 0, rdata_len , 0, False);
3429 mem_create(&rparam_buf, rparam, 0, rparam_len, 0, False);
3431 /* now send the reply */
3432 send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
3434 if (rdata ) free(rdata);
3435 if (rparam) free(rparam);
3437 return(-1);
3440 /****************************************************************************
3441 handle named pipe commands
3442 ****************************************************************************/
3443 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
3444 uint16 *setup,char *data,char *params,
3445 int suwcnt,int tdscnt,int tpscnt,
3446 int msrcnt,int mdrcnt,int mprcnt)
3448 DEBUG(3,("named pipe command on <%s> name\n", name));
3450 if (strequal(name,"LANMAN"))
3452 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3455 if (strequal(name,"WKSSVC") ||
3456 strequal(name,"SRVSVC") ||
3457 strequal(name,"WINREG") ||
3458 strequal(name,"SAMR") ||
3459 strequal(name,"LSARPC"))
3461 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
3462 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3465 if (strlen(name) < 1)
3467 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3470 if (setup)
3472 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3475 return 0;
3479 /****************************************************************************
3480 reply to a SMBtrans
3481 ****************************************************************************/
3482 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
3484 fstring name;
3485 int name_offset = 0;
3486 char *data=NULL,*params=NULL;
3487 uint16 *setup=NULL;
3488 int outsize = 0;
3489 uint16 vuid = SVAL(inbuf,smb_uid);
3490 int tpscnt = SVAL(inbuf,smb_vwv0);
3491 int tdscnt = SVAL(inbuf,smb_vwv1);
3492 int mprcnt = SVAL(inbuf,smb_vwv2);
3493 int mdrcnt = SVAL(inbuf,smb_vwv3);
3494 int msrcnt = CVAL(inbuf,smb_vwv4);
3495 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3496 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3497 int pscnt = SVAL(inbuf,smb_vwv9);
3498 int psoff = SVAL(inbuf,smb_vwv10);
3499 int dscnt = SVAL(inbuf,smb_vwv11);
3500 int dsoff = SVAL(inbuf,smb_vwv12);
3501 int suwcnt = CVAL(inbuf,smb_vwv13);
3503 bzero(name, sizeof(name));
3504 fstrcpy(name,smb_buf(inbuf));
3506 if (dscnt > tdscnt || pscnt > tpscnt) {
3507 exit_server("invalid trans parameters\n");
3510 if (tdscnt) {
3511 if((data = (char *)malloc(tdscnt)) == NULL) {
3512 DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt));
3513 return(ERROR(ERRDOS,ERRnomem));
3515 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3518 if (tpscnt) {
3519 if((params = (char *)malloc(tpscnt)) == NULL) {
3520 DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt));
3521 return(ERROR(ERRDOS,ERRnomem));
3523 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3526 if (suwcnt) {
3527 int i;
3528 if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
3529 DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", suwcnt * sizeof(uint16)));
3530 return(ERROR(ERRDOS,ERRnomem));
3532 for (i=0;i<suwcnt;i++)
3533 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3537 if (pscnt < tpscnt || dscnt < tdscnt) {
3538 /* We need to send an interim response then receive the rest
3539 of the parameter/data bytes */
3540 outsize = set_message(outbuf,0,0,True);
3541 show_msg(outbuf);
3542 send_smb(Client,outbuf);
3545 /* receive the rest of the trans packet */
3546 while (pscnt < tpscnt || dscnt < tdscnt) {
3547 BOOL ret;
3548 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3550 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3552 if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) {
3553 if(ret) {
3554 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3555 } else {
3556 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3557 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3559 if (params) free(params);
3560 if (data) free(data);
3561 if (setup) free(setup);
3562 return(ERROR(ERRSRV,ERRerror));
3565 show_msg(inbuf);
3567 tpscnt = SVAL(inbuf,smb_vwv0);
3568 tdscnt = SVAL(inbuf,smb_vwv1);
3570 pcnt = SVAL(inbuf,smb_vwv2);
3571 poff = SVAL(inbuf,smb_vwv3);
3572 pdisp = SVAL(inbuf,smb_vwv4);
3574 dcnt = SVAL(inbuf,smb_vwv5);
3575 doff = SVAL(inbuf,smb_vwv6);
3576 ddisp = SVAL(inbuf,smb_vwv7);
3578 pscnt += pcnt;
3579 dscnt += dcnt;
3581 if (dscnt > tdscnt || pscnt > tpscnt) {
3582 exit_server("invalid trans parameters\n");
3585 if (pcnt)
3586 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3587 if (dcnt)
3588 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3592 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3593 name,tdscnt,tpscnt,suwcnt));
3596 * WinCE wierdness....
3599 if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine,
3600 strlen(local_machine)) == 0)) {
3601 name_offset = strlen(local_machine)+1;
3604 if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3605 DEBUG(5,("calling named_pipe\n"));
3606 outsize = named_pipe(conn,vuid,outbuf,
3607 name+name_offset+strlen("\\PIPE\\"),setup,data,params,
3608 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3609 } else {
3610 DEBUG(3,("invalid pipe name\n"));
3611 outsize = 0;
3615 if (data) free(data);
3616 if (params) free(params);
3617 if (setup) free(setup);
3619 if (close_on_completion)
3620 close_cnum(conn,vuid);
3622 if (one_way)
3623 return(-1);
3625 if (outsize == 0)
3626 return(ERROR(ERRSRV,ERRnosupport));
3628 return(outsize);