add some debug info
[jra/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   pstrcpy(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,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
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   fstrcpy(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         become_root(True);
1606
1607         for (i=0;i<MAX_OPEN_FILES;i++)
1608           if (Files[i].open && Files[i].print_file)
1609             {
1610               pstring wd;
1611               GetWd(wd);
1612               unbecome_user();
1613               
1614               if (!become_user(Files[i].cnum,vuid) || 
1615                   !become_service(Files[i].cnum,True))
1616                 break;
1617               
1618               if (sys_rename(Files[i].name,name) == 0)
1619                 string_set(&Files[i].name,name);
1620               break;
1621             }
1622
1623          unbecome_root(True);
1624       }
1625     desc.errcode=NERR_Success;
1626   
1627     break;
1628   default:                      /* not implemented */
1629     return False;
1630   }
1631  
1632   SSVALS(*rparam,0,desc.errcode);
1633   SSVAL(*rparam,2,0);           /* converter word */
1634   
1635   return(True);
1636 }
1637
1638
1639 /****************************************************************************
1640   get info about the server
1641   ****************************************************************************/
1642 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1643                                   int mdrcnt,int mprcnt,
1644                                   char **rdata,char **rparam,
1645                                   int *rdata_len,int *rparam_len)
1646 {
1647   char *str1 = param+2;
1648   char *str2 = skip_string(str1,1);
1649   char *p = skip_string(str2,1);
1650   int uLevel = SVAL(p,0);
1651   char *p2;
1652   int struct_len;
1653
1654   DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1655
1656   /* check it's a supported varient */
1657   if (!prefix_ok(str1,"WrLh")) return False;
1658   switch( uLevel ) {
1659   case 0:
1660     if (strcmp(str2,"B16") != 0) return False;
1661     struct_len = 16;
1662     break;
1663   case 1:
1664     if (strcmp(str2,"B16BBDz") != 0) return False;
1665     struct_len = 26;
1666     break;
1667   case 2:
1668     if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1669         != 0) return False;
1670     struct_len = 134;
1671     break;
1672   case 3:
1673     if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1674         != 0) return False;
1675     struct_len = 144;
1676     break;
1677   case 20:
1678     if (strcmp(str2,"DN") != 0) return False;
1679     struct_len = 6;
1680     break;
1681   case 50:
1682     if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1683     struct_len = 42;
1684     break;
1685   default: return False;
1686   }
1687
1688   *rdata_len = mdrcnt;
1689   *rdata = REALLOC(*rdata,*rdata_len);
1690
1691   p = *rdata;
1692   p2 = p + struct_len;
1693   if (uLevel != 20) {
1694     StrnCpy(p,local_machine,16);
1695     strupper(p);
1696   }
1697   p += 16;
1698   if (uLevel > 0)
1699     {
1700       struct srv_info_struct *servers=NULL;
1701       int i,count;
1702       pstring comment;
1703       uint32 servertype= lp_default_server_announce();
1704
1705       pstrcpy(comment,lp_serverstring());
1706
1707       if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1708         for (i=0;i<count;i++)
1709           if (strequal(servers[i].name,local_machine))
1710       {
1711             servertype = servers[i].type;
1712             pstrcpy(comment,servers[i].comment);            
1713           }
1714       }
1715       if (servers) free(servers);
1716
1717       SCVAL(p,0,lp_major_announce_version());
1718       SCVAL(p,1,lp_minor_announce_version());
1719       SIVAL(p,2,servertype);
1720
1721       if (mdrcnt == struct_len) {
1722         SIVAL(p,6,0);
1723       } else {
1724         SIVAL(p,6,PTR_DIFF(p2,*rdata));
1725         standard_sub(cnum,comment);
1726         StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1727         p2 = skip_string(p2,1);
1728       }
1729     }
1730   if (uLevel > 1)
1731     {
1732       return False;             /* not yet implemented */
1733     }
1734
1735   *rdata_len = PTR_DIFF(p2,*rdata);
1736
1737   *rparam_len = 6;
1738   *rparam = REALLOC(*rparam,*rparam_len);
1739   SSVAL(*rparam,0,NERR_Success);
1740   SSVAL(*rparam,2,0);           /* converter word */
1741   SSVAL(*rparam,4,*rdata_len);
1742
1743   return(True);
1744 }
1745
1746
1747 /****************************************************************************
1748   get info about the server
1749   ****************************************************************************/
1750 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1751                                 int mdrcnt,int mprcnt,
1752                                 char **rdata,char **rparam,
1753                                 int *rdata_len,int *rparam_len)
1754 {
1755   char *str1 = param+2;
1756   char *str2 = skip_string(str1,1);
1757   char *p = skip_string(str2,1);
1758   char *p2;
1759   extern pstring sesssetup_user;
1760   int level = SVAL(p,0);
1761
1762   DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1763
1764   *rparam_len = 6;
1765   *rparam = REALLOC(*rparam,*rparam_len);
1766
1767   /* check it's a supported varient */
1768   if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1769     return(False);
1770
1771   *rdata_len = mdrcnt + 1024;
1772   *rdata = REALLOC(*rdata,*rdata_len);
1773
1774   SSVAL(*rparam,0,NERR_Success);
1775   SSVAL(*rparam,2,0);           /* converter word */
1776
1777   p = *rdata;
1778   p2 = p + 22;
1779
1780
1781   SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1782   strcpy(p2,local_machine);
1783   strupper(p2);
1784   p2 = skip_string(p2,1);
1785   p += 4;
1786
1787   SIVAL(p,0,PTR_DIFF(p2,*rdata));
1788   strcpy(p2,sesssetup_user);
1789   p2 = skip_string(p2,1);
1790   p += 4;
1791
1792   SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1793   strcpy(p2,myworkgroup);
1794   strupper(p2);
1795   p2 = skip_string(p2,1);
1796   p += 4;
1797
1798   SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
1799   SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
1800   p += 2;
1801
1802   SIVAL(p,0,PTR_DIFF(p2,*rdata));
1803   strcpy(p2,myworkgroup);       /* don't know.  login domain?? */
1804   p2 = skip_string(p2,1);
1805   p += 4;
1806
1807   SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1808   strcpy(p2,"");
1809   p2 = skip_string(p2,1);
1810   p += 4;
1811
1812   *rdata_len = PTR_DIFF(p2,*rdata);
1813
1814   SSVAL(*rparam,4,*rdata_len);
1815
1816   return(True);
1817 }
1818
1819 /****************************************************************************
1820   get info about a user
1821
1822     struct user_info_11 {
1823         char                usri11_name[21];  0-20 
1824         char                usri11_pad;       21 
1825         char                *usri11_comment;  22-25 
1826         char            *usri11_usr_comment;  26-29
1827         unsigned short      usri11_priv;      30-31
1828         unsigned long       usri11_auth_flags; 32-35
1829         long                usri11_password_age; 36-39
1830         char                *usri11_homedir; 40-43
1831         char            *usri11_parms; 44-47
1832         long                usri11_last_logon; 48-51
1833         long                usri11_last_logoff; 52-55
1834         unsigned short      usri11_bad_pw_count; 56-57
1835         unsigned short      usri11_num_logons; 58-59
1836         char                *usri11_logon_server; 60-63
1837         unsigned short      usri11_country_code; 64-65
1838         char            *usri11_workstations; 66-69
1839         unsigned long       usri11_max_storage; 70-73
1840         unsigned short      usri11_units_per_week; 74-75
1841         unsigned char       *usri11_logon_hours; 76-79
1842         unsigned short      usri11_code_page; 80-81
1843     };
1844
1845 where:
1846
1847   usri11_name specifies the user name for which information is retireved
1848
1849   usri11_pad aligns the next data structure element to a word boundary
1850
1851   usri11_comment is a null terminated ASCII comment
1852
1853   usri11_user_comment is a null terminated ASCII comment about the user
1854
1855   usri11_priv specifies the level of the privilege assigned to the user.
1856        The possible values are:
1857
1858 Name             Value  Description
1859 USER_PRIV_GUEST  0      Guest privilege
1860 USER_PRIV_USER   1      User privilege
1861 USER_PRV_ADMIN   2      Administrator privilege
1862
1863   usri11_auth_flags specifies the account operator privileges. The
1864        possible values are:
1865
1866 Name            Value   Description
1867 AF_OP_PRINT     0       Print operator
1868
1869
1870 Leach, Naik                                        [Page 28]\r\f
1871
1872
1873 INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
1874
1875
1876 AF_OP_COMM      1       Communications operator
1877 AF_OP_SERVER    2       Server operator
1878 AF_OP_ACCOUNTS  3       Accounts operator
1879
1880
1881   usri11_password_age specifies how many seconds have elapsed since the
1882        password was last changed.
1883
1884   usri11_home_dir points to a null terminated ASCII string that contains
1885        the path name of the user's home directory.
1886
1887   usri11_parms points to a null terminated ASCII string that is set
1888        aside for use by applications.
1889
1890   usri11_last_logon specifies the time when the user last logged on.
1891        This value is stored as the number of seconds elapsed since
1892        00:00:00, January 1, 1970.
1893
1894   usri11_last_logoff specifies the time when the user last logged off.
1895        This value is stored as the number of seconds elapsed since
1896        00:00:00, January 1, 1970. A value of 0 means the last logoff
1897        time is unknown.
1898
1899   usri11_bad_pw_count specifies the number of incorrect passwords
1900        entered since the last successful logon.
1901
1902   usri11_log1_num_logons specifies the number of times this user has
1903        logged on. A value of -1 means the number of logons is unknown.
1904
1905   usri11_logon_server points to a null terminated ASCII string that
1906        contains the name of the server to which logon requests are sent.
1907        A null string indicates logon requests should be sent to the
1908        domain controller.
1909
1910   usri11_country_code specifies the country code for the user's language
1911        of choice.
1912
1913   usri11_workstations points to a null terminated ASCII string that
1914        contains the names of workstations the user may log on from.
1915        There may be up to 8 workstations, with the names separated by
1916        commas. A null strings indicates there are no restrictions.
1917
1918   usri11_max_storage specifies the maximum amount of disk space the user
1919        can occupy. A value of 0xffffffff indicates there are no
1920        restrictions.
1921
1922   usri11_units_per_week specifies the equal number of time units into
1923        which a week is divided. This value must be equal to 168.
1924
1925   usri11_logon_hours points to a 21 byte (168 bits) string that
1926        specifies the time during which the user can log on. Each bit
1927        represents one unique hour in a week. The first bit (bit 0, word
1928        0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
1929
1930
1931
1932 Leach, Naik                                        [Page 29]\r\f
1933
1934
1935 INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
1936
1937
1938        Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
1939        are no restrictions.
1940
1941   usri11_code_page specifies the code page for the user's language of
1942        choice
1943
1944 All of the pointers in this data structure need to be treated
1945 specially. The  pointer is a 32 bit pointer. The higher 16 bits need
1946 to be ignored. The converter word returned in the parameters section
1947 needs to be subtracted from the lower 16 bits to calculate an offset
1948 into the return buffer where this ASCII string resides.
1949
1950 There is no auxiliary data in the response.
1951
1952   ****************************************************************************/
1953
1954 #define usri11_name           0 
1955 #define usri11_pad            21
1956 #define usri11_comment        22
1957 #define usri11_usr_comment    26
1958 #define usri11_full_name      30
1959 #define usri11_priv           34
1960 #define usri11_auth_flags     36
1961 #define usri11_password_age   40
1962 #define usri11_homedir        44
1963 #define usri11_parms          48
1964 #define usri11_last_logon     52
1965 #define usri11_last_logoff    56
1966 #define usri11_bad_pw_count   60
1967 #define usri11_num_logons     62
1968 #define usri11_logon_server   64
1969 #define usri11_country_code   68
1970 #define usri11_workstations   70
1971 #define usri11_max_storage    74
1972 #define usri11_units_per_week 78
1973 #define usri11_logon_hours    80
1974 #define usri11_code_page      84
1975 #define usri11_end            86
1976
1977 #define USER_PRIV_GUEST 0
1978 #define USER_PRIV_USER 1
1979 #define USER_PRIV_ADMIN 2
1980
1981 #define AF_OP_PRINT     0 
1982 #define AF_OP_COMM      1
1983 #define AF_OP_SERVER    2
1984 #define AF_OP_ACCOUNTS  3
1985
1986
1987 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
1988                                 int mdrcnt,int mprcnt,
1989                                 char **rdata,char **rparam,
1990                                 int *rdata_len,int *rparam_len)
1991 {
1992         char *str1 = param+2;
1993         char *str2 = skip_string(str1,1);
1994         char *UserName = skip_string(str2,1);
1995         char *p = skip_string(UserName,1);
1996         int uLevel = SVAL(p,0);
1997         char *p2;
1998
1999     /* get NIS home of a previously validated user - simeon */
2000     user_struct *vuser = get_valid_user_struct(vuid);
2001     DEBUG(3,("  Username of UID %d is %s\n", vuser->uid, vuser->name));
2002
2003     *rparam_len = 6;
2004     *rparam = REALLOC(*rparam,*rparam_len);
2005
2006     DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2007   
2008         /* check it's a supported variant */
2009         if (strcmp(str1,"zWrLh") != 0) return False;
2010         switch( uLevel )
2011         {
2012                 case 0: p2 = "B21"; break;
2013                 case 1: p2 = "B21BB16DWzzWz"; break;
2014                 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2015                 case 10: p2 = "B21Bzzz"; break;
2016                 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2017                 default: return False;
2018         }
2019
2020         if (strcmp(p2,str2) != 0) return False;
2021
2022         *rdata_len = mdrcnt + 1024;
2023         *rdata = REALLOC(*rdata,*rdata_len);
2024
2025         SSVAL(*rparam,0,NERR_Success);
2026         SSVAL(*rparam,2,0);             /* converter word */
2027
2028         p = *rdata;
2029         p2 = p + usri11_end;
2030
2031         memset(p,0,21); 
2032         fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2033
2034         if (uLevel > 0)
2035         {
2036                 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2037                 *p2 = 0;
2038         }
2039         if (uLevel >= 10)
2040         {
2041                 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2042                 strcpy(p2,"Comment");
2043                 p2 = skip_string(p2,1);
2044
2045                 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2046                 strcpy(p2,"UserComment");
2047                 p2 = skip_string(p2,1);
2048
2049                 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2050                 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2051                 strcpy(p2,vuser->real_name);    /* simeon */
2052                 p2 = skip_string(p2,1);
2053         }
2054
2055         if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2056         {         
2057                 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); 
2058                 SIVAL(p,usri11_auth_flags,AF_OP_PRINT);         /* auth flags */
2059                 SIVALS(p,usri11_password_age,0xffffffff);               /* password age */
2060                 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2061                 strcpy(p2, lp_logon_path());
2062                 p2 = skip_string(p2,1);
2063                 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2064                 strcpy(p2,"");
2065                 p2 = skip_string(p2,1);
2066                 SIVAL(p,usri11_last_logon,0);           /* last logon */
2067                 SIVAL(p,usri11_last_logoff,0);          /* last logoff */
2068                 SSVALS(p,usri11_bad_pw_count,0xffffffff);               /* bad pw counts */
2069                 SSVALS(p,usri11_num_logons,0xffffffff);         /* num logons */
2070                 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2071                 strcpy(p2,"\\\\*");
2072                 p2 = skip_string(p2,1);
2073                 SSVAL(p,usri11_country_code,0);         /* country code */
2074
2075                 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2076                 strcpy(p2,"");
2077                 p2 = skip_string(p2,1);
2078
2079                 SIVALS(p,usri11_max_storage,0xffffffff);                /* max storage */
2080                 SSVAL(p,usri11_units_per_week,168);             /* units per week */
2081                 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2082
2083                 /* a simple way to get logon hours at all times. */
2084                 memset(p2,0xff,21);
2085                 SCVAL(p2,21,0);           /* fix zero termination */
2086                 p2 = skip_string(p2,1);
2087
2088                 SSVAL(p,usri11_code_page,0);            /* code page */
2089         }
2090         if (uLevel == 1 || uLevel == 2)
2091         {
2092                 memset(p+22,' ',16);    /* password */
2093                 SIVALS(p,38,-1);                /* password age */
2094                 SSVAL(p,42,
2095                 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2096                 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2097                 strcpy(p2,lp_logon_path());
2098                 p2 = skip_string(p2,1);
2099                 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2100                 *p2++ = 0;
2101                 SSVAL(p,52,0);          /* flags */
2102                 SIVAL(p,54,0);          /* script_path */
2103                 if (uLevel == 2)
2104                 {
2105                         SIVAL(p,60,0);          /* auth_flags */
2106                         SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2107                         strcpy(p2,vuser->real_name);    /* simeon */
2108                         p2 = skip_string(p2,1);
2109                         SIVAL(p,68,0);          /* urs_comment */
2110                         SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2111                         strcpy(p2,"");
2112                         p2 = skip_string(p2,1);
2113                         SIVAL(p,76,0);          /* workstations */
2114                         SIVAL(p,80,0);          /* last_logon */
2115                         SIVAL(p,84,0);          /* last_logoff */
2116                         SIVALS(p,88,-1);                /* acct_expires */
2117                         SIVALS(p,92,-1);                /* max_storage */
2118                         SSVAL(p,96,168);        /* units_per_week */
2119                         SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2120                         memset(p2,-1,21);
2121                         p2 += 21;
2122                         SSVALS(p,102,-1);       /* bad_pw_count */
2123                         SSVALS(p,104,-1);       /* num_logons */
2124                         SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2125                         strcpy(p2,"\\\\%L");
2126                         standard_sub_basic(p2);
2127                         p2 = skip_string(p2,1);
2128                         SSVAL(p,110,49);        /* country_code */
2129                         SSVAL(p,112,860);       /* code page */
2130                 }
2131         }
2132
2133         *rdata_len = PTR_DIFF(p2,*rdata);
2134
2135         SSVAL(*rparam,4,*rdata_len);    /* is this right?? */
2136
2137         return(True);
2138 }
2139
2140 /*******************************************************************
2141   get groups that a user is a member of
2142   ******************************************************************/
2143 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2144                                  int mdrcnt,int mprcnt,
2145                                  char **rdata,char **rparam,
2146                                  int *rdata_len,int *rparam_len)
2147 {
2148   char *str1 = param+2;
2149   char *str2 = skip_string(str1,1);
2150   char *UserName = skip_string(str2,1);
2151   char *p = skip_string(UserName,1);
2152   int uLevel = SVAL(p,0);
2153   char *p2;
2154   int count=0;
2155
2156   *rparam_len = 8;
2157   *rparam = REALLOC(*rparam,*rparam_len);
2158
2159   /* check it's a supported varient */
2160   if (strcmp(str1,"zWrLeh") != 0) return False;
2161   switch( uLevel ) {
2162   case 0: p2 = "B21"; break;
2163   default: return False;
2164   }
2165   if (strcmp(p2,str2) != 0) return False;
2166
2167   *rdata_len = mdrcnt + 1024;
2168   *rdata = REALLOC(*rdata,*rdata_len);
2169
2170   SSVAL(*rparam,0,NERR_Success);
2171   SSVAL(*rparam,2,0);           /* converter word */
2172
2173   p = *rdata;
2174
2175   /* XXXX we need a real SAM database some day */
2176   strcpy(p,"Users"); p += 21; count++;
2177   strcpy(p,"Domain Users"); p += 21; count++;
2178   strcpy(p,"Guests"); p += 21; count++;
2179   strcpy(p,"Domain Guests"); p += 21; count++;
2180
2181   *rdata_len = PTR_DIFF(p,*rdata);
2182
2183   SSVAL(*rparam,4,count);       /* is this right?? */
2184   SSVAL(*rparam,6,count);       /* is this right?? */
2185
2186   return(True);
2187 }
2188
2189
2190 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2191                                 int mdrcnt,int mprcnt,
2192                                 char **rdata,char **rparam,
2193                                 int *rdata_len,int *rparam_len)
2194 {
2195   char *str1 = param+2;
2196   char *str2 = skip_string(str1,1);
2197   char *p = skip_string(str2,1);
2198   int uLevel;
2199   struct pack_desc desc;
2200   char* name;
2201   char* logon_script;
2202
2203   uLevel = SVAL(p,0);
2204   name = p + 2;
2205
2206   bzero(&desc,sizeof(desc));
2207
2208   DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2209
2210   /* check it's a supported varient */
2211   if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2212   if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2213   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2214   desc.base = *rdata;
2215   desc.buflen = mdrcnt;
2216   desc.subformat = NULL;
2217   desc.format = str2;
2218   
2219   if (init_package(&desc,1,0))
2220   {
2221     PACKI(&desc,"W",0);         /* code */
2222     PACKS(&desc,"B21",name);    /* eff. name */
2223     PACKS(&desc,"B","");                /* pad */
2224     PACKI(&desc,"W",
2225           Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2226     PACKI(&desc,"D",0);         /* auth flags XXX */
2227     PACKI(&desc,"W",0);         /* num logons */
2228     PACKI(&desc,"W",0);         /* bad pw count */
2229     PACKI(&desc,"D",0);         /* last logon */
2230     PACKI(&desc,"D",-1);                /* last logoff */
2231     PACKI(&desc,"D",-1);                /* logoff time */
2232     PACKI(&desc,"D",-1);                /* kickoff time */
2233     PACKI(&desc,"D",0);         /* password age */
2234     PACKI(&desc,"D",0);         /* password can change */
2235     PACKI(&desc,"D",-1);                /* password must change */
2236     {
2237       fstring mypath;
2238       strcpy(mypath,"\\\\");
2239       strcat(mypath,local_machine);
2240       strupper(mypath);
2241       PACKS(&desc,"z",mypath); /* computer */
2242     }
2243     PACKS(&desc,"z",myworkgroup);/* domain */
2244
2245 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2246 /* made sure all macros are fully substituted and available */
2247     logon_script = lp_logon_script();
2248     standard_sub( cnum, logon_script );
2249     PACKS(&desc,"z", logon_script);             /* script path */
2250 /* End of JHT mods */
2251
2252     PACKI(&desc,"D",0x00000000);                /* reserved */
2253   }
2254
2255   *rdata_len = desc.usedlen;
2256   *rparam_len = 6;
2257   *rparam = REALLOC(*rparam,*rparam_len);
2258   SSVALS(*rparam,0,desc.errcode);
2259   SSVAL(*rparam,2,0);
2260   SSVAL(*rparam,4,desc.neededlen);
2261
2262   DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2263   return(True);
2264 }
2265
2266
2267 /****************************************************************************
2268   api_WAccessGetUserPerms
2269   ****************************************************************************/
2270 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2271                                     int mdrcnt,int mprcnt,
2272                                     char **rdata,char **rparam,
2273                                     int *rdata_len,int *rparam_len)
2274 {
2275   char *str1 = param+2;
2276   char *str2 = skip_string(str1,1);
2277   char *user = skip_string(str2,1);
2278   char *resource = skip_string(user,1);
2279
2280   DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2281
2282   /* check it's a supported varient */
2283   if (strcmp(str1,"zzh") != 0) return False;
2284   if (strcmp(str2,"") != 0) return False;
2285
2286   *rparam_len = 6;
2287   *rparam = REALLOC(*rparam,*rparam_len);
2288   SSVALS(*rparam,0,0);          /* errorcode */
2289   SSVAL(*rparam,2,0);           /* converter word */
2290   SSVAL(*rparam,4,0x7f);        /* permission flags */
2291
2292   return(True);
2293 }
2294
2295 /****************************************************************************
2296   api_WPrintJobEnumerate
2297   ****************************************************************************/
2298 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2299                                  int mdrcnt,int mprcnt,
2300                                  char **rdata,char **rparam,
2301                                  int *rdata_len,int *rparam_len)
2302 {
2303   char *str1 = param+2;
2304   char *str2 = skip_string(str1,1);
2305   char *p = skip_string(str2,1);
2306   int uLevel,cbBuf;
2307   int count;
2308   int i;
2309   int snum;
2310   int job;
2311   struct pack_desc desc;
2312   print_queue_struct *queue=NULL;
2313   print_status_struct status;
2314
2315   uLevel = SVAL(p,2);
2316   cbBuf = SVAL(p,4);
2317
2318   bzero(&desc,sizeof(desc));
2319   bzero(&status,sizeof(status));
2320
2321   DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2322
2323   /* check it's a supported varient */
2324   if (strcmp(str1,"WWrLh") != 0) return False;
2325   if (!check_printjob_info(&desc,uLevel,str2)) return False;
2326
2327   printjob_decode(SVAL(p,0), &snum, &job);
2328
2329   if (snum < 0 || !VALID_SNUM(snum)) return(False);
2330
2331   count = get_printqueue(snum,cnum,&queue,&status);
2332   for (i = 0; i < count; i++) {
2333     if ((queue[i].job & 0xFF) == job) break;
2334   }
2335   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2336   desc.base = *rdata;
2337   desc.buflen = mdrcnt;
2338
2339   if (init_package(&desc,1,0)) {
2340     if (i < count) {
2341       fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2342       *rdata_len = desc.usedlen;
2343     }
2344     else {
2345       desc.errcode = NERR_JobNotFound;
2346       *rdata_len = 0;
2347     }
2348   }
2349
2350   *rparam_len = 6;
2351   *rparam = REALLOC(*rparam,*rparam_len);
2352   SSVALS(*rparam,0,desc.errcode);
2353   SSVAL(*rparam,2,0);
2354   SSVAL(*rparam,4,desc.neededlen);
2355
2356   if (queue) free(queue);
2357
2358   DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2359   return(True);
2360 }
2361
2362 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2363                                    int mdrcnt,int mprcnt,
2364                                    char **rdata,char **rparam,
2365                                    int *rdata_len,int *rparam_len)
2366 {
2367   char *str1 = param+2;
2368   char *str2 = skip_string(str1,1);
2369   char *p = skip_string(str2,1);
2370   char* name = p;
2371   int uLevel,cbBuf;
2372   int count;
2373   int i, succnt=0;
2374   int snum;
2375   struct pack_desc desc;
2376   print_queue_struct *queue=NULL;
2377   print_status_struct status;
2378
2379   bzero(&desc,sizeof(desc));
2380   bzero(&status,sizeof(status));
2381
2382   p = skip_string(p,1);
2383   uLevel = SVAL(p,0);
2384   cbBuf = SVAL(p,2);
2385
2386   DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2387
2388   /* check it's a supported varient */
2389   if (strcmp(str1,"zWrLeh") != 0) return False;
2390   if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2391   if (!check_printjob_info(&desc,uLevel,str2)) return False;
2392
2393   snum = lp_servicenumber(name);
2394   if (snum < 0 && pcap_printername_ok(name,NULL)) {
2395     int pnum = lp_servicenumber(PRINTERS_NAME);
2396     if (pnum >= 0) {
2397       lp_add_printer(name,pnum);
2398       snum = lp_servicenumber(name);
2399     }
2400   }
2401
2402   if (snum < 0 || !VALID_SNUM(snum)) return(False);
2403
2404   count = get_printqueue(snum,cnum,&queue,&status);
2405   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2406   desc.base = *rdata;
2407   desc.buflen = mdrcnt;
2408
2409   if (init_package(&desc,count,0)) {
2410     succnt = 0;
2411     for (i = 0; i < count; i++) {
2412       fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2413       if (desc.errcode == NERR_Success) succnt = i+1;
2414     }
2415   }
2416
2417   *rdata_len = desc.usedlen;
2418
2419   *rparam_len = 8;
2420   *rparam = REALLOC(*rparam,*rparam_len);
2421   SSVALS(*rparam,0,desc.errcode);
2422   SSVAL(*rparam,2,0);
2423   SSVAL(*rparam,4,succnt);
2424   SSVAL(*rparam,6,count);
2425
2426   if (queue) free(queue);
2427
2428   DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2429   return(True);
2430 }
2431
2432 static int check_printdest_info(struct pack_desc* desc,
2433                                 int uLevel, char* id)
2434 {
2435   desc->subformat = NULL;
2436   switch( uLevel ) {
2437   case 0: desc->format = "B9"; break;
2438   case 1: desc->format = "B9B21WWzW"; break;
2439   case 2: desc->format = "z"; break;
2440   case 3: desc->format = "zzzWWzzzWW"; break;
2441   default: return False;
2442   }
2443   if (strcmp(desc->format,id) != 0) return False;
2444   return True;
2445 }
2446
2447 static void fill_printdest_info(int cnum, int snum, int uLevel,
2448                                 struct pack_desc* desc)
2449 {
2450   char buf[100];
2451   strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2452   buf[sizeof(buf)-1] = 0;
2453   strupper(buf);
2454   if (uLevel <= 1) {
2455     PACKS(desc,"B9",buf);       /* szName */
2456     if (uLevel == 1) {
2457       PACKS(desc,"B21","");     /* szUserName */
2458       PACKI(desc,"W",0);                /* uJobId */
2459       PACKI(desc,"W",0);                /* fsStatus */
2460       PACKS(desc,"z","");       /* pszStatus */
2461       PACKI(desc,"W",0);                /* time */
2462     }
2463   }
2464   if (uLevel == 2 || uLevel == 3) {
2465     PACKS(desc,"z",buf);                /* pszPrinterName */
2466     if (uLevel == 3) {
2467       PACKS(desc,"z","");       /* pszUserName */
2468       PACKS(desc,"z","");       /* pszLogAddr */
2469       PACKI(desc,"W",0);                /* uJobId */
2470       PACKI(desc,"W",0);                /* fsStatus */
2471       PACKS(desc,"z","");       /* pszStatus */
2472       PACKS(desc,"z","");       /* pszComment */
2473       PACKS(desc,"z","NULL"); /* pszDrivers */
2474       PACKI(desc,"W",0);                /* time */
2475       PACKI(desc,"W",0);                /* pad1 */
2476     }
2477   }
2478 }
2479
2480 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2481                                   int mdrcnt,int mprcnt,
2482                                   char **rdata,char **rparam,
2483                                   int *rdata_len,int *rparam_len)
2484 {
2485   char *str1 = param+2;
2486   char *str2 = skip_string(str1,1);
2487   char *p = skip_string(str2,1);
2488   char* PrinterName = p;
2489   int uLevel,cbBuf;
2490   struct pack_desc desc;
2491   int snum;
2492
2493   bzero(&desc,sizeof(desc));
2494
2495   p = skip_string(p,1);
2496   uLevel = SVAL(p,0);
2497   cbBuf = SVAL(p,2);
2498
2499   DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2500
2501   /* check it's a supported varient */
2502   if (strcmp(str1,"zWrLh") != 0) return False;
2503   if (!check_printdest_info(&desc,uLevel,str2)) return False;
2504
2505   snum = lp_servicenumber(PrinterName);
2506   if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2507     int pnum = lp_servicenumber(PRINTERS_NAME);
2508     if (pnum >= 0) {
2509       lp_add_printer(PrinterName,pnum);
2510       snum = lp_servicenumber(PrinterName);
2511     }
2512   }
2513
2514   if (snum < 0) {
2515     *rdata_len = 0;
2516     desc.errcode = NERR_DestNotFound;
2517     desc.neededlen = 0;
2518   }
2519   else {
2520     if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2521     desc.base = *rdata;
2522     desc.buflen = mdrcnt;
2523     if (init_package(&desc,1,0)) {
2524       fill_printdest_info(cnum,snum,uLevel,&desc);
2525     }
2526     *rdata_len = desc.usedlen;
2527   }
2528
2529   *rparam_len = 6;
2530   *rparam = REALLOC(*rparam,*rparam_len);
2531   SSVALS(*rparam,0,desc.errcode);
2532   SSVAL(*rparam,2,0);
2533   SSVAL(*rparam,4,desc.neededlen);
2534
2535   DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2536   return(True);
2537 }
2538
2539 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2540                                int mdrcnt,int mprcnt,
2541                                char **rdata,char **rparam,
2542                                int *rdata_len,int *rparam_len)
2543 {
2544   char *str1 = param+2;
2545   char *str2 = skip_string(str1,1);
2546   char *p = skip_string(str2,1);
2547   int uLevel,cbBuf;
2548   int queuecnt;
2549   int i, n, succnt=0;
2550   struct pack_desc desc;
2551   int services = lp_numservices();
2552
2553   bzero(&desc,sizeof(desc));
2554
2555   uLevel = SVAL(p,0);
2556   cbBuf = SVAL(p,2);
2557
2558   DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2559
2560   /* check it's a supported varient */
2561   if (strcmp(str1,"WrLeh") != 0) return False;
2562   if (!check_printdest_info(&desc,uLevel,str2)) return False;
2563
2564   queuecnt = 0;
2565   for (i = 0; i < services; i++)
2566     if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2567       queuecnt++;
2568
2569   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2570   desc.base = *rdata;
2571   desc.buflen = mdrcnt;
2572   if (init_package(&desc,queuecnt,0)) {    
2573     succnt = 0;
2574     n = 0;
2575     for (i = 0; i < services; i++) {
2576       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2577         fill_printdest_info(cnum,i,uLevel,&desc);
2578         n++;
2579         if (desc.errcode == NERR_Success) succnt = n;
2580       }
2581     }
2582   }
2583
2584   *rdata_len = desc.usedlen;
2585
2586   *rparam_len = 8;
2587   *rparam = REALLOC(*rparam,*rparam_len);
2588   SSVALS(*rparam,0,desc.errcode);
2589   SSVAL(*rparam,2,0);
2590   SSVAL(*rparam,4,succnt);
2591   SSVAL(*rparam,6,queuecnt);
2592
2593   DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2594   return(True);
2595 }
2596
2597 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2598                                  int mdrcnt,int mprcnt,
2599                                  char **rdata,char **rparam,
2600                                  int *rdata_len,int *rparam_len)
2601 {
2602   char *str1 = param+2;
2603   char *str2 = skip_string(str1,1);
2604   char *p = skip_string(str2,1);
2605   int uLevel,cbBuf;
2606   int succnt;
2607   struct pack_desc desc;
2608
2609   bzero(&desc,sizeof(desc));
2610
2611   uLevel = SVAL(p,0);
2612   cbBuf = SVAL(p,2);
2613
2614   DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2615
2616   /* check it's a supported varient */
2617   if (strcmp(str1,"WrLeh") != 0) return False;
2618   if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2619
2620   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2621   desc.base = *rdata;
2622   desc.buflen = mdrcnt;
2623   if (init_package(&desc,1,0)) {
2624     PACKS(&desc,"B41","NULL");
2625   }
2626
2627   succnt = (desc.errcode == NERR_Success ? 1 : 0);
2628
2629   *rdata_len = desc.usedlen;
2630
2631   *rparam_len = 8;
2632   *rparam = REALLOC(*rparam,*rparam_len);
2633   SSVALS(*rparam,0,desc.errcode);
2634   SSVAL(*rparam,2,0);
2635   SSVAL(*rparam,4,succnt);
2636   SSVAL(*rparam,6,1);
2637
2638   DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2639   return(True);
2640 }
2641
2642 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2643                                 int mdrcnt,int mprcnt,
2644                                 char **rdata,char **rparam,
2645                                 int *rdata_len,int *rparam_len)
2646 {
2647   char *str1 = param+2;
2648   char *str2 = skip_string(str1,1);
2649   char *p = skip_string(str2,1);
2650   int uLevel,cbBuf;
2651   int succnt;
2652   struct pack_desc desc;
2653
2654   bzero(&desc,sizeof(desc));
2655
2656   uLevel = SVAL(p,0);
2657   cbBuf = SVAL(p,2);
2658
2659   DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2660
2661   /* check it's a supported varient */
2662   if (strcmp(str1,"WrLeh") != 0) return False;
2663   if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2664
2665   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2666   desc.base = *rdata;
2667   desc.buflen = mdrcnt;
2668   desc.format = str2;
2669   if (init_package(&desc,1,0)) {
2670     PACKS(&desc,"B13","lpd");
2671   }
2672
2673   succnt = (desc.errcode == NERR_Success ? 1 : 0);
2674
2675   *rdata_len = desc.usedlen;
2676
2677   *rparam_len = 8;
2678   *rparam = REALLOC(*rparam,*rparam_len);
2679   SSVALS(*rparam,0,desc.errcode);
2680   SSVAL(*rparam,2,0);
2681   SSVAL(*rparam,4,succnt);
2682   SSVAL(*rparam,6,1);
2683
2684   DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2685   return(True);
2686 }
2687
2688 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2689                                int mdrcnt,int mprcnt,
2690                                char **rdata,char **rparam,
2691                                int *rdata_len,int *rparam_len)
2692 {
2693   char *str1 = param+2;
2694   char *str2 = skip_string(str1,1);
2695   char *p = skip_string(str2,1);
2696   int uLevel,cbBuf;
2697   int succnt;
2698   struct pack_desc desc;
2699
2700   bzero(&desc,sizeof(desc));
2701
2702   uLevel = SVAL(p,0);
2703   cbBuf = SVAL(p,2);
2704
2705   DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2706
2707   /* check it's a supported varient */
2708   if (strcmp(str1,"WrLeh") != 0) return False;
2709   if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2710
2711   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2712   bzero(&desc,sizeof(desc));
2713   desc.base = *rdata;
2714   desc.buflen = mdrcnt;
2715   desc.format = str2;
2716   if (init_package(&desc,1,0)) {
2717     PACKS(&desc,"B13","lp0");
2718   }
2719
2720   succnt = (desc.errcode == NERR_Success ? 1 : 0);
2721
2722   *rdata_len = desc.usedlen;
2723
2724   *rparam_len = 8;
2725   *rparam = REALLOC(*rparam,*rparam_len);
2726   SSVALS(*rparam,0,desc.errcode);
2727   SSVAL(*rparam,2,0);
2728   SSVAL(*rparam,4,succnt);
2729   SSVAL(*rparam,6,1);
2730
2731   DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2732   return(True);
2733 }
2734
2735
2736 struct
2737 {
2738   char * name;
2739   char * pipename;
2740   int subcommand;
2741   BOOL (*fn) ();
2742 } api_fd_commands [] =
2743   {
2744 #ifdef NTDOMAIN
2745     { "SetNmdPpHndState",       "lsarpc",       1,      api_LsarpcSNPHS },
2746     { "SetNmdPpHndState",       "srvsvc",       1,      api_LsarpcSNPHS },
2747     { "SetNmdPpHndState",       "NETLOGON",     1,      api_LsarpcSNPHS },
2748     { "TransactNmPipe", "lsarpc",       0x26,   api_ntLsarpcTNP },
2749     { "TransactNmPipe", "srvsvc",       0x26,   api_srvsvcTNP },
2750     { "TransactNmPipe", "NETLOGON",     0x26,   api_netlogrpcTNP },
2751 #else
2752     { "SetNmdPpHndState",       "lsarpc",       1,      api_LsarpcSNPHS },
2753     { "TransactNmPipe"  ,       "lsarpc",       0x26,   api_LsarpcTNP },
2754 #endif
2755     { NULL,             NULL,           -1,     (BOOL (*)())api_Unsupported }
2756   };
2757
2758 /****************************************************************************
2759   handle remote api calls delivered to a named pipe already opened.
2760   ****************************************************************************/
2761 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2762                         uint16 *setup,char *data,char *params,
2763                         int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2764 {
2765   char *rdata = NULL;
2766   char *rparam = NULL;
2767   int rdata_len = 0;
2768   int rparam_len = 0;
2769   BOOL reply=False;
2770   int i;
2771   int fd;
2772   int subcommand;
2773   
2774   /* First find out the name of this file. */
2775   if (suwcnt != 2)
2776     {
2777       DEBUG(0,("Unexpected named pipe transaction.\n"));
2778       return(-1);
2779     }
2780   
2781   /* Get the file handle and hence the file name. */
2782   fd = setup[1];
2783   subcommand = setup[0];
2784   
2785   DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2786   DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
2787            tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
2788   
2789   for (i=0;api_fd_commands[i].name;i++)
2790   {
2791     if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2792             api_fd_commands[i].subcommand == subcommand &&
2793             api_fd_commands[i].fn)
2794     {
2795           DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2796           break;
2797     }
2798   }
2799   
2800   rdata  = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024);
2801   rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2802   
2803   DEBUG(10,("calling api_fd_command\n"));
2804
2805   reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2806                                 &rdata,&rparam,&rdata_len,&rparam_len);
2807   
2808   DEBUG(10,("called api_fd_command\n"));
2809
2810   if (rdata_len > mdrcnt || rparam_len > mprcnt)
2811   {
2812     reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2813                            &rdata,&rparam,&rdata_len,&rparam_len);
2814   }
2815   
2816   
2817   /* if we get False back then it's actually unsupported */
2818   if (!reply)
2819     api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2820                     &rdata,&rparam,&rdata_len,&rparam_len);
2821   
2822   /* now send the reply */
2823   send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2824   
2825   if (rdata)
2826     free(rdata);
2827   if (rparam)
2828     free(rparam);
2829   
2830   return(-1);
2831 }
2832
2833
2834
2835 /****************************************************************************
2836   the buffer was too small
2837   ****************************************************************************/
2838 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
2839                          int mdrcnt,int mprcnt,
2840                          char **rdata,char **rparam,
2841                          int *rdata_len,int *rparam_len)
2842 {
2843   *rparam_len = MIN(*rparam_len,mprcnt);
2844   *rparam = REALLOC(*rparam,*rparam_len);
2845
2846   *rdata_len = 0;
2847
2848   SSVAL(*rparam,0,NERR_BufTooSmall);
2849
2850   DEBUG(3,("Supplied buffer too small in API command\n"));
2851
2852   return(True);
2853 }
2854
2855
2856 /****************************************************************************
2857   the request is not supported
2858   ****************************************************************************/
2859 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
2860                             int mdrcnt,int mprcnt,
2861                             char **rdata,char **rparam,
2862                             int *rdata_len,int *rparam_len)
2863 {
2864   *rparam_len = 4;
2865   *rparam = REALLOC(*rparam,*rparam_len);
2866
2867   *rdata_len = 0;
2868
2869   SSVAL(*rparam,0,NERR_notsupported);
2870   SSVAL(*rparam,2,0);           /* converter word */
2871
2872   DEBUG(3,("Unsupported API command\n"));
2873
2874   return(True);
2875 }
2876
2877
2878
2879
2880 struct
2881 {
2882   char *name;
2883   int id;
2884   BOOL (*fn)();
2885   int flags;
2886 } api_commands[] = {
2887   {"RNetShareEnum",     0,      (BOOL (*)())api_RNetShareEnum,0},
2888   {"RNetShareGetInfo",  1,      (BOOL (*)())api_RNetShareGetInfo,0},
2889   {"RNetServerGetInfo", 13,     (BOOL (*)())api_RNetServerGetInfo,0},
2890   {"RNetUserGetInfo",   56,     (BOOL (*)())api_RNetUserGetInfo,0},
2891   {"NetUserGetGroups",  59,     (BOOL (*)())api_NetUserGetGroups,0},
2892   {"NetWkstaGetInfo",   63,     (BOOL (*)())api_NetWkstaGetInfo,0},
2893   {"DosPrintQEnum",     69,     (BOOL (*)())api_DosPrintQEnum,0},
2894   {"DosPrintQGetInfo",  70,     (BOOL (*)())api_DosPrintQGetInfo,0},
2895   {"WPrintJobEnumerate",76,     (BOOL (*)())api_WPrintJobEnumerate,0},
2896   {"WPrintJobGetInfo",  77,     (BOOL (*)())api_WPrintJobGetInfo,0},
2897   {"RDosPrintJobDel",   81,     (BOOL (*)())api_RDosPrintJobDel,0},
2898   {"RDosPrintJobPause", 82,     (BOOL (*)())api_RDosPrintJobDel,0},
2899   {"RDosPrintJobResume",83,     (BOOL (*)())api_RDosPrintJobDel,0},
2900   {"WPrintDestEnum",    84,     (BOOL (*)())api_WPrintDestEnum,0},
2901   {"WPrintDestGetInfo", 85,     (BOOL (*)())api_WPrintDestGetInfo,0},
2902   {"NetRemoteTOD",      91,     (BOOL (*)())api_NetRemoteTOD,0},
2903   {"WPrintQueuePurge",  103,    (BOOL (*)())api_WPrintQueuePurge,0},
2904   {"NetServerEnum",     104,    (BOOL (*)())api_RNetServerEnum,0},
2905   {"WAccessGetUserPerms",105,   (BOOL (*)())api_WAccessGetUserPerms,0},
2906   {"SetUserPassword",   115,    (BOOL (*)())api_SetUserPassword,0},
2907   {"WWkstaUserLogon",   132,    (BOOL (*)())api_WWkstaUserLogon,0},
2908   {"PrintJobInfo",      147,    (BOOL (*)())api_PrintJobInfo,0},
2909   {"WPrintDriverEnum",  205,    (BOOL (*)())api_WPrintDriverEnum,0},
2910   {"WPrintQProcEnum",   206,    (BOOL (*)())api_WPrintQProcEnum,0},
2911   {"WPrintPortEnum",    207,    (BOOL (*)())api_WPrintPortEnum,0},
2912   {NULL,                -1,     (BOOL (*)())api_Unsupported,0}};
2913
2914
2915 /****************************************************************************
2916   handle remote api calls
2917   ****************************************************************************/
2918 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
2919                      int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2920 {
2921   int api_command = SVAL(params,0);
2922   char *rdata = NULL;
2923   char *rparam = NULL;
2924   int rdata_len = 0;
2925   int rparam_len = 0;
2926   BOOL reply=False;
2927   int i;
2928
2929   DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2930            api_command,params+2,skip_string(params+2,1),
2931            tdscnt,tpscnt,mdrcnt,mprcnt));
2932
2933   for (i=0;api_commands[i].name;i++)
2934     if (api_commands[i].id == api_command && api_commands[i].fn)
2935       {
2936         DEBUG(3,("Doing %s\n",api_commands[i].name));
2937         break;
2938       }
2939
2940   rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2941   rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2942
2943   reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2944                              &rdata,&rparam,&rdata_len,&rparam_len);
2945
2946
2947   if (rdata_len > mdrcnt ||
2948       rparam_len > mprcnt)
2949     {
2950       reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2951                            &rdata,&rparam,&rdata_len,&rparam_len);
2952     }
2953             
2954
2955   /* if we get False back then it's actually unsupported */
2956   if (!reply)
2957     api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2958                     &rdata,&rparam,&rdata_len,&rparam_len);
2959
2960       
2961
2962   /* now send the reply */
2963   send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2964
2965   if (rdata)
2966     free(rdata);
2967   if (rparam)
2968     free(rparam);
2969   
2970   return(-1);
2971 }
2972
2973 /****************************************************************************
2974   handle named pipe commands
2975   ****************************************************************************/
2976 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
2977                       uint16 *setup,char *data,char *params,
2978                       int suwcnt,int tdscnt,int tpscnt,
2979                       int msrcnt,int mdrcnt,int mprcnt)
2980 {
2981
2982   if (strequal(name,"LANMAN"))
2983     return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2984
2985 if (strlen(name) < 1)
2986   return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
2987
2988
2989   DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2990            name,(int)setup[0],(int)setup[1]));
2991   
2992   return(0);
2993 }
2994
2995
2996 /****************************************************************************
2997   reply to a SMBtrans
2998   ****************************************************************************/
2999 int reply_trans(char *inbuf,char *outbuf)
3000 {
3001   fstring name;
3002
3003   char *data=NULL,*params=NULL;
3004   uint16 *setup=NULL;
3005
3006   int outsize = 0;
3007   int cnum = SVAL(inbuf,smb_tid);
3008   uint16 vuid = SVAL(inbuf,smb_uid);
3009
3010   int tpscnt = SVAL(inbuf,smb_vwv0);
3011   int tdscnt = SVAL(inbuf,smb_vwv1);
3012   int mprcnt = SVAL(inbuf,smb_vwv2);
3013   int mdrcnt = SVAL(inbuf,smb_vwv3);
3014   int msrcnt = CVAL(inbuf,smb_vwv4);
3015   BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3016   BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3017   int pscnt = SVAL(inbuf,smb_vwv9);
3018   int psoff = SVAL(inbuf,smb_vwv10);
3019   int dscnt = SVAL(inbuf,smb_vwv11);
3020   int dsoff = SVAL(inbuf,smb_vwv12);
3021   int suwcnt = CVAL(inbuf,smb_vwv13);
3022
3023   fstrcpy(name,smb_buf(inbuf));
3024
3025   if (dscnt > tdscnt || pscnt > tpscnt) {
3026           exit_server("invalid trans parameters\n");
3027   }
3028   
3029   if (tdscnt)
3030     {
3031       data = (char *)malloc(tdscnt);
3032       memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3033     }
3034   if (tpscnt)
3035     {
3036       params = (char *)malloc(tpscnt);
3037       memcpy(params,smb_base(inbuf)+psoff,pscnt);
3038     }
3039
3040   if (suwcnt)
3041     {
3042       int i;
3043       setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3044       for (i=0;i<suwcnt;i++)
3045         setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3046     }
3047
3048
3049   if (pscnt < tpscnt || dscnt < tdscnt)
3050     {
3051       /* We need to send an interim response then receive the rest
3052          of the parameter/data bytes */
3053       outsize = set_message(outbuf,0,0,True);
3054       show_msg(outbuf);
3055       send_smb(Client,outbuf);
3056     }
3057
3058   /* receive the rest of the trans packet */
3059   while (pscnt < tpscnt || dscnt < tdscnt)
3060     {
3061       int pcnt,poff,dcnt,doff,pdisp,ddisp;
3062       
3063       if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
3064           CVAL(inbuf, smb_com) != SMBtrans)
3065         {
3066           DEBUG(2,("Invalid secondary trans2 packet\n"));
3067           if (params) free(params);
3068           if (data) free(data);
3069           if (setup) free(setup);
3070           return(ERROR(ERRSRV,ERRerror));
3071         }
3072
3073       show_msg(inbuf);
3074       
3075       tpscnt = SVAL(inbuf,smb_vwv0);
3076       tdscnt = SVAL(inbuf,smb_vwv1);
3077
3078       pcnt = SVAL(inbuf,smb_vwv2);
3079       poff = SVAL(inbuf,smb_vwv3);
3080       pdisp = SVAL(inbuf,smb_vwv4);
3081       
3082       dcnt = SVAL(inbuf,smb_vwv5);
3083       doff = SVAL(inbuf,smb_vwv6);
3084       ddisp = SVAL(inbuf,smb_vwv7);
3085       
3086       pscnt += pcnt;
3087       dscnt += dcnt;
3088
3089       if (dscnt > tdscnt || pscnt > tpscnt) {
3090               exit_server("invalid trans parameters\n");
3091       }
3092
3093       if (pcnt)
3094         memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3095       if (dcnt)
3096         memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);      
3097     }
3098
3099
3100   DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3101   
3102
3103   if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3104     outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3105                          suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3106
3107
3108   if (data) free(data);
3109   if (params) free(params);
3110   if (setup) free(setup);
3111
3112   if (close_on_completion)
3113     close_cnum(cnum,vuid);
3114
3115   if (one_way)
3116     return(-1);
3117   
3118   if (outsize == 0)
3119     return(ERROR(ERRSRV,ERRnosupport));
3120
3121   return(outsize);
3122 }