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