ipc.c: Changed reply_trans to use receive_next_smb() to cope
[nivanova/samba-autobuild/.git] / source / smbd / ipc.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Inter-process communication and named pipe handling
5    Copyright (C) Andrew Tridgell 1992-1997
6
7    SMB Version handling
8    Copyright (C) John H Terpstra 1995-1997
9    
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.
14    
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.
19    
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.
23    */
24 /*
25    This file handles the named pipe and mailslot calls
26    in the SMBtrans protocol
27    */
28
29 #include "includes.h"
30
31 #ifdef CHECK_TYPES
32 #undef CHECK_TYPES
33 #endif
34 #define CHECK_TYPES 0
35
36 extern int DEBUGLEVEL;
37 extern int max_send;
38 extern files_struct Files[];
39 extern connection_struct Connections[];
40
41 extern fstring local_machine;
42 extern fstring myworkgroup;
43
44 #define NERR_Success 0
45 #define NERR_badpass 86
46 #define NERR_notsupported 50
47
48 #define NERR_BASE (2100)
49 #define NERR_BufTooSmall (NERR_BASE+23)
50 #define NERR_JobNotFound (NERR_BASE+51)
51 #define NERR_DestNotFound (NERR_BASE+52)
52 #define ERROR_INVALID_LEVEL 124
53 #define ERROR_MORE_DATA 234
54
55 #define ACCESS_READ 0x01
56 #define ACCESS_WRITE 0x02
57 #define ACCESS_CREATE 0x04
58
59 #define SHPWLEN 8               /* share password length */
60 #define NNLEN 12                /* 8.3 net name length */
61 #define SNLEN 15                /* service name length */
62 #define QNLEN 12                /* queue name maximum length */
63
64 extern int Client;
65 extern int oplock_sock;
66 extern int smb_read_error;
67
68 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
69                             int mdrcnt,int mprcnt,
70                             char **rdata,char **rparam,
71                             int *rdata_len,int *rparam_len);
72 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
73                          int mdrcnt,int mprcnt,
74                          char **rdata,char **rparam,
75                          int *rdata_len,int *rparam_len);
76
77
78 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
79 {
80   pstring buf;
81   int l;
82
83   if (!src || !dst || !n || !(*dst)) return(0);
84
85   StrnCpy(buf,src,sizeof(buf)/2);
86   string_sub(buf,"%S",lp_servicename(snum));
87   standard_sub(cnum,buf);
88   StrnCpy(*dst,buf,*n);
89   l = strlen(*dst) + 1;
90   (*dst) += l;
91   (*n) -= l;
92   return l;
93 }
94
95 static int CopyAndAdvance(char** dst, char* src, int* n)
96 {
97   int l;
98   if (!src || !dst || !n || !(*dst)) return(0);
99   StrnCpy(*dst,src,*n);
100   l = strlen(*dst) + 1;
101   (*dst) += l;
102   (*n) -= l;
103   return l;
104 }
105
106 static int StrlenExpanded(int cnum, int snum, char* s)
107 {
108   pstring buf;
109   if (!s) return(0);
110   StrnCpy(buf,s,sizeof(buf)/2);
111   string_sub(buf,"%S",lp_servicename(snum));
112   standard_sub(cnum,buf);
113   return strlen(buf) + 1;
114 }
115
116 static char* Expand(int cnum, int snum, char* s)
117 {
118   static pstring buf;
119   if (!s) return(NULL);
120   StrnCpy(buf,s,sizeof(buf)/2);
121   string_sub(buf,"%S",lp_servicename(snum));
122   standard_sub(cnum,buf);
123   return &buf[0];
124 }
125
126 /*******************************************************************
127   check a API string for validity when we only need to check the prefix
128   ******************************************************************/
129 static BOOL prefix_ok(char *str,char *prefix)
130 {
131   return(strncmp(str,prefix,strlen(prefix)) == 0);
132 }
133
134
135 /****************************************************************************
136   send a trans reply
137   ****************************************************************************/
138 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
139                              int ldata,int lparam,int lsetup)
140 {
141   int i;
142   int this_ldata,this_lparam;
143   int tot_data=0,tot_param=0;
144   int align;
145
146   this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
147   this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
148
149 #ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
150   /* if you don't want Net Monitor to decode your packets, do this!!! */
151   align = ((this_lparam+1)%4);
152 #else
153   align = (this_lparam%4);
154 #endif
155
156   set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
157   if (this_lparam)
158     memcpy(smb_buf(outbuf),param,this_lparam);
159   if (this_ldata)
160     memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
161
162   SSVAL(outbuf,smb_vwv0,lparam);
163   SSVAL(outbuf,smb_vwv1,ldata);
164   SSVAL(outbuf,smb_vwv3,this_lparam);
165   SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
166   SSVAL(outbuf,smb_vwv5,0);
167   SSVAL(outbuf,smb_vwv6,this_ldata);
168   SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
169   SSVAL(outbuf,smb_vwv8,0);
170   SSVAL(outbuf,smb_vwv9,lsetup);
171   for (i=0;i<lsetup;i++)
172     SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
173
174   show_msg(outbuf);
175   send_smb(Client,outbuf);
176
177   tot_data = this_ldata;
178   tot_param = this_lparam;
179
180   while (tot_data < ldata || tot_param < lparam)
181     {
182       this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
183       this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
184
185       align = (this_lparam%4);
186
187       set_message(outbuf,10,this_ldata+this_lparam+align,False);
188       if (this_lparam)
189         memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
190       if (this_ldata)
191         memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
192
193       SSVAL(outbuf,smb_vwv3,this_lparam);
194       SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
195       SSVAL(outbuf,smb_vwv5,tot_param);
196       SSVAL(outbuf,smb_vwv6,this_ldata);
197       SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
198       SSVAL(outbuf,smb_vwv8,tot_data);
199       SSVAL(outbuf,smb_vwv9,0);
200
201       show_msg(outbuf);
202       send_smb(Client,outbuf);
203
204       tot_data += this_ldata;
205       tot_param += this_lparam;
206     }
207 }
208
209 struct pack_desc {
210   char* format;     /* formatstring for structure */
211   char* subformat;  /* subformat for structure */
212   char* base;       /* baseaddress of buffer */
213   int buflen;      /* remaining size for fixed part; on init: length of base */
214   int subcount;     /* count of substructures */
215   char* structbuf;  /* pointer into buffer for remaining fixed part */
216   int stringlen;    /* remaining size for variable part */              
217   char* stringbuf;  /* pointer into buffer for remaining variable part */
218   int neededlen;    /* total needed size */
219   int usedlen;      /* total used size (usedlen <= neededlen and usedlen <= buflen) */
220   char* curpos;     /* current position; pointer into format or subformat */
221   int errcode;
222 };
223
224 static int get_counter(char** p)
225 {
226   int i, n;
227   if (!p || !(*p)) return(1);
228   if (!isdigit(**p)) return 1;
229   for (n = 0;;) {
230     i = **p;
231     if (isdigit(i))
232       n = 10 * n + (i - '0');
233     else
234       return n;
235     (*p)++;
236   }
237 }
238
239 static int getlen(char* p)
240 {
241   int n = 0;
242   if (!p) return(0);
243   while (*p) {
244     switch( *p++ ) {
245     case 'W':                   /* word (2 byte) */
246       n += 2;
247       break;
248     case 'N':                   /* count of substructures (word) at end */
249       n += 2;
250       break;
251     case 'D':                   /* double word (4 byte) */
252     case 'z':                   /* offset to zero terminated string (4 byte) */
253     case 'l':                   /* offset to user data (4 byte) */
254       n += 4;
255       break;
256     case 'b':                   /* offset to data (with counter) (4 byte) */
257       n += 4;
258       get_counter(&p);
259       break;
260     case 'B':                   /* byte (with optional counter) */
261       n += get_counter(&p);
262       break;
263     }
264   }
265   return n;
266 }
267
268 static BOOL init_package(struct pack_desc* p, int count, int subcount)
269 {
270   int n = p->buflen;
271   int i;
272
273   if (!p->format || !p->base) return(False);
274
275   i = count * getlen(p->format);
276   if (p->subformat) i += subcount * getlen(p->subformat);
277   p->structbuf = p->base;
278   p->neededlen = 0;
279   p->usedlen = 0;
280   p->subcount = 0;
281   p->curpos = p->format;
282   if (i > n) {
283     i = n = 0;
284     p->errcode = NERR_BufTooSmall;
285   }
286
287   p->errcode = NERR_Success;
288   p->buflen = i;
289   n -= i;
290   p->stringbuf = p->base + i;
291   p->stringlen = n;
292   return(p->errcode == NERR_Success);
293 }
294
295 #ifdef __STDC__
296 static int package(struct pack_desc* p, ...)
297 {
298 #else
299 static int package(va_alist)
300 va_dcl
301 {
302   struct pack_desc* p;
303 #endif
304   va_list args;
305   int needed=0, stringneeded;
306   char* str=NULL;
307   int is_string=0, stringused;
308   int32 temp;
309
310 #ifdef __STDC__
311   va_start(args,p);
312 #else
313   va_start(args);
314   p = va_arg(args,struct pack_desc *);
315 #endif
316
317   if (!*p->curpos) {
318     if (!p->subcount)
319       p->curpos = p->format;
320     else {
321       p->curpos = p->subformat;
322       p->subcount--;
323     }
324   }
325 #if CHECK_TYPES
326   str = va_arg(args,char*);
327   if (strncmp(str,p->curpos,strlen(str)) != 0) {
328     DEBUG(2,("type error in package: %s instead of %*s\n",str,
329              strlen(str),p->curpos));
330     va_end(args);
331 #if AJT
332     ajt_panic();
333 #endif  
334     return 0;
335   }
336 #endif
337   stringneeded = -1;
338
339   if (!p->curpos) return(0);
340
341   switch( *p->curpos++ ) {
342   case 'W':                     /* word (2 byte) */
343     needed = 2;
344     temp = va_arg(args,int);
345     if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
346     break;
347   case 'N':                     /* count of substructures (word) at end */
348     needed = 2;
349     p->subcount = va_arg(args,int);
350     if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
351     break;
352   case 'D':                     /* double word (4 byte) */
353     needed = 4;
354     temp = va_arg(args,int);
355     if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
356     break;
357   case 'B':                     /* byte (with optional counter) */
358     needed = get_counter(&p->curpos);
359     {
360       char *s = va_arg(args,char*);
361       if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
362     }
363     break;
364   case 'z':                     /* offset to zero terminated string (4 byte) */
365     str = va_arg(args,char*);
366     stringneeded = (str ? strlen(str)+1 : 0);
367     is_string = 1;
368     break;
369   case 'l':                     /* offset to user data (4 byte) */
370     str = va_arg(args,char*);
371     stringneeded = va_arg(args,int);
372     is_string = 0;
373     break;
374   case 'b':                     /* offset to data (with counter) (4 byte) */
375     str = va_arg(args,char*);
376     stringneeded = get_counter(&p->curpos);
377     is_string = 0;
378     break;
379   }
380   va_end(args);
381   if (stringneeded >= 0) {
382     needed = 4;
383     if (p->buflen >= needed) {
384       stringused = stringneeded;
385       if (stringused > p->stringlen) {
386         stringused = (is_string ? p->stringlen : 0);
387         if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
388       }
389       if (!stringused)
390         SIVAL(p->structbuf,0,0);
391       else {
392         SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
393         memcpy(p->stringbuf,str?str:"",stringused);
394         if (is_string) p->stringbuf[stringused-1] = '\0';
395         p->stringbuf += stringused;
396         p->stringlen -= stringused;
397         p->usedlen += stringused;
398       }
399     }
400     p->neededlen += stringneeded;
401   }
402   p->neededlen += needed;
403   if (p->buflen >= needed) {
404     p->structbuf += needed;
405     p->buflen -= needed;
406     p->usedlen += needed;
407   }
408   else {
409     if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
410   }
411   return 1;
412 }
413
414 #if CHECK_TYPES
415 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
416 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
417 #else
418 #define PACK(desc,t,v) package(desc,v)
419 #define PACKl(desc,t,v,l) package(desc,v,l)
420 #endif
421
422 static void PACKI(struct pack_desc* desc,char *t,int v)
423 {
424   PACK(desc,t,v);
425 }
426
427 static void PACKS(struct pack_desc* desc,char *t,char *v)
428 {
429   PACK(desc,t,v);
430 }
431
432
433 /****************************************************************************
434   get a print queue
435   ****************************************************************************/
436
437 static void PackDriverData(struct pack_desc* desc)
438 {
439   char drivdata[4+4+32];
440   SIVAL(drivdata,0,sizeof drivdata); /* cb */
441   SIVAL(drivdata,4,1000);       /* lVersion */
442   memset(drivdata+8,0,32);      /* szDeviceName */
443   strcpy(drivdata+8,"NULL");
444   PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
445 }
446
447 static int check_printq_info(struct pack_desc* desc,
448                              int uLevel, char *id1, char *id2)
449 {
450   desc->subformat = NULL;
451   switch( uLevel ) {
452   case 0:
453     desc->format = "B13";
454     break;
455   case 1:
456     desc->format = "B13BWWWzzzzzWW";
457     break;
458   case 2:
459     desc->format = "B13BWWWzzzzzWN";
460     desc->subformat = "WB21BB16B10zWWzDDz";
461     break;
462   case 3:
463     desc->format = "zWWWWzzzzWWzzl";
464     break;
465   case 4:
466     desc->format = "zWWWWzzzzWNzzl";
467     desc->subformat = "WWzWWDDzz";
468     break;
469   case 5:
470     desc->format = "z";
471     break;
472   case 52:
473     desc->format = "WzzzzzzzzN";
474     desc->subformat = "z";
475     break;
476   default: return False;
477   }
478   if (strcmp(desc->format,id1) != 0) return False;
479   if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
480   return True;
481 }
482
483 static void fill_printjob_info(int cnum, int snum, int uLevel,
484                                struct pack_desc* desc,
485                                print_queue_struct* queue, int n)
486 {
487   time_t t = queue->time;
488
489   /* the client expects localtime */
490   t -= TimeDiff(t);
491
492   PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
493   if (uLevel == 1) {
494     PACKS(desc,"B21",queue->user); /* szUserName */
495     PACKS(desc,"B","");         /* pad */
496     PACKS(desc,"B16","");       /* szNotifyName */
497     PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
498     PACKS(desc,"z","");         /* pszParms */
499     PACKI(desc,"W",n+1);                /* uPosition */
500     PACKI(desc,"W",queue->status); /* fsStatus */
501     PACKS(desc,"z","");         /* pszStatus */
502     PACKI(desc,"D",t); /* ulSubmitted */
503     PACKI(desc,"D",queue->size); /* ulSize */
504     PACKS(desc,"z",queue->file); /* pszComment */
505   }
506   if (uLevel == 2 || uLevel == 3) {
507     PACKI(desc,"W",queue->priority);            /* uPriority */
508     PACKS(desc,"z",queue->user); /* pszUserName */
509     PACKI(desc,"W",n+1);                /* uPosition */
510     PACKI(desc,"W",queue->status); /* fsStatus */
511     PACKI(desc,"D",t); /* ulSubmitted */
512     PACKI(desc,"D",queue->size); /* ulSize */
513     PACKS(desc,"z","Samba");    /* pszComment */
514     PACKS(desc,"z",queue->file); /* pszDocument */
515     if (uLevel == 3) {
516       PACKS(desc,"z","");       /* pszNotifyName */
517       PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
518       PACKS(desc,"z","");       /* pszParms */
519       PACKS(desc,"z","");       /* pszStatus */
520       PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
521       PACKS(desc,"z","lpd");    /* pszQProcName */
522       PACKS(desc,"z","");       /* pszQProcParms */
523       PACKS(desc,"z","NULL"); /* pszDriverName */
524       PackDriverData(desc);     /* pDriverData */
525       PACKS(desc,"z","");       /* pszPrinterName */
526     }
527   }
528 }
529
530 static void fill_printq_info(int cnum, int snum, int uLevel,
531                              struct pack_desc* desc,
532                              int count, print_queue_struct* queue,
533                              print_status_struct* status)
534 {
535   switch (uLevel) {
536     case 1:
537     case 2:
538       PACKS(desc,"B13",SERVICE(snum));
539       break;
540     case 3:
541     case 4:
542     case 5:
543       PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
544       break;
545   }
546
547   if (uLevel == 1 || uLevel == 2) {
548     PACKS(desc,"B","");         /* alignment */
549     PACKI(desc,"W",5);          /* priority */
550     PACKI(desc,"W",0);          /* start time */
551     PACKI(desc,"W",0);          /* until time */
552     PACKS(desc,"z","");         /* pSepFile */
553     PACKS(desc,"z","lpd");      /* pPrProc */
554     PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
555     PACKS(desc,"z","");         /* pParms */
556     if (snum < 0) {
557       PACKS(desc,"z","UNKNOWN PRINTER");
558       PACKI(desc,"W",LPSTAT_ERROR);
559     }
560     else if (!status || !status->message[0]) {
561       PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
562       PACKI(desc,"W",LPSTAT_OK); /* status */
563     } else {
564       PACKS(desc,"z",status->message);
565       PACKI(desc,"W",status->status); /* status */
566     }
567     PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
568   }
569   if (uLevel == 3 || uLevel == 4) {
570     PACKI(desc,"W",5);          /* uPriority */
571     PACKI(desc,"W",0);          /* uStarttime */
572     PACKI(desc,"W",0);          /* uUntiltime */
573     PACKI(desc,"W",5);          /* pad1 */
574     PACKS(desc,"z","");         /* pszSepFile */
575     PACKS(desc,"z","WinPrint"); /* pszPrProc */
576     PACKS(desc,"z","");         /* pszParms */
577     if (!status || !status->message[0]) {
578       PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
579       PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
580     } else {
581       PACKS(desc,"z",status->message); /* pszComment */
582       PACKI(desc,"W",status->status); /* fsStatus */
583     }
584     PACKI(desc,(uLevel == 3 ? "W" : "N"),count);        /* cJobs */
585     PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
586     PACKS(desc,"z",lp_printerdriver(snum));             /* pszDriverName */
587     PackDriverData(desc);       /* pDriverData */
588   }
589   if (uLevel == 2 || uLevel == 4) {
590     int i;
591     for (i=0;i<count;i++)
592       fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
593   }
594
595   if (uLevel==52) {
596     int i,ok=0;
597     pstring tok,driver,short_name;
598     char *p,*q;
599     FILE *f;
600     pstring fname;
601
602     strcpy(fname,lp_driverfile());
603
604     f=fopen(fname,"r");
605     if (!f) {
606       DEBUG(0,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
607     }
608
609     p=(char *)malloc(8192*sizeof(char));
610     bzero(p, 8192*sizeof(char));
611     q=p;
612
613     /* lookup the long printer driver name in the file description */
614     while (f && !feof(f) && !ok)
615     {
616       fgets(p,8191,f);
617       p[strlen(p)-1]='\0';
618       next_token(&p,tok,":");
619       if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
620     }
621
622     fclose(f);
623
624     next_token(&p,short_name,":");
625     next_token(&p,driver,":");
626
627     PACKI(desc,"W",0x0400);                      /* don't know */
628     PACKS(desc,"z",lp_printerdriver(snum));        /* long printer name */
629
630     if (ok)
631     {
632       PACKS(desc,"z",driver);                    /* Driver Name */
633       PACKS(desc,"z",short_name);                /* short printer name */
634       DEBUG(3,("Driver:%s:\n",driver));
635       DEBUG(3,("short name:%s:\n",short_name));
636     }
637     else 
638     {
639       PACKS(desc,"z","");
640       PACKS(desc,"z","");
641     }
642
643     PACKS(desc,"z","");
644     PACKS(desc,"z",lp_driverlocation(snum));       /* share to retrieve files */
645     PACKS(desc,"z","EMF");
646     PACKS(desc,"z","");
647     if (ok)
648       PACKS(desc,"z",driver);                      /* driver name */
649     else
650       PACKS(desc,"z","");
651     PACKI(desc,"N",count);                         /* number of files to copy */
652     for (i=0;i<count;i++)
653     {
654       next_token(&p,tok,",");
655       PACKS(desc,"z",tok);                        /* driver files to copy */
656       DEBUG(3,("file:%s:\n",tok));
657     }
658     free(q);
659   }
660
661   DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
662 }
663
664 /* This function returns the number of file for a given driver */
665 int get_printerdrivernumber(int snum)
666 {
667   int i=0,ok=0;
668   pstring tok;
669   char *p,*q;
670   FILE *f;
671   pstring fname;
672
673   strcpy(fname,lp_driverfile());
674
675   DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
676   f=fopen(fname,"r");
677   if (!f) {
678     DEBUG(0,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
679     return(0);
680   }
681
682   p=(char *)malloc(8192*sizeof(char));
683   q=p; /* need it to free memory because p change ! */
684
685   /* lookup the long printer driver name in the file description */
686   while (!feof(f) && !ok)
687   {
688     fgets(p,8191,f);
689     next_token(&p,tok,":");
690     if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
691   }
692
693   if (ok) {
694     /* skip 2 fields */
695     next_token(&p,tok,":");  /* short name */
696     next_token(&p,tok,":");  /* driver name */
697     /* count the number of files */
698     while (next_token(&p,tok,","))
699        i++;
700   }
701   fclose(f);
702   free(q);
703
704   return(i);
705 }
706
707 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
708                                  int mdrcnt,int mprcnt,
709                                  char **rdata,char **rparam,
710                                  int *rdata_len,int *rparam_len)
711 {
712   char *str1 = param+2;
713   char *str2 = skip_string(str1,1);
714   char *p = skip_string(str2,1);
715   char *QueueName = p;
716   int uLevel,cbBuf;
717   int count=0;
718   int snum;
719   char* str3;
720   struct pack_desc desc;
721   print_queue_struct *queue=NULL;
722   print_status_struct status;
723   
724   bzero(&status,sizeof(status));
725   bzero(&desc,sizeof(desc));
726  
727   p = skip_string(p,1);
728   uLevel = SVAL(p,0);
729   cbBuf = SVAL(p,2);
730   str3 = p + 4;
731  
732   /* remove any trailing username */
733   if ((p = strchr(QueueName,'%'))) *p = 0;
734  
735   DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
736  
737   /* check it's a supported varient */
738   if (!prefix_ok(str1,"zWrLh")) return False;
739   if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
740  
741   snum = lp_servicenumber(QueueName);
742   if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
743     int pnum = lp_servicenumber(PRINTERS_NAME);
744     if (pnum >= 0) {
745       lp_add_printer(QueueName,pnum);
746       snum = lp_servicenumber(QueueName);
747     }
748   }
749   
750   if (snum < 0 || !VALID_SNUM(snum)) return(False);
751
752   if (uLevel==52)
753   {
754     count = get_printerdrivernumber(snum);
755     DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
756   }
757   else
758     count = get_printqueue(snum,cnum,&queue,&status);
759
760   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
761   desc.base = *rdata;
762   desc.buflen = mdrcnt;
763   if (init_package(&desc,1,count)) {
764     desc.subcount = count;
765     fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
766   }
767
768   *rdata_len = desc.usedlen;
769   
770   *rparam_len = 6;
771   *rparam = REALLOC(*rparam,*rparam_len);
772   SSVALS(*rparam,0,desc.errcode);
773   SSVAL(*rparam,2,0);
774   SSVAL(*rparam,4,desc.neededlen);
775   
776   DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
777
778   if (queue) free(queue);
779   
780   return(True);
781 }
782
783
784 /****************************************************************************
785   view list of all print jobs on all queues
786   ****************************************************************************/
787 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
788                               int mdrcnt, int mprcnt,
789                               char **rdata, char** rparam,
790                               int *rdata_len, int *rparam_len)
791 {
792   char *param_format = param+2;
793   char *output_format1 = skip_string(param_format,1);
794   char *p = skip_string(output_format1,1);
795   int uLevel = SVAL(p,0);
796   char *output_format2 = p + 4;
797   int services = lp_numservices();
798   int i, n;
799   struct pack_desc desc;
800   print_queue_struct **queue = NULL;
801   print_status_struct *status = NULL;
802   int* subcntarr = NULL;
803   int queuecnt, subcnt=0, succnt=0;
804  
805   bzero(&desc,sizeof(desc));
806
807   DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
808  
809   if (!prefix_ok(param_format,"WrLeh")) return False;
810   if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
811     return False;
812   queuecnt = 0;
813   for (i = 0; i < services; i++)
814     if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
815       queuecnt++;
816   if (uLevel > 0) {
817     queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
818     memset(queue,0,queuecnt*sizeof(print_queue_struct*));
819     status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
820     memset(status,0,queuecnt*sizeof(print_status_struct));
821     subcntarr = (int*)malloc(queuecnt*sizeof(int));
822     subcnt = 0;
823     n = 0;
824     for (i = 0; i < services; i++)
825       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
826         subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
827         subcnt += subcntarr[n];
828         n++;
829       }
830   }
831   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
832   desc.base = *rdata;
833   desc.buflen = mdrcnt;
834
835   if (init_package(&desc,queuecnt,subcnt)) {
836     n = 0;
837     succnt = 0;
838     for (i = 0; i < services; i++)
839       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
840         fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
841         n++;
842         if (desc.errcode == NERR_Success) succnt = n;
843       }
844   }
845
846   if (subcntarr) free(subcntarr);
847  
848   *rdata_len = desc.usedlen;
849   *rparam_len = 8;
850   *rparam = REALLOC(*rparam,*rparam_len);
851   SSVALS(*rparam,0,desc.errcode);
852   SSVAL(*rparam,2,0);
853   SSVAL(*rparam,4,succnt);
854   SSVAL(*rparam,6,queuecnt);
855   
856   for (i = 0; i < queuecnt; i++) {
857     if (queue && queue[i]) free(queue[i]);
858   }
859
860   if (queue) free(queue);
861   if (status) free(status);
862   
863   return True;
864 }
865
866 /****************************************************************************
867   get info level for a server list query
868   ****************************************************************************/
869 static BOOL check_server_info(int uLevel, char* id)
870 {
871   switch( uLevel ) {
872   case 0:
873     if (strcmp(id,"B16") != 0) return False;
874     break;
875   case 1:
876     if (strcmp(id,"B16BBDz") != 0) return False;
877     break;
878   default: 
879     return False;
880   }
881   return True;
882 }
883
884 struct srv_info_struct
885 {
886   fstring name;
887   uint32 type;
888   fstring comment;
889   fstring domain;
890   BOOL server_added;
891 };
892
893
894 /*******************************************************************
895   get server info lists from the files saved by nmbd. Return the
896   number of entries
897   ******************************************************************/
898 static int get_server_info(uint32 servertype, 
899                            struct srv_info_struct **servers,
900                            char *domain)
901 {
902   FILE *f;
903   pstring fname;
904   int count=0;
905   int alloced=0;
906   pstring line;
907   BOOL local_list_only;
908
909   pstrcpy(fname,lp_lockdir());
910   trim_string(fname,NULL,"/");
911   strcat(fname,"/");
912   strcat(fname,SERVER_LIST);
913
914   f = fopen(fname,"r");
915
916   if (!f) {
917     DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
918     return(0);
919   }
920
921   /* request for everything is code for request all servers */
922   if (servertype == SV_TYPE_ALL) 
923         servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
924
925   local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
926
927   DEBUG(4,("Servertype search: %8x\n",servertype));
928
929   while (!feof(f))
930   {
931     fstring stype;
932     struct srv_info_struct *s;
933     char *ptr = line;
934     BOOL ok = True;
935     *ptr = 0;
936
937     fgets(line,sizeof(line)-1,f);
938     if (!*line) continue;
939     
940     if (count == alloced) {
941       alloced += 10;
942       (*servers) = (struct srv_info_struct *)
943         Realloc(*servers,sizeof(**servers)*alloced);
944       if (!(*servers)) return(0);
945       bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
946     }
947     s = &(*servers)[count];
948     
949     if (!next_token(&ptr,s->name   , NULL)) continue;
950     if (!next_token(&ptr,stype     , NULL)) continue;
951     if (!next_token(&ptr,s->comment, NULL)) continue;
952     if (!next_token(&ptr,s->domain , NULL)) {
953       /* this allows us to cope with an old nmbd */
954       strcpy(s->domain,myworkgroup); 
955     }
956     
957     if (sscanf(stype,"%X",&s->type) != 1) { 
958       DEBUG(4,("r:host file ")); 
959       ok = False; 
960     }
961     
962         /* Filter the servers/domains we return based on what was asked for. */
963
964         /* Check to see if we are being asked for a local list only. */
965         if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
966           DEBUG(4,("r: local list only"));
967           ok = False;
968         }
969
970     /* doesn't match up: don't want it */
971     if (!(servertype & s->type)) { 
972       DEBUG(4,("r:serv type ")); 
973       ok = False; 
974     }
975     
976     if ((servertype & SV_TYPE_DOMAIN_ENUM) != 
977         (s->type & SV_TYPE_DOMAIN_ENUM))
978       {
979         DEBUG(4,("s: dom mismatch "));
980         ok = False;
981       }
982     
983     if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
984       {
985         ok = False;
986       }
987     
988         /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
989         s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
990
991     if (ok)
992       {
993         DEBUG(4,("**SV** %20s %8x %25s %15s\n",
994                  s->name, s->type, s->comment, s->domain));
995         
996         s->server_added = True;
997         count++;
998       }
999     else
1000       {
1001         DEBUG(4,("%20s %8x %25s %15s\n",
1002                  s->name, s->type, s->comment, s->domain));
1003       }
1004   }
1005   
1006   fclose(f);
1007   return(count);
1008 }
1009
1010
1011 /*******************************************************************
1012   fill in a server info structure
1013   ******************************************************************/
1014 static int fill_srv_info(struct srv_info_struct *service, 
1015                          int uLevel, char **buf, int *buflen, 
1016                          char **stringbuf, int *stringspace, char *baseaddr)
1017 {
1018   int struct_len;
1019   char* p;
1020   char* p2;
1021   int l2;
1022   int len;
1023  
1024   switch (uLevel) {
1025   case 0: struct_len = 16; break;
1026   case 1: struct_len = 26; break;
1027   default: return -1;
1028   }  
1029  
1030   if (!buf)
1031     {
1032       len = 0;
1033       switch (uLevel) 
1034         {
1035         case 1:
1036           len = strlen(service->comment)+1;
1037           break;
1038         }
1039
1040       if (buflen) *buflen = struct_len;
1041       if (stringspace) *stringspace = len;
1042       return struct_len + len;
1043     }
1044   
1045   len = struct_len;
1046   p = *buf;
1047   if (*buflen < struct_len) return -1;
1048   if (stringbuf)
1049     {
1050       p2 = *stringbuf;
1051       l2 = *stringspace;
1052     }
1053   else
1054     {
1055       p2 = p + struct_len;
1056       l2 = *buflen - struct_len;
1057     }
1058   if (!baseaddr) baseaddr = p;
1059   
1060   switch (uLevel)
1061     {
1062     case 0:
1063       StrnCpy(p,service->name,15);
1064       break;
1065
1066     case 1:
1067       StrnCpy(p,service->name,15);
1068       SIVAL(p,18,service->type);
1069       SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1070       len += CopyAndAdvance(&p2,service->comment,&l2);
1071       break;
1072     }
1073
1074   if (stringbuf)
1075     {
1076       *buf = p + struct_len;
1077       *buflen -= struct_len;
1078       *stringbuf = p2;
1079       *stringspace = l2;
1080     }
1081   else
1082     {
1083       *buf = p2;
1084       *buflen -= len;
1085     }
1086   return len;
1087 }
1088
1089
1090 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1091 {
1092   return(strcmp(s1->name,s2->name));
1093 }
1094
1095 /****************************************************************************
1096   view list of servers available (or possibly domains). The info is
1097   extracted from lists saved by nmbd on the local host
1098   ****************************************************************************/
1099 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
1100                                int mdrcnt, int mprcnt, char **rdata, 
1101                                char **rparam, int *rdata_len, int *rparam_len)
1102 {
1103   char *str1 = param+2;
1104   char *str2 = skip_string(str1,1);
1105   char *p = skip_string(str2,1);
1106   int uLevel = SVAL(p,0);
1107   int buf_len = SVAL(p,2);
1108   uint32 servertype = IVAL(p,4);
1109   char *p2;
1110   int data_len, fixed_len, string_len;
1111   int f_len, s_len;
1112   struct srv_info_struct *servers=NULL;
1113   int counted=0,total=0;
1114   int i,missed;
1115   fstring domain;
1116   BOOL domain_request;
1117   BOOL local_request;
1118
1119   /* If someone sets all the bits they don't really mean to set
1120      DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1121      known servers. */
1122
1123   if (servertype == SV_TYPE_ALL) 
1124     servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1125
1126   /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1127      any other bit (they may just set this bit on it's own) they 
1128      want all the locally seen servers. However this bit can be 
1129      set on its own so set the requested servers to be 
1130      ALL - DOMAIN_ENUM. */
1131
1132   if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) 
1133     servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1134
1135   domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1136   local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1137
1138   p += 8;
1139
1140   if (!prefix_ok(str1,"WrLehD")) return False;
1141   if (!check_server_info(uLevel,str2)) return False;
1142   
1143   DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1144   DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1145   DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1146
1147   if (strcmp(str1, "WrLehDz") == 0) {
1148     StrnCpy(domain, p, sizeof(fstring)-1);
1149   } else {
1150     StrnCpy(domain, myworkgroup, sizeof(fstring)-1);    
1151   }
1152
1153   if (lp_browse_list())
1154     total = get_server_info(servertype,&servers,domain);
1155
1156   data_len = fixed_len = string_len = 0;
1157   missed = 0;
1158
1159   qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1160
1161   {
1162     char *lastname=NULL;
1163
1164     for (i=0;i<total;i++)
1165     {
1166       struct srv_info_struct *s = &servers[i];
1167       if (lastname && strequal(lastname,s->name)) continue;
1168       lastname = s->name;
1169       data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1170       DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1171                s->name, s->type, s->comment, s->domain));
1172       
1173       if (data_len <= buf_len) {
1174           counted++;
1175           fixed_len += f_len;
1176           string_len += s_len;
1177       } else {
1178         missed++;
1179       }
1180     }
1181   }
1182
1183   *rdata_len = fixed_len + string_len;
1184   *rdata = REALLOC(*rdata,*rdata_len);
1185   bzero(*rdata,*rdata_len);
1186   
1187   p2 = (*rdata) + fixed_len;    /* auxilliary data (strings) will go here */
1188   p = *rdata;
1189   f_len = fixed_len;
1190   s_len = string_len;
1191
1192   {
1193     char *lastname=NULL;
1194     int count2 = counted;
1195     for (i = 0; i < total && count2;i++)
1196       {
1197         struct srv_info_struct *s = &servers[i];
1198         if (lastname && strequal(lastname,s->name)) continue;
1199         lastname = s->name;
1200         fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1201         DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1202                  s->name, s->type, s->comment, s->domain));
1203         count2--;
1204       }
1205   }
1206   
1207   *rparam_len = 8;
1208   *rparam = REALLOC(*rparam,*rparam_len);
1209   SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
1210   SSVAL(*rparam,2,0);
1211   SSVAL(*rparam,4,counted);
1212   SSVAL(*rparam,6,counted+missed);
1213
1214   if (servers) free(servers);
1215
1216   DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1217            domain,uLevel,counted,counted+missed));
1218
1219   return(True);
1220 }
1221
1222
1223 /****************************************************************************
1224   get info about a share
1225   ****************************************************************************/
1226 static BOOL check_share_info(int uLevel, char* id)
1227 {
1228   switch( uLevel ) {
1229   case 0:
1230     if (strcmp(id,"B13") != 0) return False;
1231     break;
1232   case 1:
1233     if (strcmp(id,"B13BWz") != 0) return False;
1234     break;
1235   case 2:
1236     if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1237     break;
1238   case 91:
1239     if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1240     break;
1241   default: return False;
1242   }
1243   return True;
1244 }
1245
1246 static int fill_share_info(int cnum, int snum, int uLevel,
1247                            char** buf, int* buflen,
1248                            char** stringbuf, int* stringspace, char* baseaddr)
1249 {
1250   int struct_len;
1251   char* p;
1252   char* p2;
1253   int l2;
1254   int len;
1255  
1256   switch( uLevel ) {
1257   case 0: struct_len = 13; break;
1258   case 1: struct_len = 20; break;
1259   case 2: struct_len = 40; break;
1260   case 91: struct_len = 68; break;
1261   default: return -1;
1262   }
1263   
1264  
1265   if (!buf)
1266     {
1267       len = 0;
1268       if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1269       if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1270       if (buflen) *buflen = struct_len;
1271       if (stringspace) *stringspace = len;
1272       return struct_len + len;
1273     }
1274   
1275   len = struct_len;
1276   p = *buf;
1277   if ((*buflen) < struct_len) return -1;
1278   if (stringbuf)
1279     {
1280       p2 = *stringbuf;
1281       l2 = *stringspace;
1282     }
1283   else
1284     {
1285       p2 = p + struct_len;
1286       l2 = (*buflen) - struct_len;
1287     }
1288   if (!baseaddr) baseaddr = p;
1289   
1290   StrnCpy(p,lp_servicename(snum),13);
1291   
1292   if (uLevel > 0)
1293     {
1294       int type;
1295       CVAL(p,13) = 0;
1296       type = STYPE_DISKTREE;
1297       if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1298       if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1299       SSVAL(p,14,type);         /* device type */
1300       SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1301       len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1302     }
1303   
1304   if (uLevel > 1)
1305     {
1306       SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1307       SSVALS(p,22,-1);          /* max uses */
1308       SSVAL(p,24,1); /* current uses */
1309       SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1310       len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1311       memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1312     }
1313   
1314   if (uLevel > 2)
1315     {
1316       memset(p+40,0,SHPWLEN+2);
1317       SSVAL(p,50,0);
1318       SIVAL(p,52,0);
1319       SSVAL(p,56,0);
1320       SSVAL(p,58,0);
1321       SIVAL(p,60,0);
1322       SSVAL(p,64,0);
1323       SSVAL(p,66,0);
1324     }
1325        
1326   if (stringbuf)
1327     {
1328       (*buf) = p + struct_len;
1329       (*buflen) -= struct_len;
1330       (*stringbuf) = p2;
1331       (*stringspace) = l2;
1332     }
1333   else
1334     {
1335       (*buf) = p2;
1336       (*buflen) -= len;
1337     }
1338   return len;
1339 }
1340
1341 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1342                                  int mdrcnt,int mprcnt,
1343                                  char **rdata,char **rparam,
1344                                  int *rdata_len,int *rparam_len)
1345 {
1346   char *str1 = param+2;
1347   char *str2 = skip_string(str1,1);
1348   char *netname = skip_string(str2,1);
1349   char *p = skip_string(netname,1);
1350   int uLevel = SVAL(p,0);
1351   int snum = find_service(netname);
1352   
1353   if (snum < 0) return False;
1354   
1355   /* check it's a supported varient */
1356   if (!prefix_ok(str1,"zWrLh")) return False;
1357   if (!check_share_info(uLevel,str2)) return False;
1358  
1359   *rdata = REALLOC(*rdata,mdrcnt);
1360   p = *rdata;
1361   *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1362   if (*rdata_len < 0) return False;
1363  
1364   *rparam_len = 6;
1365   *rparam = REALLOC(*rparam,*rparam_len);
1366   SSVAL(*rparam,0,NERR_Success);
1367   SSVAL(*rparam,2,0);           /* converter word */
1368   SSVAL(*rparam,4,*rdata_len);
1369  
1370   return(True);
1371 }
1372
1373 /****************************************************************************
1374   view list of shares available
1375   ****************************************************************************/
1376 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1377                               int mdrcnt,int mprcnt,
1378                               char **rdata,char **rparam,
1379                               int *rdata_len,int *rparam_len)
1380 {
1381   char *str1 = param+2;
1382   char *str2 = skip_string(str1,1);
1383   char *p = skip_string(str2,1);
1384   int uLevel = SVAL(p,0);
1385   int buf_len = SVAL(p,2);
1386   char *p2;
1387   int count=lp_numservices();
1388   int total=0,counted=0;
1389   int i;
1390   int data_len, fixed_len, string_len;
1391   int f_len, s_len;
1392  
1393   if (!prefix_ok(str1,"WrLeh")) return False;
1394   if (!check_share_info(uLevel,str2)) return False;
1395   
1396   data_len = fixed_len = string_len = 0;
1397   for (i=0;i<count;i++)
1398     if (lp_browseable(i) && lp_snum_ok(i))
1399       {
1400         total++;
1401         data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1402         if (data_len <= buf_len)
1403           {
1404             counted++;
1405             fixed_len += f_len;
1406             string_len += s_len;
1407           }
1408       }
1409   *rdata_len = fixed_len + string_len;
1410   *rdata = REALLOC(*rdata,*rdata_len);
1411   memset(*rdata,0,*rdata_len);
1412   
1413   p2 = (*rdata) + fixed_len;    /* auxillery data (strings) will go here */
1414   p = *rdata;
1415   f_len = fixed_len;
1416   s_len = string_len;
1417   for (i = 0; i < count;i++)
1418     if (lp_browseable(i) && lp_snum_ok(i))
1419       if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1420         break;
1421   
1422   *rparam_len = 8;
1423   *rparam = REALLOC(*rparam,*rparam_len);
1424   SSVAL(*rparam,0,NERR_Success);
1425   SSVAL(*rparam,2,0);
1426   SSVAL(*rparam,4,counted);
1427   SSVAL(*rparam,6,total);
1428   
1429   DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1430            counted,total,uLevel,
1431            buf_len,*rdata_len,mdrcnt));
1432   return(True);
1433 }
1434
1435
1436
1437 /****************************************************************************
1438   get the time of day info
1439   ****************************************************************************/
1440 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1441                              int mdrcnt,int mprcnt,
1442                              char **rdata,char **rparam,
1443                              int *rdata_len,int *rparam_len)
1444 {
1445   char *p;
1446   *rparam_len = 4;
1447   *rparam = REALLOC(*rparam,*rparam_len);
1448
1449   *rdata_len = 21;
1450   *rdata = REALLOC(*rdata,*rdata_len);
1451
1452   SSVAL(*rparam,0,NERR_Success);
1453   SSVAL(*rparam,2,0);           /* converter word */
1454
1455   p = *rdata;
1456
1457   {
1458     struct tm *t;
1459     time_t unixdate = time(NULL);
1460
1461     put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1462                                     by NT in a "net time" operation,
1463                                     it seems to ignore the one below */
1464
1465     /* the client expects to get localtime, not GMT, in this bit 
1466        (I think, this needs testing) */
1467     t = LocalTime(&unixdate);
1468
1469     SIVAL(p,4,0);               /* msecs ? */
1470     CVAL(p,8) = t->tm_hour;
1471     CVAL(p,9) = t->tm_min;
1472     CVAL(p,10) = t->tm_sec;
1473     CVAL(p,11) = 0;             /* hundredths of seconds */
1474     SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1475     SSVAL(p,14,10000);          /* timer interval in 0.0001 of sec */
1476     CVAL(p,16) = t->tm_mday;
1477     CVAL(p,17) = t->tm_mon + 1;
1478     SSVAL(p,18,1900+t->tm_year);
1479     CVAL(p,20) = t->tm_wday;
1480   }
1481
1482
1483   return(True);
1484 }
1485
1486 /****************************************************************************
1487   set the user password
1488   ****************************************************************************/
1489 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1490                                 int mdrcnt,int mprcnt,
1491                                 char **rdata,char **rparam,
1492                                 int *rdata_len,int *rparam_len)
1493 {
1494   char *p = skip_string(param+2,2);
1495   fstring user;
1496   fstring pass1,pass2;
1497
1498   fstrcpy(user,p);
1499
1500   p = skip_string(p,1);
1501
1502   StrnCpy(pass1,p,16);
1503   StrnCpy(pass2,p+16,16);
1504
1505   *rparam_len = 4;
1506   *rparam = REALLOC(*rparam,*rparam_len);
1507
1508   *rdata_len = 0;
1509
1510   SSVAL(*rparam,0,NERR_badpass);
1511   SSVAL(*rparam,2,0);           /* converter word */
1512
1513   DEBUG(3,("Set password for <%s>\n",user));
1514
1515   if (password_ok(user,pass1,strlen(pass1),NULL) &&
1516       chgpasswd(user,pass1,pass2))
1517   {
1518     SSVAL(*rparam,0,NERR_Success);
1519   }
1520
1521   bzero(pass1,sizeof(fstring));
1522   bzero(pass2,sizeof(fstring));  
1523          
1524   return(True);
1525 }
1526
1527 /****************************************************************************
1528   delete a print job
1529   Form: <W> <> 
1530   ****************************************************************************/
1531 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1532                                 int mdrcnt,int mprcnt,
1533                                 char **rdata,char **rparam,
1534                                 int *rdata_len,int *rparam_len)
1535 {
1536   int function = SVAL(param,0);
1537   char *str1 = param+2;
1538   char *str2 = skip_string(str1,1);
1539   char *p = skip_string(str2,1);
1540   int jobid, snum;
1541   int i, count;
1542
1543   printjob_decode(SVAL(p,0), &snum, &jobid);
1544
1545   /* check it's a supported varient */
1546   if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1547     return(False);
1548
1549   *rparam_len = 4;
1550   *rparam = REALLOC(*rparam,*rparam_len);
1551
1552   *rdata_len = 0;
1553
1554   SSVAL(*rparam,0,NERR_Success);
1555
1556   if (snum >= 0 && VALID_SNUM(snum))
1557     {
1558       print_queue_struct *queue=NULL;
1559       lpq_reset(snum);
1560       count = get_printqueue(snum,cnum,&queue,NULL);
1561   
1562       for (i=0;i<count;i++)
1563         if ((queue[i].job&0xFF) == jobid)
1564           {
1565             switch (function) {
1566             case 81:            /* delete */ 
1567               DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1568               del_printqueue(cnum,snum,queue[i].job);
1569               break;
1570             case 82:            /* pause */
1571             case 83:            /* resume */
1572               DEBUG(3,("%s queue entry %d\n",
1573                        (function==82?"pausing":"resuming"),queue[i].job));
1574               status_printjob(cnum,snum,queue[i].job,
1575                               (function==82?LPQ_PAUSED:LPQ_QUEUED));
1576               break;
1577             }
1578             break;
1579           }
1580   
1581       if (i==count)
1582         SSVAL(*rparam,0,NERR_JobNotFound);
1583
1584       if (queue) free(queue);
1585     }
1586
1587   SSVAL(*rparam,2,0);           /* converter word */
1588
1589   return(True);
1590 }
1591
1592 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1593                                  int mdrcnt,int mprcnt,
1594                                  char **rdata,char **rparam,
1595                                  int *rdata_len,int *rparam_len)
1596 {
1597   char *str1 = param+2;
1598   char *str2 = skip_string(str1,1);
1599   char *QueueName = skip_string(str2,1);
1600   int snum;
1601
1602   /* check it's a supported varient */
1603   if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1604     return(False);
1605
1606   *rparam_len = 4;
1607   *rparam = REALLOC(*rparam,*rparam_len);
1608
1609   *rdata_len = 0;
1610
1611   SSVAL(*rparam,0,NERR_Success);
1612   SSVAL(*rparam,2,0);           /* converter word */
1613
1614   snum = lp_servicenumber(QueueName);
1615   if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1616     int pnum = lp_servicenumber(PRINTERS_NAME);
1617     if (pnum >= 0) {
1618       lp_add_printer(QueueName,pnum);
1619       snum = lp_servicenumber(QueueName);
1620     }
1621   }
1622
1623   if (snum >= 0 && VALID_SNUM(snum)) {
1624     print_queue_struct *queue=NULL;
1625     int i, count;
1626     lpq_reset(snum);
1627     
1628     count = get_printqueue(snum,cnum,&queue,NULL);
1629     for (i = 0; i < count; i++)
1630       del_printqueue(cnum,snum,queue[i].job);
1631     
1632     if (queue) free(queue);
1633   }
1634
1635   DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1636
1637   return(True);
1638 }
1639
1640
1641 /****************************************************************************
1642   set the property of a print job (undocumented?)
1643   ? function = 0xb -> set name of print job
1644   ? function = 0x6 -> move print job up/down
1645   Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz> 
1646   or   <WWsTP> <WB21BB16B10zWWzDDz> 
1647 ****************************************************************************/
1648 static int check_printjob_info(struct pack_desc* desc,
1649                                int uLevel, char* id)
1650 {
1651   desc->subformat = NULL;
1652   switch( uLevel ) {
1653   case 0: desc->format = "W"; break;
1654   case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1655   case 2: desc->format = "WWzWWDDzz"; break;
1656   case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1657   default: return False;
1658   }
1659   if (strcmp(desc->format,id) != 0) return False;
1660   return True;
1661 }
1662
1663 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1664                              int mdrcnt,int mprcnt,
1665                              char **rdata,char **rparam,
1666                              int *rdata_len,int *rparam_len)
1667 {
1668   struct pack_desc desc;
1669   char *str1 = param+2;
1670   char *str2 = skip_string(str1,1);
1671   char *p = skip_string(str2,1);
1672   int jobid, snum;
1673   int uLevel = SVAL(p,2);
1674   int function = SVAL(p,4);     /* what is this ?? */
1675   int i;
1676   char *s = data;
1677
1678   printjob_decode(SVAL(p,0), &snum, &jobid);
1679    
1680   *rparam_len = 4;
1681   *rparam = REALLOC(*rparam,*rparam_len);
1682   
1683   *rdata_len = 0;
1684   
1685   /* check it's a supported varient */
1686   if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1687     return(False);
1688    
1689   switch (function) {
1690   case 0x6:     /* change job place in the queue, data gives the new place */
1691     if (snum >= 0 && VALID_SNUM(snum))
1692       {
1693         print_queue_struct *queue=NULL;
1694         int count;
1695   
1696         lpq_reset(snum);
1697         count = get_printqueue(snum,cnum,&queue,NULL);
1698         for (i=0;i<count;i++)   /* find job */
1699           if ((queue[i].job&0xFF) == jobid) break;
1700             
1701         if (i==count) {
1702           desc.errcode=NERR_JobNotFound;
1703           if (queue) free(queue);
1704         }
1705         else {
1706           desc.errcode=NERR_Success;
1707           i++;
1708 #if 0   
1709           {
1710             int place= SVAL(data,0);
1711             /* we currently have no way of doing this. Can any unix do it? */
1712             if (i < place)      /* move down */;
1713             else if (i > place )        /* move up */;
1714           }
1715 #endif
1716           desc.errcode=NERR_notsupported; /* not yet supported */
1717           if (queue) free(queue);
1718         }
1719       }
1720     else desc.errcode=NERR_JobNotFound;
1721     break;
1722   case 0xb:   /* change print job name, data gives the name */
1723     /* jobid, snum should be zero */
1724     if (isalpha(*s))
1725       {
1726         pstring name;
1727         int l = 0;
1728         while (l<64 && *s)
1729           {
1730             if (issafe(*s)) name[l++] = *s;
1731             s++;
1732           }      
1733         name[l] = 0;
1734         
1735         DEBUG(3,("Setting print name to %s\n",name));
1736         
1737         become_root(True);
1738
1739         for (i=0;i<MAX_OPEN_FILES;i++)
1740           if (Files[i].open && Files[i].print_file)
1741             {
1742               pstring wd;
1743           int fcnum = Files[i].cnum;
1744               GetWd(wd);
1745               unbecome_user();
1746               
1747               if (!become_user(&Connections[fcnum], fcnum,vuid) || 
1748                   !become_service(fcnum,True))
1749                 break;
1750               
1751               if (sys_rename(Files[i].name,name) == 0)
1752                 string_set(&Files[i].name,name);
1753               break;
1754             }
1755
1756          unbecome_root(True);
1757       }
1758     desc.errcode=NERR_Success;
1759   
1760     break;
1761   default:                      /* not implemented */
1762     return False;
1763   }
1764  
1765   SSVALS(*rparam,0,desc.errcode);
1766   SSVAL(*rparam,2,0);           /* converter word */
1767   
1768   return(True);
1769 }
1770
1771
1772 /****************************************************************************
1773   get info about the server
1774   ****************************************************************************/
1775 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1776                                   int mdrcnt,int mprcnt,
1777                                   char **rdata,char **rparam,
1778                                   int *rdata_len,int *rparam_len)
1779 {
1780   char *str1 = param+2;
1781   char *str2 = skip_string(str1,1);
1782   char *p = skip_string(str2,1);
1783   int uLevel = SVAL(p,0);
1784   char *p2;
1785   int struct_len;
1786
1787   DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1788
1789   /* check it's a supported varient */
1790   if (!prefix_ok(str1,"WrLh")) return False;
1791   switch( uLevel ) {
1792   case 0:
1793     if (strcmp(str2,"B16") != 0) return False;
1794     struct_len = 16;
1795     break;
1796   case 1:
1797     if (strcmp(str2,"B16BBDz") != 0) return False;
1798     struct_len = 26;
1799     break;
1800   case 2:
1801     if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1802         != 0) return False;
1803     struct_len = 134;
1804     break;
1805   case 3:
1806     if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1807         != 0) return False;
1808     struct_len = 144;
1809     break;
1810   case 20:
1811     if (strcmp(str2,"DN") != 0) return False;
1812     struct_len = 6;
1813     break;
1814   case 50:
1815     if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1816     struct_len = 42;
1817     break;
1818   default: return False;
1819   }
1820
1821   *rdata_len = mdrcnt;
1822   *rdata = REALLOC(*rdata,*rdata_len);
1823
1824   p = *rdata;
1825   p2 = p + struct_len;
1826   if (uLevel != 20) {
1827     StrnCpy(p,local_machine,16);
1828     strupper(p);
1829   }
1830   p += 16;
1831   if (uLevel > 0)
1832     {
1833       struct srv_info_struct *servers=NULL;
1834       int i,count;
1835       pstring comment;
1836       uint32 servertype= lp_default_server_announce();
1837
1838       pstrcpy(comment,lp_serverstring());
1839
1840       if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1841         for (i=0;i<count;i++)
1842           if (strequal(servers[i].name,local_machine))
1843       {
1844             servertype = servers[i].type;
1845             pstrcpy(comment,servers[i].comment);            
1846           }
1847       }
1848       if (servers) free(servers);
1849
1850       SCVAL(p,0,lp_major_announce_version());
1851       SCVAL(p,1,lp_minor_announce_version());
1852       SIVAL(p,2,servertype);
1853
1854       if (mdrcnt == struct_len) {
1855         SIVAL(p,6,0);
1856       } else {
1857         SIVAL(p,6,PTR_DIFF(p2,*rdata));
1858         standard_sub(cnum,comment);
1859         StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1860         p2 = skip_string(p2,1);
1861       }
1862     }
1863   if (uLevel > 1)
1864     {
1865       return False;             /* not yet implemented */
1866     }
1867
1868   *rdata_len = PTR_DIFF(p2,*rdata);
1869
1870   *rparam_len = 6;
1871   *rparam = REALLOC(*rparam,*rparam_len);
1872   SSVAL(*rparam,0,NERR_Success);
1873   SSVAL(*rparam,2,0);           /* converter word */
1874   SSVAL(*rparam,4,*rdata_len);
1875
1876   return(True);
1877 }
1878
1879
1880 /****************************************************************************
1881   get info about the server
1882   ****************************************************************************/
1883 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1884                                 int mdrcnt,int mprcnt,
1885                                 char **rdata,char **rparam,
1886                                 int *rdata_len,int *rparam_len)
1887 {
1888   char *str1 = param+2;
1889   char *str2 = skip_string(str1,1);
1890   char *p = skip_string(str2,1);
1891   char *p2;
1892   extern pstring sesssetup_user;
1893   int level = SVAL(p,0);
1894
1895   DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1896
1897   *rparam_len = 6;
1898   *rparam = REALLOC(*rparam,*rparam_len);
1899
1900   /* check it's a supported varient */
1901   if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1902     return(False);
1903
1904   *rdata_len = mdrcnt + 1024;
1905   *rdata = REALLOC(*rdata,*rdata_len);
1906
1907   SSVAL(*rparam,0,NERR_Success);
1908   SSVAL(*rparam,2,0);           /* converter word */
1909
1910   p = *rdata;
1911   p2 = p + 22;
1912
1913
1914   SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1915   strcpy(p2,local_machine);
1916   strupper(p2);
1917   p2 = skip_string(p2,1);
1918   p += 4;
1919
1920   SIVAL(p,0,PTR_DIFF(p2,*rdata));
1921   strcpy(p2,sesssetup_user);
1922   p2 = skip_string(p2,1);
1923   p += 4;
1924
1925   SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1926   strcpy(p2,myworkgroup);
1927   strupper(p2);
1928   p2 = skip_string(p2,1);
1929   p += 4;
1930
1931   SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
1932   SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
1933   p += 2;
1934
1935   SIVAL(p,0,PTR_DIFF(p2,*rdata));
1936   strcpy(p2,myworkgroup);       /* don't know.  login domain?? */
1937   p2 = skip_string(p2,1);
1938   p += 4;
1939
1940   SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1941   strcpy(p2,"");
1942   p2 = skip_string(p2,1);
1943   p += 4;
1944
1945   *rdata_len = PTR_DIFF(p2,*rdata);
1946
1947   SSVAL(*rparam,4,*rdata_len);
1948
1949   return(True);
1950 }
1951
1952 /****************************************************************************
1953   get info about a user
1954
1955     struct user_info_11 {
1956         char                usri11_name[21];  0-20 
1957         char                usri11_pad;       21 
1958         char                *usri11_comment;  22-25 
1959         char            *usri11_usr_comment;  26-29
1960         unsigned short      usri11_priv;      30-31
1961         unsigned long       usri11_auth_flags; 32-35
1962         long                usri11_password_age; 36-39
1963         char                *usri11_homedir; 40-43
1964         char            *usri11_parms; 44-47
1965         long                usri11_last_logon; 48-51
1966         long                usri11_last_logoff; 52-55
1967         unsigned short      usri11_bad_pw_count; 56-57
1968         unsigned short      usri11_num_logons; 58-59
1969         char                *usri11_logon_server; 60-63
1970         unsigned short      usri11_country_code; 64-65
1971         char            *usri11_workstations; 66-69
1972         unsigned long       usri11_max_storage; 70-73
1973         unsigned short      usri11_units_per_week; 74-75
1974         unsigned char       *usri11_logon_hours; 76-79
1975         unsigned short      usri11_code_page; 80-81
1976     };
1977
1978 where:
1979
1980   usri11_name specifies the user name for which information is retireved
1981
1982   usri11_pad aligns the next data structure element to a word boundary
1983
1984   usri11_comment is a null terminated ASCII comment
1985
1986   usri11_user_comment is a null terminated ASCII comment about the user
1987
1988   usri11_priv specifies the level of the privilege assigned to the user.
1989        The possible values are:
1990
1991 Name             Value  Description
1992 USER_PRIV_GUEST  0      Guest privilege
1993 USER_PRIV_USER   1      User privilege
1994 USER_PRV_ADMIN   2      Administrator privilege
1995
1996   usri11_auth_flags specifies the account operator privileges. The
1997        possible values are:
1998
1999 Name            Value   Description
2000 AF_OP_PRINT     0       Print operator
2001
2002
2003 Leach, Naik                                        [Page 28]\r\f
2004
2005
2006 INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
2007
2008
2009 AF_OP_COMM      1       Communications operator
2010 AF_OP_SERVER    2       Server operator
2011 AF_OP_ACCOUNTS  3       Accounts operator
2012
2013
2014   usri11_password_age specifies how many seconds have elapsed since the
2015        password was last changed.
2016
2017   usri11_home_dir points to a null terminated ASCII string that contains
2018        the path name of the user's home directory.
2019
2020   usri11_parms points to a null terminated ASCII string that is set
2021        aside for use by applications.
2022
2023   usri11_last_logon specifies the time when the user last logged on.
2024        This value is stored as the number of seconds elapsed since
2025        00:00:00, January 1, 1970.
2026
2027   usri11_last_logoff specifies the time when the user last logged off.
2028        This value is stored as the number of seconds elapsed since
2029        00:00:00, January 1, 1970. A value of 0 means the last logoff
2030        time is unknown.
2031
2032   usri11_bad_pw_count specifies the number of incorrect passwords
2033        entered since the last successful logon.
2034
2035   usri11_log1_num_logons specifies the number of times this user has
2036        logged on. A value of -1 means the number of logons is unknown.
2037
2038   usri11_logon_server points to a null terminated ASCII string that
2039        contains the name of the server to which logon requests are sent.
2040        A null string indicates logon requests should be sent to the
2041        domain controller.
2042
2043   usri11_country_code specifies the country code for the user's language
2044        of choice.
2045
2046   usri11_workstations points to a null terminated ASCII string that
2047        contains the names of workstations the user may log on from.
2048        There may be up to 8 workstations, with the names separated by
2049        commas. A null strings indicates there are no restrictions.
2050
2051   usri11_max_storage specifies the maximum amount of disk space the user
2052        can occupy. A value of 0xffffffff indicates there are no
2053        restrictions.
2054
2055   usri11_units_per_week specifies the equal number of time units into
2056        which a week is divided. This value must be equal to 168.
2057
2058   usri11_logon_hours points to a 21 byte (168 bits) string that
2059        specifies the time during which the user can log on. Each bit
2060        represents one unique hour in a week. The first bit (bit 0, word
2061        0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2062
2063
2064
2065 Leach, Naik                                        [Page 29]\r\f
2066
2067
2068 INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
2069
2070
2071        Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2072        are no restrictions.
2073
2074   usri11_code_page specifies the code page for the user's language of
2075        choice
2076
2077 All of the pointers in this data structure need to be treated
2078 specially. The  pointer is a 32 bit pointer. The higher 16 bits need
2079 to be ignored. The converter word returned in the parameters section
2080 needs to be subtracted from the lower 16 bits to calculate an offset
2081 into the return buffer where this ASCII string resides.
2082
2083 There is no auxiliary data in the response.
2084
2085   ****************************************************************************/
2086
2087 #define usri11_name           0 
2088 #define usri11_pad            21
2089 #define usri11_comment        22
2090 #define usri11_usr_comment    26
2091 #define usri11_full_name      30
2092 #define usri11_priv           34
2093 #define usri11_auth_flags     36
2094 #define usri11_password_age   40
2095 #define usri11_homedir        44
2096 #define usri11_parms          48
2097 #define usri11_last_logon     52
2098 #define usri11_last_logoff    56
2099 #define usri11_bad_pw_count   60
2100 #define usri11_num_logons     62
2101 #define usri11_logon_server   64
2102 #define usri11_country_code   68
2103 #define usri11_workstations   70
2104 #define usri11_max_storage    74
2105 #define usri11_units_per_week 78
2106 #define usri11_logon_hours    80
2107 #define usri11_code_page      84
2108 #define usri11_end            86
2109
2110 #define USER_PRIV_GUEST 0
2111 #define USER_PRIV_USER 1
2112 #define USER_PRIV_ADMIN 2
2113
2114 #define AF_OP_PRINT     0 
2115 #define AF_OP_COMM      1
2116 #define AF_OP_SERVER    2
2117 #define AF_OP_ACCOUNTS  3
2118
2119
2120 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
2121                                 int mdrcnt,int mprcnt,
2122                                 char **rdata,char **rparam,
2123                                 int *rdata_len,int *rparam_len)
2124 {
2125         char *str1 = param+2;
2126         char *str2 = skip_string(str1,1);
2127         char *UserName = skip_string(str2,1);
2128         char *p = skip_string(UserName,1);
2129         int uLevel = SVAL(p,0);
2130         char *p2;
2131
2132     /* get NIS home of a previously validated user - simeon */
2133     user_struct *vuser = get_valid_user_struct(vuid);
2134     DEBUG(3,("  Username of UID %d is %s\n", vuser->uid, vuser->name));
2135
2136     *rparam_len = 6;
2137     *rparam = REALLOC(*rparam,*rparam_len);
2138
2139     DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2140   
2141         /* check it's a supported variant */
2142         if (strcmp(str1,"zWrLh") != 0) return False;
2143         switch( uLevel )
2144         {
2145                 case 0: p2 = "B21"; break;
2146                 case 1: p2 = "B21BB16DWzzWz"; break;
2147                 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2148                 case 10: p2 = "B21Bzzz"; break;
2149                 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2150                 default: return False;
2151         }
2152
2153         if (strcmp(p2,str2) != 0) return False;
2154
2155         *rdata_len = mdrcnt + 1024;
2156         *rdata = REALLOC(*rdata,*rdata_len);
2157
2158         SSVAL(*rparam,0,NERR_Success);
2159         SSVAL(*rparam,2,0);             /* converter word */
2160
2161         p = *rdata;
2162         p2 = p + usri11_end;
2163
2164         memset(p,0,21); 
2165         fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2166
2167         if (uLevel > 0)
2168         {
2169                 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2170                 *p2 = 0;
2171         }
2172         if (uLevel >= 10)
2173         {
2174                 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2175                 strcpy(p2,"Comment");
2176                 p2 = skip_string(p2,1);
2177
2178                 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2179                 strcpy(p2,"UserComment");
2180                 p2 = skip_string(p2,1);
2181
2182                 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2183                 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2184                 strcpy(p2,vuser->real_name);    /* simeon */
2185                 p2 = skip_string(p2,1);
2186         }
2187
2188         if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2189         {         
2190                 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); 
2191                 SIVAL(p,usri11_auth_flags,AF_OP_PRINT);         /* auth flags */
2192                 SIVALS(p,usri11_password_age,0xffffffff);               /* password age */
2193                 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2194                 strcpy(p2, lp_logon_path());
2195                 p2 = skip_string(p2,1);
2196                 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2197                 strcpy(p2,"");
2198                 p2 = skip_string(p2,1);
2199                 SIVAL(p,usri11_last_logon,0);           /* last logon */
2200                 SIVAL(p,usri11_last_logoff,0);          /* last logoff */
2201                 SSVALS(p,usri11_bad_pw_count,0xffffffff);               /* bad pw counts */
2202                 SSVALS(p,usri11_num_logons,0xffffffff);         /* num logons */
2203                 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2204                 strcpy(p2,"\\\\*");
2205                 p2 = skip_string(p2,1);
2206                 SSVAL(p,usri11_country_code,0);         /* country code */
2207
2208                 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2209                 strcpy(p2,"");
2210                 p2 = skip_string(p2,1);
2211
2212                 SIVALS(p,usri11_max_storage,0xffffffff);                /* max storage */
2213                 SSVAL(p,usri11_units_per_week,168);             /* units per week */
2214                 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2215
2216                 /* a simple way to get logon hours at all times. */
2217                 memset(p2,0xff,21);
2218                 SCVAL(p2,21,0);           /* fix zero termination */
2219                 p2 = skip_string(p2,1);
2220
2221                 SSVAL(p,usri11_code_page,0);            /* code page */
2222         }
2223         if (uLevel == 1 || uLevel == 2)
2224         {
2225                 memset(p+22,' ',16);    /* password */
2226                 SIVALS(p,38,-1);                /* password age */
2227                 SSVAL(p,42,
2228                 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2229                 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2230                 strcpy(p2,lp_logon_path());
2231                 p2 = skip_string(p2,1);
2232                 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2233                 *p2++ = 0;
2234                 SSVAL(p,52,0);          /* flags */
2235                 SIVAL(p,54,0);          /* script_path */
2236                 if (uLevel == 2)
2237                 {
2238                         SIVAL(p,60,0);          /* auth_flags */
2239                         SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2240                         strcpy(p2,vuser->real_name);    /* simeon */
2241                         p2 = skip_string(p2,1);
2242                         SIVAL(p,68,0);          /* urs_comment */
2243                         SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2244                         strcpy(p2,"");
2245                         p2 = skip_string(p2,1);
2246                         SIVAL(p,76,0);          /* workstations */
2247                         SIVAL(p,80,0);          /* last_logon */
2248                         SIVAL(p,84,0);          /* last_logoff */
2249                         SIVALS(p,88,-1);                /* acct_expires */
2250                         SIVALS(p,92,-1);                /* max_storage */
2251                         SSVAL(p,96,168);        /* units_per_week */
2252                         SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2253                         memset(p2,-1,21);
2254                         p2 += 21;
2255                         SSVALS(p,102,-1);       /* bad_pw_count */
2256                         SSVALS(p,104,-1);       /* num_logons */
2257                         SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2258                         strcpy(p2,"\\\\%L");
2259                         standard_sub_basic(p2);
2260                         p2 = skip_string(p2,1);
2261                         SSVAL(p,110,49);        /* country_code */
2262                         SSVAL(p,112,860);       /* code page */
2263                 }
2264         }
2265
2266         *rdata_len = PTR_DIFF(p2,*rdata);
2267
2268         SSVAL(*rparam,4,*rdata_len);    /* is this right?? */
2269
2270         return(True);
2271 }
2272
2273 /*******************************************************************
2274   get groups that a user is a member of
2275   ******************************************************************/
2276 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2277                                  int mdrcnt,int mprcnt,
2278                                  char **rdata,char **rparam,
2279                                  int *rdata_len,int *rparam_len)
2280 {
2281   char *str1 = param+2;
2282   char *str2 = skip_string(str1,1);
2283   char *UserName = skip_string(str2,1);
2284   char *p = skip_string(UserName,1);
2285   int uLevel = SVAL(p,0);
2286   char *p2;
2287   int count=0;
2288
2289   *rparam_len = 8;
2290   *rparam = REALLOC(*rparam,*rparam_len);
2291
2292   /* check it's a supported varient */
2293   if (strcmp(str1,"zWrLeh") != 0) return False;
2294   switch( uLevel ) {
2295   case 0: p2 = "B21"; break;
2296   default: return False;
2297   }
2298   if (strcmp(p2,str2) != 0) return False;
2299
2300   *rdata_len = mdrcnt + 1024;
2301   *rdata = REALLOC(*rdata,*rdata_len);
2302
2303   SSVAL(*rparam,0,NERR_Success);
2304   SSVAL(*rparam,2,0);           /* converter word */
2305
2306   p = *rdata;
2307
2308   /* XXXX we need a real SAM database some day */
2309   strcpy(p,"Users"); p += 21; count++;
2310   strcpy(p,"Domain Users"); p += 21; count++;
2311   strcpy(p,"Guests"); p += 21; count++;
2312   strcpy(p,"Domain Guests"); p += 21; count++;
2313
2314   *rdata_len = PTR_DIFF(p,*rdata);
2315
2316   SSVAL(*rparam,4,count);       /* is this right?? */
2317   SSVAL(*rparam,6,count);       /* is this right?? */
2318
2319   return(True);
2320 }
2321
2322
2323 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2324                                 int mdrcnt,int mprcnt,
2325                                 char **rdata,char **rparam,
2326                                 int *rdata_len,int *rparam_len)
2327 {
2328   char *str1 = param+2;
2329   char *str2 = skip_string(str1,1);
2330   char *p = skip_string(str2,1);
2331   int uLevel;
2332   struct pack_desc desc;
2333   char* name;
2334   char* logon_script;
2335
2336   uLevel = SVAL(p,0);
2337   name = p + 2;
2338
2339   bzero(&desc,sizeof(desc));
2340
2341   DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2342
2343   /* check it's a supported varient */
2344   if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2345   if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2346   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2347   desc.base = *rdata;
2348   desc.buflen = mdrcnt;
2349   desc.subformat = NULL;
2350   desc.format = str2;
2351   
2352   if (init_package(&desc,1,0))
2353   {
2354     PACKI(&desc,"W",0);         /* code */
2355     PACKS(&desc,"B21",name);    /* eff. name */
2356     PACKS(&desc,"B","");                /* pad */
2357     PACKI(&desc,"W",
2358           Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2359     PACKI(&desc,"D",0);         /* auth flags XXX */
2360     PACKI(&desc,"W",0);         /* num logons */
2361     PACKI(&desc,"W",0);         /* bad pw count */
2362     PACKI(&desc,"D",0);         /* last logon */
2363     PACKI(&desc,"D",-1);                /* last logoff */
2364     PACKI(&desc,"D",-1);                /* logoff time */
2365     PACKI(&desc,"D",-1);                /* kickoff time */
2366     PACKI(&desc,"D",0);         /* password age */
2367     PACKI(&desc,"D",0);         /* password can change */
2368     PACKI(&desc,"D",-1);                /* password must change */
2369     {
2370       fstring mypath;
2371       strcpy(mypath,"\\\\");
2372       strcat(mypath,local_machine);
2373       strupper(mypath);
2374       PACKS(&desc,"z",mypath); /* computer */
2375     }
2376     PACKS(&desc,"z",myworkgroup);/* domain */
2377
2378 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2379 /* made sure all macros are fully substituted and available */
2380     logon_script = lp_logon_script();
2381     standard_sub( cnum, logon_script );
2382     PACKS(&desc,"z", logon_script);             /* script path */
2383 /* End of JHT mods */
2384
2385     PACKI(&desc,"D",0x00000000);                /* reserved */
2386   }
2387
2388   *rdata_len = desc.usedlen;
2389   *rparam_len = 6;
2390   *rparam = REALLOC(*rparam,*rparam_len);
2391   SSVALS(*rparam,0,desc.errcode);
2392   SSVAL(*rparam,2,0);
2393   SSVAL(*rparam,4,desc.neededlen);
2394
2395   DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2396   return(True);
2397 }
2398
2399
2400 /****************************************************************************
2401   api_WAccessGetUserPerms
2402   ****************************************************************************/
2403 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2404                                     int mdrcnt,int mprcnt,
2405                                     char **rdata,char **rparam,
2406                                     int *rdata_len,int *rparam_len)
2407 {
2408   char *str1 = param+2;
2409   char *str2 = skip_string(str1,1);
2410   char *user = skip_string(str2,1);
2411   char *resource = skip_string(user,1);
2412
2413   DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2414
2415   /* check it's a supported varient */
2416   if (strcmp(str1,"zzh") != 0) return False;
2417   if (strcmp(str2,"") != 0) return False;
2418
2419   *rparam_len = 6;
2420   *rparam = REALLOC(*rparam,*rparam_len);
2421   SSVALS(*rparam,0,0);          /* errorcode */
2422   SSVAL(*rparam,2,0);           /* converter word */
2423   SSVAL(*rparam,4,0x7f);        /* permission flags */
2424
2425   return(True);
2426 }
2427
2428 /****************************************************************************
2429   api_WPrintJobEnumerate
2430   ****************************************************************************/
2431 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2432                                  int mdrcnt,int mprcnt,
2433                                  char **rdata,char **rparam,
2434                                  int *rdata_len,int *rparam_len)
2435 {
2436   char *str1 = param+2;
2437   char *str2 = skip_string(str1,1);
2438   char *p = skip_string(str2,1);
2439   int uLevel,cbBuf;
2440   int count;
2441   int i;
2442   int snum;
2443   int job;
2444   struct pack_desc desc;
2445   print_queue_struct *queue=NULL;
2446   print_status_struct status;
2447
2448   uLevel = SVAL(p,2);
2449   cbBuf = SVAL(p,4);
2450
2451   bzero(&desc,sizeof(desc));
2452   bzero(&status,sizeof(status));
2453
2454   DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2455
2456   /* check it's a supported varient */
2457   if (strcmp(str1,"WWrLh") != 0) return False;
2458   if (!check_printjob_info(&desc,uLevel,str2)) return False;
2459
2460   printjob_decode(SVAL(p,0), &snum, &job);
2461
2462   if (snum < 0 || !VALID_SNUM(snum)) return(False);
2463
2464   count = get_printqueue(snum,cnum,&queue,&status);
2465   for (i = 0; i < count; i++) {
2466     if ((queue[i].job & 0xFF) == job) break;
2467   }
2468   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2469   desc.base = *rdata;
2470   desc.buflen = mdrcnt;
2471
2472   if (init_package(&desc,1,0)) {
2473     if (i < count) {
2474       fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2475       *rdata_len = desc.usedlen;
2476     }
2477     else {
2478       desc.errcode = NERR_JobNotFound;
2479       *rdata_len = 0;
2480     }
2481   }
2482
2483   *rparam_len = 6;
2484   *rparam = REALLOC(*rparam,*rparam_len);
2485   SSVALS(*rparam,0,desc.errcode);
2486   SSVAL(*rparam,2,0);
2487   SSVAL(*rparam,4,desc.neededlen);
2488
2489   if (queue) free(queue);
2490
2491   DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2492   return(True);
2493 }
2494
2495 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2496                                    int mdrcnt,int mprcnt,
2497                                    char **rdata,char **rparam,
2498                                    int *rdata_len,int *rparam_len)
2499 {
2500   char *str1 = param+2;
2501   char *str2 = skip_string(str1,1);
2502   char *p = skip_string(str2,1);
2503   char* name = p;
2504   int uLevel,cbBuf;
2505   int count;
2506   int i, succnt=0;
2507   int snum;
2508   struct pack_desc desc;
2509   print_queue_struct *queue=NULL;
2510   print_status_struct status;
2511
2512   bzero(&desc,sizeof(desc));
2513   bzero(&status,sizeof(status));
2514
2515   p = skip_string(p,1);
2516   uLevel = SVAL(p,0);
2517   cbBuf = SVAL(p,2);
2518
2519   DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2520
2521   /* check it's a supported varient */
2522   if (strcmp(str1,"zWrLeh") != 0) return False;
2523   if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2524   if (!check_printjob_info(&desc,uLevel,str2)) return False;
2525
2526   snum = lp_servicenumber(name);
2527   if (snum < 0 && pcap_printername_ok(name,NULL)) {
2528     int pnum = lp_servicenumber(PRINTERS_NAME);
2529     if (pnum >= 0) {
2530       lp_add_printer(name,pnum);
2531       snum = lp_servicenumber(name);
2532     }
2533   }
2534
2535   if (snum < 0 || !VALID_SNUM(snum)) return(False);
2536
2537   count = get_printqueue(snum,cnum,&queue,&status);
2538   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2539   desc.base = *rdata;
2540   desc.buflen = mdrcnt;
2541
2542   if (init_package(&desc,count,0)) {
2543     succnt = 0;
2544     for (i = 0; i < count; i++) {
2545       fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2546       if (desc.errcode == NERR_Success) succnt = i+1;
2547     }
2548   }
2549
2550   *rdata_len = desc.usedlen;
2551
2552   *rparam_len = 8;
2553   *rparam = REALLOC(*rparam,*rparam_len);
2554   SSVALS(*rparam,0,desc.errcode);
2555   SSVAL(*rparam,2,0);
2556   SSVAL(*rparam,4,succnt);
2557   SSVAL(*rparam,6,count);
2558
2559   if (queue) free(queue);
2560
2561   DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2562   return(True);
2563 }
2564
2565 static int check_printdest_info(struct pack_desc* desc,
2566                                 int uLevel, char* id)
2567 {
2568   desc->subformat = NULL;
2569   switch( uLevel ) {
2570   case 0: desc->format = "B9"; break;
2571   case 1: desc->format = "B9B21WWzW"; break;
2572   case 2: desc->format = "z"; break;
2573   case 3: desc->format = "zzzWWzzzWW"; break;
2574   default: return False;
2575   }
2576   if (strcmp(desc->format,id) != 0) return False;
2577   return True;
2578 }
2579
2580 static void fill_printdest_info(int cnum, int snum, int uLevel,
2581                                 struct pack_desc* desc)
2582 {
2583   char buf[100];
2584   strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2585   buf[sizeof(buf)-1] = 0;
2586   strupper(buf);
2587   if (uLevel <= 1) {
2588     PACKS(desc,"B9",buf);       /* szName */
2589     if (uLevel == 1) {
2590       PACKS(desc,"B21","");     /* szUserName */
2591       PACKI(desc,"W",0);                /* uJobId */
2592       PACKI(desc,"W",0);                /* fsStatus */
2593       PACKS(desc,"z","");       /* pszStatus */
2594       PACKI(desc,"W",0);                /* time */
2595     }
2596   }
2597   if (uLevel == 2 || uLevel == 3) {
2598     PACKS(desc,"z",buf);                /* pszPrinterName */
2599     if (uLevel == 3) {
2600       PACKS(desc,"z","");       /* pszUserName */
2601       PACKS(desc,"z","");       /* pszLogAddr */
2602       PACKI(desc,"W",0);                /* uJobId */
2603       PACKI(desc,"W",0);                /* fsStatus */
2604       PACKS(desc,"z","");       /* pszStatus */
2605       PACKS(desc,"z","");       /* pszComment */
2606       PACKS(desc,"z","NULL"); /* pszDrivers */
2607       PACKI(desc,"W",0);                /* time */
2608       PACKI(desc,"W",0);                /* pad1 */
2609     }
2610   }
2611 }
2612
2613 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2614                                   int mdrcnt,int mprcnt,
2615                                   char **rdata,char **rparam,
2616                                   int *rdata_len,int *rparam_len)
2617 {
2618   char *str1 = param+2;
2619   char *str2 = skip_string(str1,1);
2620   char *p = skip_string(str2,1);
2621   char* PrinterName = p;
2622   int uLevel,cbBuf;
2623   struct pack_desc desc;
2624   int snum;
2625
2626   bzero(&desc,sizeof(desc));
2627
2628   p = skip_string(p,1);
2629   uLevel = SVAL(p,0);
2630   cbBuf = SVAL(p,2);
2631
2632   DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2633
2634   /* check it's a supported varient */
2635   if (strcmp(str1,"zWrLh") != 0) return False;
2636   if (!check_printdest_info(&desc,uLevel,str2)) return False;
2637
2638   snum = lp_servicenumber(PrinterName);
2639   if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2640     int pnum = lp_servicenumber(PRINTERS_NAME);
2641     if (pnum >= 0) {
2642       lp_add_printer(PrinterName,pnum);
2643       snum = lp_servicenumber(PrinterName);
2644     }
2645   }
2646
2647   if (snum < 0) {
2648     *rdata_len = 0;
2649     desc.errcode = NERR_DestNotFound;
2650     desc.neededlen = 0;
2651   }
2652   else {
2653     if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2654     desc.base = *rdata;
2655     desc.buflen = mdrcnt;
2656     if (init_package(&desc,1,0)) {
2657       fill_printdest_info(cnum,snum,uLevel,&desc);
2658     }
2659     *rdata_len = desc.usedlen;
2660   }
2661
2662   *rparam_len = 6;
2663   *rparam = REALLOC(*rparam,*rparam_len);
2664   SSVALS(*rparam,0,desc.errcode);
2665   SSVAL(*rparam,2,0);
2666   SSVAL(*rparam,4,desc.neededlen);
2667
2668   DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2669   return(True);
2670 }
2671
2672 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2673                                int mdrcnt,int mprcnt,
2674                                char **rdata,char **rparam,
2675                                int *rdata_len,int *rparam_len)
2676 {
2677   char *str1 = param+2;
2678   char *str2 = skip_string(str1,1);
2679   char *p = skip_string(str2,1);
2680   int uLevel,cbBuf;
2681   int queuecnt;
2682   int i, n, succnt=0;
2683   struct pack_desc desc;
2684   int services = lp_numservices();
2685
2686   bzero(&desc,sizeof(desc));
2687
2688   uLevel = SVAL(p,0);
2689   cbBuf = SVAL(p,2);
2690
2691   DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2692
2693   /* check it's a supported varient */
2694   if (strcmp(str1,"WrLeh") != 0) return False;
2695   if (!check_printdest_info(&desc,uLevel,str2)) return False;
2696
2697   queuecnt = 0;
2698   for (i = 0; i < services; i++)
2699     if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2700       queuecnt++;
2701
2702   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2703   desc.base = *rdata;
2704   desc.buflen = mdrcnt;
2705   if (init_package(&desc,queuecnt,0)) {    
2706     succnt = 0;
2707     n = 0;
2708     for (i = 0; i < services; i++) {
2709       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2710         fill_printdest_info(cnum,i,uLevel,&desc);
2711         n++;
2712         if (desc.errcode == NERR_Success) succnt = n;
2713       }
2714     }
2715   }
2716
2717   *rdata_len = desc.usedlen;
2718
2719   *rparam_len = 8;
2720   *rparam = REALLOC(*rparam,*rparam_len);
2721   SSVALS(*rparam,0,desc.errcode);
2722   SSVAL(*rparam,2,0);
2723   SSVAL(*rparam,4,succnt);
2724   SSVAL(*rparam,6,queuecnt);
2725
2726   DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2727   return(True);
2728 }
2729
2730 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2731                                  int mdrcnt,int mprcnt,
2732                                  char **rdata,char **rparam,
2733                                  int *rdata_len,int *rparam_len)
2734 {
2735   char *str1 = param+2;
2736   char *str2 = skip_string(str1,1);
2737   char *p = skip_string(str2,1);
2738   int uLevel,cbBuf;
2739   int succnt;
2740   struct pack_desc desc;
2741
2742   bzero(&desc,sizeof(desc));
2743
2744   uLevel = SVAL(p,0);
2745   cbBuf = SVAL(p,2);
2746
2747   DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2748
2749   /* check it's a supported varient */
2750   if (strcmp(str1,"WrLeh") != 0) return False;
2751   if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2752
2753   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2754   desc.base = *rdata;
2755   desc.buflen = mdrcnt;
2756   if (init_package(&desc,1,0)) {
2757     PACKS(&desc,"B41","NULL");
2758   }
2759
2760   succnt = (desc.errcode == NERR_Success ? 1 : 0);
2761
2762   *rdata_len = desc.usedlen;
2763
2764   *rparam_len = 8;
2765   *rparam = REALLOC(*rparam,*rparam_len);
2766   SSVALS(*rparam,0,desc.errcode);
2767   SSVAL(*rparam,2,0);
2768   SSVAL(*rparam,4,succnt);
2769   SSVAL(*rparam,6,1);
2770
2771   DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2772   return(True);
2773 }
2774
2775 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2776                                 int mdrcnt,int mprcnt,
2777                                 char **rdata,char **rparam,
2778                                 int *rdata_len,int *rparam_len)
2779 {
2780   char *str1 = param+2;
2781   char *str2 = skip_string(str1,1);
2782   char *p = skip_string(str2,1);
2783   int uLevel,cbBuf;
2784   int succnt;
2785   struct pack_desc desc;
2786
2787   bzero(&desc,sizeof(desc));
2788
2789   uLevel = SVAL(p,0);
2790   cbBuf = SVAL(p,2);
2791
2792   DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2793
2794   /* check it's a supported varient */
2795   if (strcmp(str1,"WrLeh") != 0) return False;
2796   if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2797
2798   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2799   desc.base = *rdata;
2800   desc.buflen = mdrcnt;
2801   desc.format = str2;
2802   if (init_package(&desc,1,0)) {
2803     PACKS(&desc,"B13","lpd");
2804   }
2805
2806   succnt = (desc.errcode == NERR_Success ? 1 : 0);
2807
2808   *rdata_len = desc.usedlen;
2809
2810   *rparam_len = 8;
2811   *rparam = REALLOC(*rparam,*rparam_len);
2812   SSVALS(*rparam,0,desc.errcode);
2813   SSVAL(*rparam,2,0);
2814   SSVAL(*rparam,4,succnt);
2815   SSVAL(*rparam,6,1);
2816
2817   DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2818   return(True);
2819 }
2820
2821 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2822                                int mdrcnt,int mprcnt,
2823                                char **rdata,char **rparam,
2824                                int *rdata_len,int *rparam_len)
2825 {
2826   char *str1 = param+2;
2827   char *str2 = skip_string(str1,1);
2828   char *p = skip_string(str2,1);
2829   int uLevel,cbBuf;
2830   int succnt;
2831   struct pack_desc desc;
2832
2833   bzero(&desc,sizeof(desc));
2834
2835   uLevel = SVAL(p,0);
2836   cbBuf = SVAL(p,2);
2837
2838   DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2839
2840   /* check it's a supported varient */
2841   if (strcmp(str1,"WrLeh") != 0) return False;
2842   if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2843
2844   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2845   bzero(&desc,sizeof(desc));
2846   desc.base = *rdata;
2847   desc.buflen = mdrcnt;
2848   desc.format = str2;
2849   if (init_package(&desc,1,0)) {
2850     PACKS(&desc,"B13","lp0");
2851   }
2852
2853   succnt = (desc.errcode == NERR_Success ? 1 : 0);
2854
2855   *rdata_len = desc.usedlen;
2856
2857   *rparam_len = 8;
2858   *rparam = REALLOC(*rparam,*rparam_len);
2859   SSVALS(*rparam,0,desc.errcode);
2860   SSVAL(*rparam,2,0);
2861   SSVAL(*rparam,4,succnt);
2862   SSVAL(*rparam,6,1);
2863
2864   DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2865   return(True);
2866 }
2867
2868
2869 struct
2870 {
2871   char * name;
2872   char * pipe_clnt_name;
2873 #ifdef NTDOMAIN
2874   char * pipe_srv_name;
2875 #endif
2876   int subcommand;
2877   BOOL (*fn) ();
2878 } api_fd_commands [] =
2879   {
2880 #ifdef NTDOMAIN
2881     { "TransactNmPipe",     "lsarpc",   "lsass",        0x26,   api_ntLsarpcTNP },
2882     { "TransactNmPipe",     "samr",     "lsass",        0x26,   api_samrTNP },
2883     { "TransactNmPipe",     "srvsvc",   "lsass",        0x26,   api_srvsvcTNP },
2884     { "TransactNmPipe",     "wkssvc",   "ntsvcs",       0x26,   api_wkssvcTNP },
2885     { "TransactNmPipe",     "NETLOGON", "NETLOGON",     0x26,   api_netlogrpcTNP },
2886     { NULL,                         NULL,       NULL,   -1,     (BOOL (*)())api_Unsupported }
2887 #else
2888     { "TransactNmPipe"  ,       "lsarpc",       0x26,   api_LsarpcTNP },
2889     { NULL,             NULL,           -1,     (BOOL (*)())api_Unsupported }
2890 #endif
2891   };
2892
2893 /****************************************************************************
2894   handle remote api calls delivered to a named pipe already opened.
2895   ****************************************************************************/
2896 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2897                         uint16 *setup,char *data,char *params,
2898                         int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2899 {
2900   char *rdata = NULL;
2901   char *rparam = NULL;
2902   int rdata_len = 0;
2903   int rparam_len = 0;
2904
2905   BOOL reply    = False;
2906   BOOL bind_req = False;
2907   BOOL set_nphs = False;
2908
2909   int i;
2910   int fd;
2911   int subcommand;
2912   char *pipe_name;
2913   
2914   DEBUG(5,("api_fd_reply\n"));
2915   /* First find out the name of this file. */
2916   if (suwcnt != 2)
2917     {
2918       DEBUG(0,("Unexpected named pipe transaction.\n"));
2919       return(-1);
2920     }
2921   
2922   /* Get the file handle and hence the file name. */
2923   fd = setup[1];
2924   subcommand = setup[0];
2925   pipe_name = get_rpc_pipe_hnd_name(fd);
2926
2927   if (pipe_name == NULL)
2928   {
2929     DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", fd));
2930   }
2931
2932   DEBUG(3,("Got API command %d on pipe %s (fd %x)",
2933             subcommand, pipe_name, fd));
2934   DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
2935            tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
2936   
2937   for (i = 0; api_fd_commands[i].name; i++)
2938   {
2939     if (strequal(api_fd_commands[i].pipe_clnt_name, pipe_name) &&
2940             api_fd_commands[i].subcommand == subcommand &&
2941             api_fd_commands[i].fn)
2942     {
2943           DEBUG(3,("Doing %s\n", api_fd_commands[i].name));
2944           break;
2945     }
2946   }
2947   
2948   rdata  = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024);
2949   rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2950   
2951 #ifdef NTDOMAIN
2952   /* RPC Pipe command 0x26. */
2953   if (data != NULL && api_fd_commands[i].subcommand == 0x26)
2954   {
2955     RPC_HDR hdr;
2956
2957     /* process the rpc header */
2958     char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0);
2959     
2960         /* bind request received */
2961     if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND))))
2962     {
2963       RPC_HDR_RB hdr_rb;
2964
2965       /* decode the bind request */
2966       char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0);
2967
2968       if ((bind_req = (p != NULL)))
2969       {
2970         RPC_HDR_BA hdr_ba;
2971         fstring ack_pipe_name;
2972
2973         /* name has to be \PIPE\xxxxx */
2974         strcpy(ack_pipe_name, "\\PIPE\\");
2975         strcat(ack_pipe_name, api_fd_commands[i].pipe_srv_name);
2976
2977         /* make a bind acknowledgement */
2978         make_rpc_hdr_ba(&hdr_ba,
2979                hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid,
2980                ack_pipe_name,
2981                0x1, 0x0, 0x0,
2982                &(hdr_rb.transfer));
2983
2984         p = smb_io_rpc_hdr_ba(False, &hdr_ba, rdata + 0x10, rdata, 4, 0);
2985
2986                 rdata_len = PTR_DIFF(p, rdata);
2987
2988         make_rpc_hdr(&hdr, RPC_BINDACK, 0x0, hdr.call_id, rdata_len);
2989
2990         p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0);
2991         
2992         reply = (p != NULL);
2993       }
2994     }
2995   }
2996 #endif
2997
2998   /* Set Named Pipe Handle state */
2999   if (subcommand == 0x1)
3000   {
3001     set_nphs = True;
3002     reply = api_LsarpcSNPHS(fd, cnum, params);
3003   }
3004
3005   if (!bind_req && !set_nphs)
3006   {
3007     DEBUG(10,("calling api_fd_command\n"));
3008
3009     reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3010                                 &rdata,&rparam,&rdata_len,&rparam_len);
3011     DEBUG(10,("called api_fd_command\n"));
3012   }
3013
3014   if (rdata_len > mdrcnt || rparam_len > mprcnt)
3015   {
3016     reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3017                            &rdata,&rparam,&rdata_len,&rparam_len);
3018   }
3019   
3020   /* if we get False back then it's actually unsupported */
3021   if (!reply)
3022   {
3023     api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3024                     &rdata,&rparam,&rdata_len,&rparam_len);
3025   }
3026   
3027   /* now send the reply */
3028   send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
3029   
3030   if (rdata ) free(rdata );
3031   if (rparam) free(rparam);
3032   
3033   return(-1);
3034 }
3035
3036
3037
3038 /****************************************************************************
3039   the buffer was too small
3040   ****************************************************************************/
3041 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
3042                          int mdrcnt,int mprcnt,
3043                          char **rdata,char **rparam,
3044                          int *rdata_len,int *rparam_len)
3045 {
3046   *rparam_len = MIN(*rparam_len,mprcnt);
3047   *rparam = REALLOC(*rparam,*rparam_len);
3048
3049   *rdata_len = 0;
3050
3051   SSVAL(*rparam,0,NERR_BufTooSmall);
3052
3053   DEBUG(3,("Supplied buffer too small in API command\n"));
3054
3055   return(True);
3056 }
3057
3058
3059 /****************************************************************************
3060   the request is not supported
3061   ****************************************************************************/
3062 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
3063                             int mdrcnt,int mprcnt,
3064                             char **rdata,char **rparam,
3065                             int *rdata_len,int *rparam_len)
3066 {
3067   *rparam_len = 4;
3068   *rparam = REALLOC(*rparam,*rparam_len);
3069
3070   *rdata_len = 0;
3071
3072   SSVAL(*rparam,0,NERR_notsupported);
3073   SSVAL(*rparam,2,0);           /* converter word */
3074
3075   DEBUG(3,("Unsupported API command\n"));
3076
3077   return(True);
3078 }
3079
3080
3081
3082
3083 struct
3084 {
3085   char *name;
3086   int id;
3087   BOOL (*fn)();
3088   int flags;
3089 } api_commands[] = {
3090   {"RNetShareEnum",     0,      (BOOL (*)())api_RNetShareEnum,0},
3091   {"RNetShareGetInfo",  1,      (BOOL (*)())api_RNetShareGetInfo,0},
3092   {"RNetServerGetInfo", 13,     (BOOL (*)())api_RNetServerGetInfo,0},
3093   {"RNetUserGetInfo",   56,     (BOOL (*)())api_RNetUserGetInfo,0},
3094   {"NetUserGetGroups",  59,     (BOOL (*)())api_NetUserGetGroups,0},
3095   {"NetWkstaGetInfo",   63,     (BOOL (*)())api_NetWkstaGetInfo,0},
3096   {"DosPrintQEnum",     69,     (BOOL (*)())api_DosPrintQEnum,0},
3097   {"DosPrintQGetInfo",  70,     (BOOL (*)())api_DosPrintQGetInfo,0},
3098   {"WPrintJobEnumerate",76,     (BOOL (*)())api_WPrintJobEnumerate,0},
3099   {"WPrintJobGetInfo",  77,     (BOOL (*)())api_WPrintJobGetInfo,0},
3100   {"RDosPrintJobDel",   81,     (BOOL (*)())api_RDosPrintJobDel,0},
3101   {"RDosPrintJobPause", 82,     (BOOL (*)())api_RDosPrintJobDel,0},
3102   {"RDosPrintJobResume",83,     (BOOL (*)())api_RDosPrintJobDel,0},
3103   {"WPrintDestEnum",    84,     (BOOL (*)())api_WPrintDestEnum,0},
3104   {"WPrintDestGetInfo", 85,     (BOOL (*)())api_WPrintDestGetInfo,0},
3105   {"NetRemoteTOD",      91,     (BOOL (*)())api_NetRemoteTOD,0},
3106   {"WPrintQueuePurge",  103,    (BOOL (*)())api_WPrintQueuePurge,0},
3107   {"NetServerEnum",     104,    (BOOL (*)())api_RNetServerEnum,0},
3108   {"WAccessGetUserPerms",105,   (BOOL (*)())api_WAccessGetUserPerms,0},
3109   {"SetUserPassword",   115,    (BOOL (*)())api_SetUserPassword,0},
3110   {"WWkstaUserLogon",   132,    (BOOL (*)())api_WWkstaUserLogon,0},
3111   {"PrintJobInfo",      147,    (BOOL (*)())api_PrintJobInfo,0},
3112   {"WPrintDriverEnum",  205,    (BOOL (*)())api_WPrintDriverEnum,0},
3113   {"WPrintQProcEnum",   206,    (BOOL (*)())api_WPrintQProcEnum,0},
3114   {"WPrintPortEnum",    207,    (BOOL (*)())api_WPrintPortEnum,0},
3115   {NULL,                -1,     (BOOL (*)())api_Unsupported,0}};
3116
3117
3118 /****************************************************************************
3119   handle remote api calls
3120   ****************************************************************************/
3121 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
3122                      int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3123 {
3124   int api_command = SVAL(params,0);
3125   char *rdata = NULL;
3126   char *rparam = NULL;
3127   int rdata_len = 0;
3128   int rparam_len = 0;
3129   BOOL reply=False;
3130   int i;
3131
3132   DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3133            api_command,params+2,skip_string(params+2,1),
3134            tdscnt,tpscnt,mdrcnt,mprcnt));
3135
3136   for (i=0;api_commands[i].name;i++)
3137     if (api_commands[i].id == api_command && api_commands[i].fn)
3138       {
3139         DEBUG(3,("Doing %s\n",api_commands[i].name));
3140         break;
3141       }
3142
3143   rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
3144   rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
3145
3146   reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
3147                              &rdata,&rparam,&rdata_len,&rparam_len);
3148
3149
3150   if (rdata_len > mdrcnt ||
3151       rparam_len > mprcnt)
3152     {
3153       reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
3154                            &rdata,&rparam,&rdata_len,&rparam_len);
3155     }
3156             
3157
3158   /* if we get False back then it's actually unsupported */
3159   if (!reply)
3160     api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
3161                     &rdata,&rparam,&rdata_len,&rparam_len);
3162
3163       
3164
3165   /* now send the reply */
3166   send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
3167
3168   if (rdata)
3169     free(rdata);
3170   if (rparam)
3171     free(rparam);
3172   
3173   return(-1);
3174 }
3175
3176 /****************************************************************************
3177   handle named pipe commands
3178   ****************************************************************************/
3179 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3180                       uint16 *setup,char *data,char *params,
3181                       int suwcnt,int tdscnt,int tpscnt,
3182                       int msrcnt,int mdrcnt,int mprcnt)
3183 {
3184         DEBUG(3,("named pipe command on <%s> name\n", name));
3185
3186         if (strequal(name,"LANMAN"))
3187         {
3188                 return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3189         }
3190
3191         if (strlen(name) < 1)
3192         {
3193                 return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3194         }
3195
3196         if (setup)
3197         {
3198                 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3199         }
3200
3201         return 0;
3202 }
3203
3204
3205 /****************************************************************************
3206   reply to a SMBtrans
3207   ****************************************************************************/
3208 int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
3209 {
3210   fstring name;
3211
3212   char *data=NULL,*params=NULL;
3213   uint16 *setup=NULL;
3214
3215   int outsize = 0;
3216   int cnum = SVAL(inbuf,smb_tid);
3217   uint16 vuid = SVAL(inbuf,smb_uid);
3218
3219   int tpscnt = SVAL(inbuf,smb_vwv0);
3220   int tdscnt = SVAL(inbuf,smb_vwv1);
3221   int mprcnt = SVAL(inbuf,smb_vwv2);
3222   int mdrcnt = SVAL(inbuf,smb_vwv3);
3223   int msrcnt = CVAL(inbuf,smb_vwv4);
3224   BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3225   BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3226   int pscnt = SVAL(inbuf,smb_vwv9);
3227   int psoff = SVAL(inbuf,smb_vwv10);
3228   int dscnt = SVAL(inbuf,smb_vwv11);
3229   int dsoff = SVAL(inbuf,smb_vwv12);
3230   int suwcnt = CVAL(inbuf,smb_vwv13);
3231
3232   bzero(name, sizeof(name));
3233   fstrcpy(name,smb_buf(inbuf));
3234
3235   if (dscnt > tdscnt || pscnt > tpscnt) {
3236           exit_server("invalid trans parameters\n");
3237   }
3238   
3239   if (tdscnt)
3240     {
3241       data = (char *)malloc(tdscnt);
3242       memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3243     }
3244   if (tpscnt)
3245     {
3246       params = (char *)malloc(tpscnt);
3247       memcpy(params,smb_base(inbuf)+psoff,pscnt);
3248     }
3249
3250   if (suwcnt)
3251     {
3252       int i;
3253       setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3254       for (i=0;i<suwcnt;i++)
3255         setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3256     }
3257
3258
3259   if (pscnt < tpscnt || dscnt < tdscnt)
3260     {
3261       /* We need to send an interim response then receive the rest
3262          of the parameter/data bytes */
3263       outsize = set_message(outbuf,0,0,True);
3264       show_msg(outbuf);
3265       send_smb(Client,outbuf);
3266     }
3267
3268   /* receive the rest of the trans packet */
3269   while (pscnt < tpscnt || dscnt < tdscnt)
3270     {
3271       BOOL ret;
3272       int pcnt,poff,dcnt,doff,pdisp,ddisp;
3273       
3274       ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
3275
3276       if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
3277         {
3278           if(ret)
3279             DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3280           else
3281             DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3282               (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3283           if (params) free(params);
3284           if (data) free(data);
3285           if (setup) free(setup);
3286           return(ERROR(ERRSRV,ERRerror));
3287         }
3288
3289       show_msg(inbuf);
3290       
3291       tpscnt = SVAL(inbuf,smb_vwv0);
3292       tdscnt = SVAL(inbuf,smb_vwv1);
3293
3294       pcnt = SVAL(inbuf,smb_vwv2);
3295       poff = SVAL(inbuf,smb_vwv3);
3296       pdisp = SVAL(inbuf,smb_vwv4);
3297       
3298       dcnt = SVAL(inbuf,smb_vwv5);
3299       doff = SVAL(inbuf,smb_vwv6);
3300       ddisp = SVAL(inbuf,smb_vwv7);
3301       
3302       pscnt += pcnt;
3303       dscnt += dcnt;
3304
3305       if (dscnt > tdscnt || pscnt > tpscnt) {
3306               exit_server("invalid trans parameters\n");
3307       }
3308
3309       if (pcnt)
3310         memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3311       if (dcnt)
3312         memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);      
3313     }
3314
3315
3316   DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3317
3318   if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3319   {
3320     DEBUG(5,("calling named_pipe\n"));
3321     outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3322                          suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3323   }
3324   else
3325   {
3326     DEBUG(3,("invalid pipe name\n"));
3327     outsize = 0;
3328   }
3329
3330
3331   if (data) free(data);
3332   if (params) free(params);
3333   if (setup) free(setup);
3334
3335   if (close_on_completion)
3336     close_cnum(cnum,vuid);
3337
3338   if (one_way)
3339     return(-1);
3340   
3341   if (outsize == 0)
3342     return(ERROR(ERRSRV,ERRnosupport));
3343
3344   return(outsize);
3345 }