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