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