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