client.c: New print queue query code from Jeff C. Foster " <jfoste@wgc.woodward...
[Samba/gbeck.git] / source / smbd / ipc.c
blob7922e41623637586a26baeb0692c555f9d63c70c
2 /*
3 Unix SMB/Netbios implementation.
4 Version 1.9.
5 Inter-process communication and named pipe handling
6 Copyright (C) Andrew Tridgell 1992-1997
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles the named pipe and mailslot calls
24 in the SMBtrans protocol
27 #include "includes.h"
29 #ifdef CHECK_TYPES
30 #undef CHECK_TYPES
31 #endif
32 #define CHECK_TYPES 0
34 extern int DEBUGLEVEL;
35 extern int max_send;
36 extern files_struct Files[];
37 extern connection_struct Connections[];
39 extern fstring local_machine;
40 extern fstring myworkgroup;
42 #define NERR_Success 0
43 #define NERR_badpass 86
44 #define NERR_notsupported 50
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
53 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
55 #define ACCESS_READ 0x01
56 #define ACCESS_WRITE 0x02
57 #define ACCESS_CREATE 0x04
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 */
64 extern int Client;
66 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
67 int mdrcnt,int mprcnt,
68 char **rdata,char **rparam,
69 int *rdata_len,int *rparam_len);
70 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
71 int mdrcnt,int mprcnt,
72 char **rdata,char **rparam,
73 int *rdata_len,int *rparam_len);
76 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
78 pstring buf;
79 int l;
81 if (!src || !dst || !n || !(*dst)) return(0);
83 StrnCpy(buf,src,sizeof(buf)/2);
84 string_sub(buf,"%S",lp_servicename(snum));
85 standard_sub(cnum,buf);
86 StrnCpy(*dst,buf,*n);
87 l = strlen(*dst) + 1;
88 (*dst) += l;
89 (*n) -= l;
90 return l;
93 static int CopyAndAdvance(char** dst, char* src, int* n)
95 int l;
96 if (!src || !dst || !n || !(*dst)) return(0);
97 StrnCpy(*dst,src,*n);
98 l = strlen(*dst) + 1;
99 (*dst) += l;
100 (*n) -= l;
101 return l;
104 static int StrlenExpanded(int cnum, int snum, char* s)
106 pstring buf;
107 if (!s) return(0);
108 StrnCpy(buf,s,sizeof(buf)/2);
109 string_sub(buf,"%S",lp_servicename(snum));
110 standard_sub(cnum,buf);
111 return strlen(buf) + 1;
114 static char* Expand(int cnum, int snum, char* s)
116 static pstring buf;
117 if (!s) return(NULL);
118 StrnCpy(buf,s,sizeof(buf)/2);
119 string_sub(buf,"%S",lp_servicename(snum));
120 standard_sub(cnum,buf);
121 return &buf[0];
124 /*******************************************************************
125 check a API string for validity when we only need to check the prefix
126 ******************************************************************/
127 static BOOL prefix_ok(char *str,char *prefix)
129 return(strncmp(str,prefix,strlen(prefix)) == 0);
133 /****************************************************************************
134 send a trans reply
135 ****************************************************************************/
136 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
137 int ldata,int lparam,int lsetup)
139 int i;
140 int this_ldata,this_lparam;
141 int tot_data=0,tot_param=0;
142 int align;
144 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
145 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
147 align = (this_lparam%4);
149 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
150 if (this_lparam)
151 memcpy(smb_buf(outbuf),param,this_lparam);
152 if (this_ldata)
153 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
155 SSVAL(outbuf,smb_vwv0,lparam);
156 SSVAL(outbuf,smb_vwv1,ldata);
157 SSVAL(outbuf,smb_vwv3,this_lparam);
158 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
159 SSVAL(outbuf,smb_vwv5,0);
160 SSVAL(outbuf,smb_vwv6,this_ldata);
161 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
162 SSVAL(outbuf,smb_vwv8,0);
163 SSVAL(outbuf,smb_vwv9,lsetup);
164 for (i=0;i<lsetup;i++)
165 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
167 show_msg(outbuf);
168 send_smb(Client,outbuf);
170 tot_data = this_ldata;
171 tot_param = this_lparam;
173 while (tot_data < ldata || tot_param < lparam)
175 this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
176 this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
178 align = (this_lparam%4);
180 set_message(outbuf,10,this_ldata+this_lparam+align,False);
181 if (this_lparam)
182 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
183 if (this_ldata)
184 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
186 SSVAL(outbuf,smb_vwv3,this_lparam);
187 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
188 SSVAL(outbuf,smb_vwv5,tot_param);
189 SSVAL(outbuf,smb_vwv6,this_ldata);
190 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
191 SSVAL(outbuf,smb_vwv8,tot_data);
192 SSVAL(outbuf,smb_vwv9,0);
194 show_msg(outbuf);
195 send_smb(Client,outbuf);
197 tot_data += this_ldata;
198 tot_param += this_lparam;
202 struct pack_desc {
203 char* format; /* formatstring for structure */
204 char* subformat; /* subformat for structure */
205 char* base; /* baseaddress of buffer */
206 int buflen; /* remaining size for fixed part; on init: length of base */
207 int subcount; /* count of substructures */
208 char* structbuf; /* pointer into buffer for remaining fixed part */
209 int stringlen; /* remaining size for variable part */
210 char* stringbuf; /* pointer into buffer for remaining variable part */
211 int neededlen; /* total needed size */
212 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
213 char* curpos; /* current position; pointer into format or subformat */
214 int errcode;
217 static int get_counter(char** p)
219 int i, n;
220 if (!p || !(*p)) return(1);
221 if (!isdigit(**p)) return 1;
222 for (n = 0;;) {
223 i = **p;
224 if (isdigit(i))
225 n = 10 * n + (i - '0');
226 else
227 return n;
228 (*p)++;
232 static int getlen(char* p)
234 int n = 0;
235 if (!p) return(0);
236 while (*p) {
237 switch( *p++ ) {
238 case 'W': /* word (2 byte) */
239 n += 2;
240 break;
241 case 'N': /* count of substructures (word) at end */
242 n += 2;
243 break;
244 case 'D': /* double word (4 byte) */
245 case 'z': /* offset to zero terminated string (4 byte) */
246 case 'l': /* offset to user data (4 byte) */
247 n += 4;
248 break;
249 case 'b': /* offset to data (with counter) (4 byte) */
250 n += 4;
251 get_counter(&p);
252 break;
253 case 'B': /* byte (with optional counter) */
254 n += get_counter(&p);
255 break;
258 return n;
261 static BOOL init_package(struct pack_desc* p, int count, int subcount)
263 int n = p->buflen;
264 int i;
266 if (!p->format || !p->base) return(False);
268 i = count * getlen(p->format);
269 if (p->subformat) i += subcount * getlen(p->subformat);
270 p->structbuf = p->base;
271 p->neededlen = 0;
272 p->usedlen = 0;
273 p->subcount = 0;
274 p->curpos = p->format;
275 if (i > n) {
276 i = n = 0;
277 p->errcode = NERR_BufTooSmall;
280 p->errcode = NERR_Success;
281 p->buflen = i;
282 n -= i;
283 p->stringbuf = p->base + i;
284 p->stringlen = n;
285 return(p->errcode == NERR_Success);
288 #ifdef __STDC__
289 static int package(struct pack_desc* p, ...)
291 #else
292 static int package(va_alist)
293 va_dcl
295 struct pack_desc* p;
296 #endif
297 va_list args;
298 int needed=0, stringneeded;
299 char* str=NULL;
300 int is_string=0, stringused;
301 int32 temp;
303 #ifdef __STDC__
304 va_start(args,p);
305 #else
306 va_start(args);
307 p = va_arg(args,struct pack_desc *);
308 #endif
310 if (!*p->curpos) {
311 if (!p->subcount)
312 p->curpos = p->format;
313 else {
314 p->curpos = p->subformat;
315 p->subcount--;
318 #if CHECK_TYPES
319 str = va_arg(args,char*);
320 if (strncmp(str,p->curpos,strlen(str)) != 0) {
321 DEBUG(2,("type error in package: %s instead of %*s\n",str,
322 strlen(str),p->curpos));
323 va_end(args);
324 #if AJT
325 ajt_panic();
326 #endif
327 return 0;
329 #endif
330 stringneeded = -1;
332 if (!p->curpos) return(0);
334 switch( *p->curpos++ ) {
335 case 'W': /* word (2 byte) */
336 needed = 2;
337 temp = va_arg(args,int);
338 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
339 break;
340 case 'N': /* count of substructures (word) at end */
341 needed = 2;
342 p->subcount = va_arg(args,int);
343 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
344 break;
345 case 'D': /* double word (4 byte) */
346 needed = 4;
347 temp = va_arg(args,int);
348 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
349 break;
350 case 'B': /* byte (with optional counter) */
351 needed = get_counter(&p->curpos);
353 char *s = va_arg(args,char*);
354 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
356 break;
357 case 'z': /* offset to zero terminated string (4 byte) */
358 str = va_arg(args,char*);
359 stringneeded = (str ? strlen(str)+1 : 0);
360 is_string = 1;
361 break;
362 case 'l': /* offset to user data (4 byte) */
363 str = va_arg(args,char*);
364 stringneeded = va_arg(args,int);
365 is_string = 0;
366 break;
367 case 'b': /* offset to data (with counter) (4 byte) */
368 str = va_arg(args,char*);
369 stringneeded = get_counter(&p->curpos);
370 is_string = 0;
371 break;
373 va_end(args);
374 if (stringneeded >= 0) {
375 needed = 4;
376 if (p->buflen >= needed) {
377 stringused = stringneeded;
378 if (stringused > p->stringlen) {
379 stringused = (is_string ? p->stringlen : 0);
380 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
382 if (!stringused)
383 SIVAL(p->structbuf,0,0);
384 else {
385 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
386 memcpy(p->stringbuf,str?str:"",stringused);
387 if (is_string) p->stringbuf[stringused-1] = '\0';
388 p->stringbuf += stringused;
389 p->stringlen -= stringused;
390 p->usedlen += stringused;
393 p->neededlen += stringneeded;
395 p->neededlen += needed;
396 if (p->buflen >= needed) {
397 p->structbuf += needed;
398 p->buflen -= needed;
399 p->usedlen += needed;
401 else {
402 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
404 return 1;
407 #if CHECK_TYPES
408 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
409 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
410 #else
411 #define PACK(desc,t,v) package(desc,v)
412 #define PACKl(desc,t,v,l) package(desc,v,l)
413 #endif
415 static void PACKI(struct pack_desc* desc,char *t,int v)
417 PACK(desc,t,v);
420 static void PACKS(struct pack_desc* desc,char *t,char *v)
422 PACK(desc,t,v);
426 /****************************************************************************
427 get a print queue
428 ****************************************************************************/
430 static void PackDriverData(struct pack_desc* desc)
432 char drivdata[4+4+32];
433 SIVAL(drivdata,0,sizeof drivdata); /* cb */
434 SIVAL(drivdata,4,1000); /* lVersion */
435 memset(drivdata+8,0,32); /* szDeviceName */
436 strcpy(drivdata+8,"NULL");
437 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
440 static int check_printq_info(struct pack_desc* desc,
441 int uLevel, char *id1, const char* id2)
443 desc->subformat = NULL;
444 switch( uLevel ) {
445 case 0:
446 desc->format = "B13";
447 break;
448 case 1:
449 desc->format = "B13BWWWzzzzzWW";
450 break;
451 case 2:
452 desc->format = "B13BWWWzzzzzWN";
453 desc->subformat = "WB21BB16B10zWWzDDz";
454 break;
455 case 3:
456 desc->format = "zWWWWzzzzWWzzl";
457 break;
458 case 4:
459 desc->format = "zWWWWzzzzWNzzl";
460 desc->subformat = "WWzWWDDzz";
461 break;
462 case 5:
463 desc->format = "z";
464 break;
465 default: return False;
467 if (strcmp(desc->format,id1) != 0) return False;
468 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
469 return True;
472 static void fill_printjob_info(int cnum, int snum, int uLevel,
473 struct pack_desc* desc,
474 print_queue_struct* queue, int n)
476 time_t t = queue->time;
478 /* the client expects localtime */
479 t -= TimeDiff(t);
481 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
482 if (uLevel == 1) {
483 PACKS(desc,"B21",queue->user); /* szUserName */
484 PACKS(desc,"B",""); /* pad */
485 PACKS(desc,"B16",""); /* szNotifyName */
486 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
487 PACKS(desc,"z",""); /* pszParms */
488 PACKI(desc,"W",n+1); /* uPosition */
489 PACKI(desc,"W",queue->status); /* fsStatus */
490 PACKS(desc,"z",""); /* pszStatus */
491 PACKI(desc,"D",t); /* ulSubmitted */
492 PACKI(desc,"D",queue->size); /* ulSize */
493 PACKS(desc,"z",queue->file); /* pszComment */
495 if (uLevel == 2 || uLevel == 3) {
496 PACKI(desc,"W",queue->priority); /* uPriority */
497 PACKS(desc,"z",queue->user); /* pszUserName */
498 PACKI(desc,"W",n+1); /* uPosition */
499 PACKI(desc,"W",queue->status); /* fsStatus */
500 PACKI(desc,"D",t); /* ulSubmitted */
501 PACKI(desc,"D",queue->size); /* ulSize */
502 PACKS(desc,"z","Samba"); /* pszComment */
503 PACKS(desc,"z",queue->file); /* pszDocument */
504 if (uLevel == 3) {
505 PACKS(desc,"z",""); /* pszNotifyName */
506 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
507 PACKS(desc,"z",""); /* pszParms */
508 PACKS(desc,"z",""); /* pszStatus */
509 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
510 PACKS(desc,"z","lpd"); /* pszQProcName */
511 PACKS(desc,"z",""); /* pszQProcParms */
512 PACKS(desc,"z","NULL"); /* pszDriverName */
513 PackDriverData(desc); /* pDriverData */
514 PACKS(desc,"z",""); /* pszPrinterName */
519 static void fill_printq_info(int cnum, int snum, int uLevel,
520 struct pack_desc* desc,
521 int count, print_queue_struct* queue,
522 print_status_struct* status)
524 if (uLevel < 3) {
525 PACKS(desc,"B13",SERVICE(snum));
526 } else {
527 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
529 if (uLevel == 1 || uLevel == 2) {
530 PACKS(desc,"B",""); /* alignment */
531 PACKI(desc,"W",5); /* priority */
532 PACKI(desc,"W",0); /* start time */
533 PACKI(desc,"W",0); /* until time */
534 PACKS(desc,"z",""); /* pSepFile */
535 PACKS(desc,"z","lpd"); /* pPrProc */
536 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
537 PACKS(desc,"z",""); /* pParms */
538 if (snum < 0) {
539 PACKS(desc,"z","UNKNOWN PRINTER");
540 PACKI(desc,"W",LPSTAT_ERROR);
542 else if (!status || !status->message[0]) {
543 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
544 PACKI(desc,"W",LPSTAT_OK); /* status */
545 } else {
546 PACKS(desc,"z",status->message);
547 PACKI(desc,"W",status->status); /* status */
549 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
551 if (uLevel == 3 || uLevel == 4) {
552 PACKI(desc,"W",5); /* uPriority */
553 PACKI(desc,"W",0); /* uStarttime */
554 PACKI(desc,"W",0); /* uUntiltime */
555 PACKI(desc,"W",5); /* pad1 */
556 PACKS(desc,"z",""); /* pszSepFile */
557 PACKS(desc,"z","WinPrint"); /* pszPrProc */
558 PACKS(desc,"z",""); /* pszParms */
559 if (!status || !status->message[0]) {
560 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
561 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
562 } else {
563 PACKS(desc,"z",status->message); /* pszComment */
564 PACKI(desc,"W",status->status); /* fsStatus */
566 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
567 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
568 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
569 PackDriverData(desc); /* pDriverData */
571 if (uLevel == 2 || uLevel == 4) {
572 int i;
573 for (i=0;i<count;i++)
574 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
577 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
580 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
581 int mdrcnt,int mprcnt,
582 char **rdata,char **rparam,
583 int *rdata_len,int *rparam_len)
585 char *str1 = param+2;
586 char *str2 = skip_string(str1,1);
587 char *p = skip_string(str2,1);
588 char *QueueName = p;
589 int uLevel,cbBuf;
590 int count=0;
591 int snum;
592 char* str3;
593 struct pack_desc desc;
594 print_queue_struct *queue=NULL;
595 print_status_struct status;
597 bzero(&status,sizeof(status));
598 bzero(&desc,sizeof(desc));
600 p = skip_string(p,1);
601 uLevel = SVAL(p,0);
602 cbBuf = SVAL(p,2);
603 str3 = p + 4;
605 /* remove any trailing username */
606 if ((p = strchr(QueueName,'%'))) *p = 0;
608 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
610 /* check it's a supported varient */
611 if (!prefix_ok(str1,"zWrLh")) return False;
612 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
614 snum = lp_servicenumber(QueueName);
615 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
616 int pnum = lp_servicenumber(PRINTERS_NAME);
617 if (pnum >= 0) {
618 lp_add_printer(QueueName,pnum);
619 snum = lp_servicenumber(QueueName);
623 if (snum < 0 || !VALID_SNUM(snum)) return(False);
625 count = get_printqueue(snum,cnum,&queue,&status);
626 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
627 desc.base = *rdata;
628 desc.buflen = mdrcnt;
629 if (init_package(&desc,1,count)) {
630 desc.subcount = count;
631 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
634 *rdata_len = desc.usedlen;
636 *rparam_len = 6;
637 *rparam = REALLOC(*rparam,*rparam_len);
638 SSVALS(*rparam,0,desc.errcode);
639 SSVAL(*rparam,2,0);
640 SSVAL(*rparam,4,desc.neededlen);
642 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
644 if (queue) free(queue);
646 return(True);
650 /****************************************************************************
651 view list of all print jobs on all queues
652 ****************************************************************************/
653 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
654 int mdrcnt, int mprcnt,
655 char **rdata, char** rparam,
656 int *rdata_len, int *rparam_len)
658 char *param_format = param+2;
659 char *output_format1 = skip_string(param_format,1);
660 char *p = skip_string(output_format1,1);
661 int uLevel = SVAL(p,0);
662 char *output_format2 = p + 4;
663 int services = lp_numservices();
664 int i, n;
665 struct pack_desc desc;
666 print_queue_struct **queue = NULL;
667 print_status_struct *status = NULL;
668 int* subcntarr = NULL;
669 int queuecnt, subcnt=0, succnt=0;
671 bzero(&desc,sizeof(desc));
673 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
675 if (!prefix_ok(param_format,"WrLeh")) return False;
676 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
677 return False;
678 queuecnt = 0;
679 for (i = 0; i < services; i++)
680 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
681 queuecnt++;
682 if (uLevel > 0) {
683 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
684 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
685 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
686 memset(status,0,queuecnt*sizeof(print_status_struct));
687 subcntarr = (int*)malloc(queuecnt*sizeof(int));
688 subcnt = 0;
689 n = 0;
690 for (i = 0; i < services; i++)
691 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
692 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
693 subcnt += subcntarr[n];
694 n++;
697 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
698 desc.base = *rdata;
699 desc.buflen = mdrcnt;
701 if (init_package(&desc,queuecnt,subcnt)) {
702 n = 0;
703 succnt = 0;
704 for (i = 0; i < services; i++)
705 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
706 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
707 n++;
708 if (desc.errcode == NERR_Success) succnt = n;
712 if (subcntarr) free(subcntarr);
714 *rdata_len = desc.usedlen;
715 *rparam_len = 8;
716 *rparam = REALLOC(*rparam,*rparam_len);
717 SSVALS(*rparam,0,desc.errcode);
718 SSVAL(*rparam,2,0);
719 SSVAL(*rparam,4,succnt);
720 SSVAL(*rparam,6,queuecnt);
722 for (i = 0; i < queuecnt; i++) {
723 if (queue && queue[i]) free(queue[i]);
726 if (queue) free(queue);
727 if (status) free(status);
729 return True;
732 /****************************************************************************
733 get info level for a server list query
734 ****************************************************************************/
735 static BOOL check_server_info(int uLevel, char* id)
737 switch( uLevel ) {
738 case 0:
739 if (strcmp(id,"B16") != 0) return False;
740 break;
741 case 1:
742 if (strcmp(id,"B16BBDz") != 0) return False;
743 break;
744 default:
745 return False;
747 return True;
750 struct srv_info_struct
752 fstring name;
753 uint32 type;
754 fstring comment;
755 fstring domain;
756 BOOL server_added;
760 /*******************************************************************
761 get server info lists from the files saved by nmbd. Return the
762 number of entries
763 ******************************************************************/
764 static int get_server_info(uint32 servertype,
765 struct srv_info_struct **servers,
766 char *domain)
768 FILE *f;
769 pstring fname;
770 int count=0;
771 int alloced=0;
772 pstring line;
773 BOOL local_list_only;
775 strcpy(fname,lp_lockdir());
776 trim_string(fname,NULL,"/");
777 strcat(fname,"/");
778 strcat(fname,SERVER_LIST);
780 f = fopen(fname,"r");
782 if (!f) {
783 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
784 return(0);
787 /* request for everything is code for request all servers */
788 if (servertype == SV_TYPE_ALL)
789 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
791 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
793 DEBUG(4,("Servertype search: %8x\n",servertype));
795 while (!feof(f))
797 fstring stype;
798 struct srv_info_struct *s;
799 char *ptr = line;
800 BOOL ok = True;
801 *ptr = 0;
803 fgets(line,sizeof(line)-1,f);
804 if (!*line) continue;
806 if (count == alloced) {
807 alloced += 10;
808 (*servers) = (struct srv_info_struct *)
809 Realloc(*servers,sizeof(**servers)*alloced);
810 if (!(*servers)) return(0);
811 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
813 s = &(*servers)[count];
815 if (!next_token(&ptr,s->name , NULL)) continue;
816 if (!next_token(&ptr,stype , NULL)) continue;
817 if (!next_token(&ptr,s->comment, NULL)) continue;
818 if (!next_token(&ptr,s->domain , NULL)) {
819 /* this allows us to cope with an old nmbd */
820 strcpy(s->domain,myworkgroup);
823 if (sscanf(stype,"%X",&s->type) != 1) {
824 DEBUG(4,("r:host file "));
825 ok = False;
828 /* Filter the servers/domains we return based on what was asked for. */
830 /* Check to see if we are being asked for a local list only. */
831 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
832 DEBUG(4,("r: local list only"));
833 ok = False;
836 /* doesn't match up: don't want it */
837 if (!(servertype & s->type)) {
838 DEBUG(4,("r:serv type "));
839 ok = False;
842 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
843 (s->type & SV_TYPE_DOMAIN_ENUM))
845 DEBUG(4,("s: dom mismatch "));
846 ok = False;
849 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
851 ok = False;
854 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
855 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
857 if (ok)
859 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
860 s->name, s->type, s->comment, s->domain));
862 s->server_added = True;
863 count++;
865 else
867 DEBUG(4,("%20s %8x %25s %15s\n",
868 s->name, s->type, s->comment, s->domain));
872 fclose(f);
873 return(count);
877 /*******************************************************************
878 fill in a server info structure
879 ******************************************************************/
880 static int fill_srv_info(struct srv_info_struct *service,
881 int uLevel, char **buf, int *buflen,
882 char **stringbuf, int *stringspace, char *baseaddr)
884 int struct_len;
885 char* p;
886 char* p2;
887 int l2;
888 int len;
890 switch (uLevel) {
891 case 0: struct_len = 16; break;
892 case 1: struct_len = 26; break;
893 default: return -1;
896 if (!buf)
898 len = 0;
899 switch (uLevel)
901 case 1:
902 len = strlen(service->comment)+1;
903 break;
906 if (buflen) *buflen = struct_len;
907 if (stringspace) *stringspace = len;
908 return struct_len + len;
911 len = struct_len;
912 p = *buf;
913 if (*buflen < struct_len) return -1;
914 if (stringbuf)
916 p2 = *stringbuf;
917 l2 = *stringspace;
919 else
921 p2 = p + struct_len;
922 l2 = *buflen - struct_len;
924 if (!baseaddr) baseaddr = p;
926 switch (uLevel)
928 case 0:
929 StrnCpy(p,service->name,15);
930 break;
932 case 1:
933 StrnCpy(p,service->name,15);
934 SIVAL(p,18,service->type);
935 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
936 len += CopyAndAdvance(&p2,service->comment,&l2);
937 break;
940 if (stringbuf)
942 *buf = p + struct_len;
943 *buflen -= struct_len;
944 *stringbuf = p2;
945 *stringspace = l2;
947 else
949 *buf = p2;
950 *buflen -= len;
952 return len;
956 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
958 return(strcmp(s1->name,s2->name));
961 /****************************************************************************
962 view list of servers available (or possibly domains). The info is
963 extracted from lists saved by nmbd on the local host
964 ****************************************************************************/
965 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
966 int mdrcnt, int mprcnt, char **rdata,
967 char **rparam, int *rdata_len, int *rparam_len)
969 char *str1 = param+2;
970 char *str2 = skip_string(str1,1);
971 char *p = skip_string(str2,1);
972 int uLevel = SVAL(p,0);
973 int buf_len = SVAL(p,2);
974 uint32 servertype = IVAL(p,4);
975 char *p2;
976 int data_len, fixed_len, string_len;
977 int f_len, s_len;
978 struct srv_info_struct *servers=NULL;
979 int counted=0,total=0;
980 int i,missed;
981 fstring domain;
982 BOOL domain_request;
983 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
985 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
987 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
989 p += 8;
991 if (!prefix_ok(str1,"WrLehD")) return False;
992 if (!check_server_info(uLevel,str2)) return False;
994 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
995 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
996 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
998 if (strcmp(str1, "WrLehDz") == 0) {
999 StrnCpy(domain, p, sizeof(fstring)-1);
1000 } else {
1001 StrnCpy(domain, myworkgroup, sizeof(fstring)-1);
1004 if (lp_browse_list())
1005 total = get_server_info(servertype,&servers,domain);
1007 data_len = fixed_len = string_len = 0;
1008 missed = 0;
1010 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1013 char *lastname=NULL;
1015 for (i=0;i<total;i++)
1017 struct srv_info_struct *s = &servers[i];
1018 if (lastname && strequal(lastname,s->name)) continue;
1019 lastname = s->name;
1020 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1021 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1022 s->name, s->type, s->comment, s->domain));
1024 if (data_len <= buf_len) {
1025 counted++;
1026 fixed_len += f_len;
1027 string_len += s_len;
1028 } else {
1029 missed++;
1034 *rdata_len = fixed_len + string_len;
1035 *rdata = REALLOC(*rdata,*rdata_len);
1036 bzero(*rdata,*rdata_len);
1038 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1039 p = *rdata;
1040 f_len = fixed_len;
1041 s_len = string_len;
1044 char *lastname=NULL;
1045 int count2 = counted;
1046 for (i = 0; i < total && count2;i++)
1048 struct srv_info_struct *s = &servers[i];
1049 if (lastname && strequal(lastname,s->name)) continue;
1050 lastname = s->name;
1051 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1052 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1053 s->name, s->type, s->comment, s->domain));
1054 count2--;
1058 *rparam_len = 8;
1059 *rparam = REALLOC(*rparam,*rparam_len);
1060 SSVAL(*rparam,0,NERR_Success);
1061 SSVAL(*rparam,2,0);
1062 SSVAL(*rparam,4,counted);
1063 SSVAL(*rparam,6,counted+missed);
1065 if (servers) free(servers);
1067 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1068 domain,uLevel,counted,counted+missed));
1070 return(True);
1074 /****************************************************************************
1075 get info about a share
1076 ****************************************************************************/
1077 static BOOL check_share_info(int uLevel, char* id)
1079 switch( uLevel ) {
1080 case 0:
1081 if (strcmp(id,"B13") != 0) return False;
1082 break;
1083 case 1:
1084 if (strcmp(id,"B13BWz") != 0) return False;
1085 break;
1086 case 2:
1087 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1088 break;
1089 case 91:
1090 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1091 break;
1092 default: return False;
1094 return True;
1097 static int fill_share_info(int cnum, int snum, int uLevel,
1098 char** buf, int* buflen,
1099 char** stringbuf, int* stringspace, char* baseaddr)
1101 int struct_len;
1102 char* p;
1103 char* p2;
1104 int l2;
1105 int len;
1107 switch( uLevel ) {
1108 case 0: struct_len = 13; break;
1109 case 1: struct_len = 20; break;
1110 case 2: struct_len = 40; break;
1111 case 91: struct_len = 68; break;
1112 default: return -1;
1116 if (!buf)
1118 len = 0;
1119 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1120 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1121 if (buflen) *buflen = struct_len;
1122 if (stringspace) *stringspace = len;
1123 return struct_len + len;
1126 len = struct_len;
1127 p = *buf;
1128 if ((*buflen) < struct_len) return -1;
1129 if (stringbuf)
1131 p2 = *stringbuf;
1132 l2 = *stringspace;
1134 else
1136 p2 = p + struct_len;
1137 l2 = (*buflen) - struct_len;
1139 if (!baseaddr) baseaddr = p;
1141 StrnCpy(p,lp_servicename(snum),13);
1143 if (uLevel > 0)
1145 int type;
1146 CVAL(p,13) = 0;
1147 type = STYPE_DISKTREE;
1148 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1149 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1150 SSVAL(p,14,type); /* device type */
1151 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1152 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1155 if (uLevel > 1)
1157 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1158 SSVALS(p,22,-1); /* max uses */
1159 SSVAL(p,24,1); /* current uses */
1160 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1161 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1162 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1165 if (uLevel > 2)
1167 memset(p+40,0,SHPWLEN+2);
1168 SSVAL(p,50,0);
1169 SIVAL(p,52,0);
1170 SSVAL(p,56,0);
1171 SSVAL(p,58,0);
1172 SIVAL(p,60,0);
1173 SSVAL(p,64,0);
1174 SSVAL(p,66,0);
1177 if (stringbuf)
1179 (*buf) = p + struct_len;
1180 (*buflen) -= struct_len;
1181 (*stringbuf) = p2;
1182 (*stringspace) = l2;
1184 else
1186 (*buf) = p2;
1187 (*buflen) -= len;
1189 return len;
1192 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1193 int mdrcnt,int mprcnt,
1194 char **rdata,char **rparam,
1195 int *rdata_len,int *rparam_len)
1197 char *str1 = param+2;
1198 char *str2 = skip_string(str1,1);
1199 char *netname = skip_string(str2,1);
1200 char *p = skip_string(netname,1);
1201 int uLevel = SVAL(p,0);
1202 int snum = find_service(netname);
1204 if (snum < 0) return False;
1206 /* check it's a supported varient */
1207 if (!prefix_ok(str1,"zWrLh")) return False;
1208 if (!check_share_info(uLevel,str2)) return False;
1210 *rdata = REALLOC(*rdata,mdrcnt);
1211 p = *rdata;
1212 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1213 if (*rdata_len < 0) return False;
1215 *rparam_len = 6;
1216 *rparam = REALLOC(*rparam,*rparam_len);
1217 SSVAL(*rparam,0,NERR_Success);
1218 SSVAL(*rparam,2,0); /* converter word */
1219 SSVAL(*rparam,4,*rdata_len);
1221 return(True);
1224 /****************************************************************************
1225 view list of shares available
1226 ****************************************************************************/
1227 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1228 int mdrcnt,int mprcnt,
1229 char **rdata,char **rparam,
1230 int *rdata_len,int *rparam_len)
1232 char *str1 = param+2;
1233 char *str2 = skip_string(str1,1);
1234 char *p = skip_string(str2,1);
1235 int uLevel = SVAL(p,0);
1236 int buf_len = SVAL(p,2);
1237 char *p2;
1238 int count=lp_numservices();
1239 int total=0,counted=0;
1240 int i;
1241 int data_len, fixed_len, string_len;
1242 int f_len, s_len;
1244 if (!prefix_ok(str1,"WrLeh")) return False;
1245 if (!check_share_info(uLevel,str2)) return False;
1247 data_len = fixed_len = string_len = 0;
1248 for (i=0;i<count;i++)
1249 if (lp_browseable(i) && lp_snum_ok(i))
1251 total++;
1252 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1253 if (data_len <= buf_len)
1255 counted++;
1256 fixed_len += f_len;
1257 string_len += s_len;
1260 *rdata_len = fixed_len + string_len;
1261 *rdata = REALLOC(*rdata,*rdata_len);
1262 memset(*rdata,0,*rdata_len);
1264 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1265 p = *rdata;
1266 f_len = fixed_len;
1267 s_len = string_len;
1268 for (i = 0; i < count;i++)
1269 if (lp_browseable(i) && lp_snum_ok(i))
1270 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1271 break;
1273 *rparam_len = 8;
1274 *rparam = REALLOC(*rparam,*rparam_len);
1275 SSVAL(*rparam,0,NERR_Success);
1276 SSVAL(*rparam,2,0);
1277 SSVAL(*rparam,4,counted);
1278 SSVAL(*rparam,6,total);
1280 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1281 counted,total,uLevel,
1282 buf_len,*rdata_len,mdrcnt));
1283 return(True);
1288 /****************************************************************************
1289 get the time of day info
1290 ****************************************************************************/
1291 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1292 int mdrcnt,int mprcnt,
1293 char **rdata,char **rparam,
1294 int *rdata_len,int *rparam_len)
1296 char *p;
1297 *rparam_len = 4;
1298 *rparam = REALLOC(*rparam,*rparam_len);
1300 *rdata_len = 21;
1301 *rdata = REALLOC(*rdata,*rdata_len);
1303 SSVAL(*rparam,0,NERR_Success);
1304 SSVAL(*rparam,2,0); /* converter word */
1306 p = *rdata;
1309 struct tm *t;
1310 time_t unixdate = time(NULL);
1312 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1313 by NT in a "net time" operation,
1314 it seems to ignore the one below */
1316 /* the client expects to get localtime, not GMT, in this bit
1317 (I think, this needs testing) */
1318 t = LocalTime(&unixdate);
1320 SIVAL(p,4,0); /* msecs ? */
1321 CVAL(p,8) = t->tm_hour;
1322 CVAL(p,9) = t->tm_min;
1323 CVAL(p,10) = t->tm_sec;
1324 CVAL(p,11) = 0; /* hundredths of seconds */
1325 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1326 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1327 CVAL(p,16) = t->tm_mday;
1328 CVAL(p,17) = t->tm_mon + 1;
1329 SSVAL(p,18,1900+t->tm_year);
1330 CVAL(p,20) = t->tm_wday;
1334 return(True);
1337 /****************************************************************************
1338 set the user password
1339 ****************************************************************************/
1340 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1341 int mdrcnt,int mprcnt,
1342 char **rdata,char **rparam,
1343 int *rdata_len,int *rparam_len)
1345 char *p = skip_string(param+2,2);
1346 fstring user;
1347 fstring pass1,pass2;
1349 strcpy(user,p);
1351 p = skip_string(p,1);
1353 StrnCpy(pass1,p,16);
1354 StrnCpy(pass2,p+16,16);
1356 *rparam_len = 4;
1357 *rparam = REALLOC(*rparam,*rparam_len);
1359 *rdata_len = 0;
1361 SSVAL(*rparam,0,NERR_badpass);
1362 SSVAL(*rparam,2,0); /* converter word */
1364 DEBUG(3,("Set password for <%s>\n",user));
1366 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1367 chgpasswd(user,pass1,pass2))
1369 SSVAL(*rparam,0,NERR_Success);
1372 bzero(pass1,sizeof(fstring));
1373 bzero(pass2,sizeof(fstring));
1375 return(True);
1378 /****************************************************************************
1379 delete a print job
1380 Form: <W> <>
1381 ****************************************************************************/
1382 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1383 int mdrcnt,int mprcnt,
1384 char **rdata,char **rparam,
1385 int *rdata_len,int *rparam_len)
1387 int function = SVAL(param,0);
1388 char *str1 = param+2;
1389 char *str2 = skip_string(str1,1);
1390 char *p = skip_string(str2,1);
1391 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1392 by the print queue api */
1393 int snum = (SVAL(p,0)>>8);
1394 int i, count;
1397 /* check it's a supported varient */
1398 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1399 return(False);
1401 *rparam_len = 4;
1402 *rparam = REALLOC(*rparam,*rparam_len);
1404 *rdata_len = 0;
1406 SSVAL(*rparam,0,NERR_Success);
1408 if (snum >= 0 && VALID_SNUM(snum))
1410 print_queue_struct *queue=NULL;
1411 lpq_reset(snum);
1412 count = get_printqueue(snum,cnum,&queue,NULL);
1414 for (i=0;i<count;i++)
1415 if ((queue[i].job%0xFF) == jobid)
1417 switch (function) {
1418 case 81: /* delete */
1419 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1420 del_printqueue(cnum,snum,queue[i].job);
1421 break;
1422 case 82: /* pause */
1423 case 83: /* resume */
1424 DEBUG(3,("%s queue entry %d\n",
1425 (function==82?"pausing":"resuming"),queue[i].job));
1426 status_printjob(cnum,snum,queue[i].job,
1427 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1428 break;
1430 break;
1433 if (i==count)
1434 SSVAL(*rparam,0,NERR_JobNotFound);
1436 if (queue) free(queue);
1439 SSVAL(*rparam,2,0); /* converter word */
1441 return(True);
1444 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1445 int mdrcnt,int mprcnt,
1446 char **rdata,char **rparam,
1447 int *rdata_len,int *rparam_len)
1449 char *str1 = param+2;
1450 char *str2 = skip_string(str1,1);
1451 char *QueueName = skip_string(str2,1);
1452 int snum;
1454 /* check it's a supported varient */
1455 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1456 return(False);
1458 *rparam_len = 4;
1459 *rparam = REALLOC(*rparam,*rparam_len);
1461 *rdata_len = 0;
1463 SSVAL(*rparam,0,NERR_Success);
1464 SSVAL(*rparam,2,0); /* converter word */
1466 snum = lp_servicenumber(QueueName);
1467 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1468 int pnum = lp_servicenumber(PRINTERS_NAME);
1469 if (pnum >= 0) {
1470 lp_add_printer(QueueName,pnum);
1471 snum = lp_servicenumber(QueueName);
1475 if (snum >= 0 && VALID_SNUM(snum)) {
1476 print_queue_struct *queue=NULL;
1477 int i, count;
1478 lpq_reset(snum);
1480 count = get_printqueue(snum,cnum,&queue,NULL);
1481 for (i = 0; i < count; i++)
1482 del_printqueue(cnum,snum,queue[i].job);
1484 if (queue) free(queue);
1487 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1489 return(True);
1493 /****************************************************************************
1494 set the property of a print job (undocumented?)
1495 ? function = 0xb -> set name of print job
1496 ? function = 0x6 -> move print job up/down
1497 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1498 or <WWsTP> <WB21BB16B10zWWzDDz>
1499 ****************************************************************************/
1500 static int check_printjob_info(struct pack_desc* desc,
1501 int uLevel, char* id)
1503 desc->subformat = NULL;
1504 switch( uLevel ) {
1505 case 0: desc->format = "W"; break;
1506 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1507 case 2: desc->format = "WWzWWDDzz"; break;
1508 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1509 default: return False;
1511 if (strcmp(desc->format,id) != 0) return False;
1512 return True;
1515 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1516 int mdrcnt,int mprcnt,
1517 char **rdata,char **rparam,
1518 int *rdata_len,int *rparam_len)
1520 struct pack_desc desc;
1521 char *str1 = param+2;
1522 char *str2 = skip_string(str1,1);
1523 char *p = skip_string(str2,1);
1524 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1525 by the print queue api */
1526 int snum = (SVAL(p,0)>>8);
1527 int uLevel = SVAL(p,2);
1528 int function = SVAL(p,4); /* what is this ?? */
1529 int i;
1530 char *s = data;
1532 *rparam_len = 4;
1533 *rparam = REALLOC(*rparam,*rparam_len);
1535 *rdata_len = 0;
1537 /* check it's a supported varient */
1538 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1539 return(False);
1541 switch (function) {
1542 case 0x6: /* change job place in the queue, data gives the new place */
1543 if (snum >= 0 && VALID_SNUM(snum))
1545 print_queue_struct *queue=NULL;
1546 int count;
1548 lpq_reset(snum);
1549 count = get_printqueue(snum,cnum,&queue,NULL);
1550 for (i=0;i<count;i++) /* find job */
1551 if ((queue[i].job%0xFF) == jobid) break;
1553 if (i==count) {
1554 desc.errcode=NERR_JobNotFound;
1555 if (queue) free(queue);
1557 else {
1558 desc.errcode=NERR_Success;
1559 i++;
1560 #if 0
1562 int place= SVAL(data,0);
1563 /* we currently have no way of doing this. Can any unix do it? */
1564 if (i < place) /* move down */;
1565 else if (i > place ) /* move up */;
1567 #endif
1568 desc.errcode=NERR_notsupported; /* not yet supported */
1569 if (queue) free(queue);
1572 else desc.errcode=NERR_JobNotFound;
1573 break;
1574 case 0xb: /* change print job name, data gives the name */
1575 /* jobid, snum should be zero */
1576 if (isalpha(*s))
1578 pstring name;
1579 int l = 0;
1580 while (l<64 && *s)
1582 if (issafe(*s)) name[l++] = *s;
1583 s++;
1585 name[l] = 0;
1587 DEBUG(3,("Setting print name to %s\n",name));
1589 for (i=0;i<MAX_OPEN_FILES;i++)
1590 if (Files[i].open && Files[i].print_file)
1592 pstring wd;
1593 GetWd(wd);
1594 unbecome_user();
1596 if (!become_user(Files[i].cnum,vuid) ||
1597 !become_service(Files[i].cnum,True))
1598 break;
1600 if (sys_rename(Files[i].name,name) == 0)
1601 string_set(&Files[i].name,name);
1602 break;
1605 desc.errcode=NERR_Success;
1607 break;
1608 default: /* not implemented */
1609 return False;
1612 SSVALS(*rparam,0,desc.errcode);
1613 SSVAL(*rparam,2,0); /* converter word */
1615 return(True);
1619 /****************************************************************************
1620 get info about the server
1621 ****************************************************************************/
1622 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1623 int mdrcnt,int mprcnt,
1624 char **rdata,char **rparam,
1625 int *rdata_len,int *rparam_len)
1627 char *str1 = param+2;
1628 char *str2 = skip_string(str1,1);
1629 char *p = skip_string(str2,1);
1630 int uLevel = SVAL(p,0);
1631 char *p2;
1632 int struct_len;
1634 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1636 /* check it's a supported varient */
1637 if (!prefix_ok(str1,"WrLh")) return False;
1638 switch( uLevel ) {
1639 case 0:
1640 if (strcmp(str2,"B16") != 0) return False;
1641 struct_len = 16;
1642 break;
1643 case 1:
1644 if (strcmp(str2,"B16BBDz") != 0) return False;
1645 struct_len = 26;
1646 break;
1647 case 2:
1648 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1649 != 0) return False;
1650 struct_len = 134;
1651 break;
1652 case 3:
1653 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1654 != 0) return False;
1655 struct_len = 144;
1656 break;
1657 case 20:
1658 if (strcmp(str2,"DN") != 0) return False;
1659 struct_len = 6;
1660 break;
1661 case 50:
1662 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1663 struct_len = 42;
1664 break;
1665 default: return False;
1668 *rdata_len = mdrcnt;
1669 *rdata = REALLOC(*rdata,*rdata_len);
1671 p = *rdata;
1672 p2 = p + struct_len;
1673 if (uLevel != 20) {
1674 StrnCpy(p,local_machine,16);
1675 strupper(p);
1677 p += 16;
1678 if (uLevel > 0)
1680 struct srv_info_struct *servers=NULL;
1681 int i,count;
1682 pstring comment;
1683 uint32 servertype=DFLT_SERVER_TYPE;
1685 strcpy(comment,lp_serverstring());
1687 if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1688 for (i=0;i<count;i++)
1689 if (strequal(servers[i].name,local_machine))
1691 servertype = servers[i].type;
1692 strcpy(comment,servers[i].comment);
1695 if (servers) free(servers);
1697 SCVAL(p,0,MAJOR_VERSION);
1698 SCVAL(p,1,MINOR_VERSION);
1699 SIVAL(p,2,servertype);
1701 if (mdrcnt == struct_len) {
1702 SIVAL(p,6,0);
1703 } else {
1704 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1705 standard_sub(cnum,comment);
1706 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1707 p2 = skip_string(p2,1);
1710 if (uLevel > 1)
1712 return False; /* not yet implemented */
1715 *rdata_len = PTR_DIFF(p2,*rdata);
1717 *rparam_len = 6;
1718 *rparam = REALLOC(*rparam,*rparam_len);
1719 SSVAL(*rparam,0,NERR_Success);
1720 SSVAL(*rparam,2,0); /* converter word */
1721 SSVAL(*rparam,4,*rdata_len);
1723 return(True);
1727 /****************************************************************************
1728 get info about the server
1729 ****************************************************************************/
1730 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1731 int mdrcnt,int mprcnt,
1732 char **rdata,char **rparam,
1733 int *rdata_len,int *rparam_len)
1735 char *str1 = param+2;
1736 char *str2 = skip_string(str1,1);
1737 char *p = skip_string(str2,1);
1738 char *p2;
1739 extern pstring sesssetup_user;
1740 int level = SVAL(p,0);
1742 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1744 *rparam_len = 6;
1745 *rparam = REALLOC(*rparam,*rparam_len);
1747 /* check it's a supported varient */
1748 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1749 return(False);
1751 *rdata_len = mdrcnt + 1024;
1752 *rdata = REALLOC(*rdata,*rdata_len);
1754 SSVAL(*rparam,0,NERR_Success);
1755 SSVAL(*rparam,2,0); /* converter word */
1757 p = *rdata;
1758 p2 = p + 22;
1761 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1762 strcpy(p2,local_machine);
1763 strupper(p2);
1764 p2 = skip_string(p2,1);
1765 p += 4;
1767 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1768 strcpy(p2,sesssetup_user);
1769 p2 = skip_string(p2,1);
1770 p += 4;
1772 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1773 strcpy(p2,myworkgroup);
1774 strupper(p2);
1775 p2 = skip_string(p2,1);
1776 p += 4;
1778 SCVAL(p,0,MAJOR_VERSION); /* system version - e.g 4 in 4.1 */
1779 SCVAL(p,1,MINOR_VERSION); /* system version - e.g .1 in 4.1 */
1780 p += 2;
1782 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1783 strcpy(p2,myworkgroup); /* don't know. login domain?? */
1784 p2 = skip_string(p2,1);
1785 p += 4;
1787 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1788 strcpy(p2,"");
1789 p2 = skip_string(p2,1);
1790 p += 4;
1792 *rdata_len = PTR_DIFF(p2,*rdata);
1794 SSVAL(*rparam,4,*rdata_len);
1796 return(True);
1799 /****************************************************************************
1800 get info about a user
1802 struct user_info_11 {
1803 char usri11_name[21]; 0-20
1804 char usri11_pad; 21
1805 char *usri11_comment; 22-25
1806 char *usri11_usr_comment; 26-29
1807 unsigned short usri11_priv; 30-31
1808 unsigned long usri11_auth_flags; 32-35
1809 long usri11_password_age; 36-39
1810 char *usri11_homedir; 40-43
1811 char *usri11_parms; 44-47
1812 long usri11_last_logon; 48-51
1813 long usri11_last_logoff; 52-55
1814 unsigned short usri11_bad_pw_count; 56-57
1815 unsigned short usri11_num_logons; 58-59
1816 char *usri11_logon_server; 60-63
1817 unsigned short usri11_country_code; 64-65
1818 char *usri11_workstations; 66-69
1819 unsigned long usri11_max_storage; 70-73
1820 unsigned short usri11_units_per_week; 74-75
1821 unsigned char *usri11_logon_hours; 76-79
1822 unsigned short usri11_code_page; 80-81
1825 where:
1827 usri11_name specifies the user name for which information is retireved
1829 usri11_pad aligns the next data structure element to a word boundary
1831 usri11_comment is a null terminated ASCII comment
1833 usri11_user_comment is a null terminated ASCII comment about the user
1835 usri11_priv specifies the level of the privilege assigned to the user.
1836 The possible values are:
1838 Name Value Description
1839 USER_PRIV_GUEST 0 Guest privilege
1840 USER_PRIV_USER 1 User privilege
1841 USER_PRV_ADMIN 2 Administrator privilege
1843 usri11_auth_flags specifies the account operator privileges. The
1844 possible values are:
1846 Name Value Description
1847 AF_OP_PRINT 0 Print operator
1850 Leach, Naik [Page 28] \f
1853 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1856 AF_OP_COMM 1 Communications operator
1857 AF_OP_SERVER 2 Server operator
1858 AF_OP_ACCOUNTS 3 Accounts operator
1861 usri11_password_age specifies how many seconds have elapsed since the
1862 password was last changed.
1864 usri11_home_dir points to a null terminated ASCII string that contains
1865 the path name of the user's home directory.
1867 usri11_parms points to a null terminated ASCII string that is set
1868 aside for use by applications.
1870 usri11_last_logon specifies the time when the user last logged on.
1871 This value is stored as the number of seconds elapsed since
1872 00:00:00, January 1, 1970.
1874 usri11_last_logoff specifies the time when the user last logged off.
1875 This value is stored as the number of seconds elapsed since
1876 00:00:00, January 1, 1970. A value of 0 means the last logoff
1877 time is unknown.
1879 usri11_bad_pw_count specifies the number of incorrect passwords
1880 entered since the last successful logon.
1882 usri11_log1_num_logons specifies the number of times this user has
1883 logged on. A value of -1 means the number of logons is unknown.
1885 usri11_logon_server points to a null terminated ASCII string that
1886 contains the name of the server to which logon requests are sent.
1887 A null string indicates logon requests should be sent to the
1888 domain controller.
1890 usri11_country_code specifies the country code for the user's language
1891 of choice.
1893 usri11_workstations points to a null terminated ASCII string that
1894 contains the names of workstations the user may log on from.
1895 There may be up to 8 workstations, with the names separated by
1896 commas. A null strings indicates there are no restrictions.
1898 usri11_max_storage specifies the maximum amount of disk space the user
1899 can occupy. A value of 0xffffffff indicates there are no
1900 restrictions.
1902 usri11_units_per_week specifies the equal number of time units into
1903 which a week is divided. This value must be equal to 168.
1905 usri11_logon_hours points to a 21 byte (168 bits) string that
1906 specifies the time during which the user can log on. Each bit
1907 represents one unique hour in a week. The first bit (bit 0, word
1908 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
1912 Leach, Naik [Page 29] \f
1915 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1918 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
1919 are no restrictions.
1921 usri11_code_page specifies the code page for the user's language of
1922 choice
1924 All of the pointers in this data structure need to be treated
1925 specially. The pointer is a 32 bit pointer. The higher 16 bits need
1926 to be ignored. The converter word returned in the parameters section
1927 needs to be subtracted from the lower 16 bits to calculate an offset
1928 into the return buffer where this ASCII string resides.
1930 There is no auxiliary data in the response.
1932 ****************************************************************************/
1934 #define usri11_name 0
1935 #define usri11_pad 21
1936 #define usri11_comment 22
1937 #define usri11_usr_comment 26
1938 #define usri11_full_name 30
1939 #define usri11_priv 34
1940 #define usri11_auth_flags 36
1941 #define usri11_password_age 40
1942 #define usri11_homedir 44
1943 #define usri11_parms 48
1944 #define usri11_last_logon 52
1945 #define usri11_last_logoff 56
1946 #define usri11_bad_pw_count 60
1947 #define usri11_num_logons 62
1948 #define usri11_logon_server 64
1949 #define usri11_country_code 68
1950 #define usri11_workstations 70
1951 #define usri11_max_storage 74
1952 #define usri11_units_per_week 78
1953 #define usri11_logon_hours 80
1954 #define usri11_code_page 84
1955 #define usri11_end 86
1957 #define USER_PRIV_GUEST 0
1958 #define USER_PRIV_USER 1
1959 #define USER_PRIV_ADMIN 2
1961 #define AF_OP_PRINT 0
1962 #define AF_OP_COMM 1
1963 #define AF_OP_SERVER 2
1964 #define AF_OP_ACCOUNTS 3
1967 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
1968 int mdrcnt,int mprcnt,
1969 char **rdata,char **rparam,
1970 int *rdata_len,int *rparam_len)
1972 char *str1 = param+2;
1973 char *str2 = skip_string(str1,1);
1974 char *UserName = skip_string(str2,1);
1975 char *p = skip_string(UserName,1);
1976 int uLevel = SVAL(p,0);
1977 char *p2;
1979 /* get NIS home of a previously validated user - simeon */
1980 user_struct *vuser = get_valid_user_struct(vuid);
1981 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
1982 #if (defined(NETGROUP) && defined(AUTOMOUNT))
1983 DEBUG(3,(" HOMESHR for %s is %s\n", vuser->name, vuser->home_share));
1984 #endif
1986 *rparam_len = 6;
1987 *rparam = REALLOC(*rparam,*rparam_len);
1989 /* check it's a supported variant */
1990 if (strcmp(str1,"zWrLh") != 0) return False;
1991 switch( uLevel )
1993 case 0: p2 = "B21"; break;
1994 case 1: p2 = "B21BB16DWzzWz"; break;
1995 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1996 case 10: p2 = "B21Bzzz"; break;
1997 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1998 default: return False;
2001 if (strcmp(p2,str2) != 0) return False;
2003 *rdata_len = mdrcnt + 1024;
2004 *rdata = REALLOC(*rdata,*rdata_len);
2006 SSVAL(*rparam,0,NERR_Success);
2007 SSVAL(*rparam,2,0); /* converter word */
2009 p = *rdata;
2010 p2 = p + usri11_end;
2012 memset(p,0,21);
2013 strcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2015 if (uLevel > 0)
2017 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2018 *p2 = 0;
2020 if (uLevel >= 10)
2022 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2023 strcpy(p2,"Comment");
2024 p2 = skip_string(p2,1);
2026 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2027 strcpy(p2,"UserComment");
2028 p2 = skip_string(p2,1);
2030 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2031 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2032 strcpy(p2,vuser->real_name); /* simeon */
2033 p2 = skip_string(p2,1);
2036 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2038 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2039 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2040 SIVALS(p,usri11_password_age,0xffffffff); /* password age */
2041 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2042 if (*lp_logon_path())
2044 strcpy(p2,lp_logon_path());
2046 else
2048 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2049 strcpy(p2, vuser->home_share);
2050 #else
2051 strcpy(p2,"\\\\%L\\%U");
2052 #endif
2054 standard_sub_basic(p2);
2055 p2 = skip_string(p2,1);
2056 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2057 strcpy(p2,"");
2058 p2 = skip_string(p2,1);
2059 SIVAL(p,usri11_last_logon,0); /* last logon */
2060 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2061 SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */
2062 SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */
2063 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2064 strcpy(p2,"\\\\*");
2065 p2 = skip_string(p2,1);
2066 SSVAL(p,usri11_country_code,0); /* country code */
2068 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2069 strcpy(p2,"");
2070 p2 = skip_string(p2,1);
2072 SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */
2073 SSVAL(p,usri11_units_per_week,168); /* units per week */
2074 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2076 /* a simple way to get logon hours at all times. */
2077 memset(p2,0xff,21);
2078 SCVAL(p2,21,0); /* fix zero termination */
2079 p2 = skip_string(p2,1);
2081 SSVAL(p,usri11_code_page,0); /* code page */
2083 if (uLevel == 1 || uLevel == 2)
2085 memset(p+22,' ',16); /* password */
2086 SIVALS(p,38,-1); /* password age */
2087 SSVAL(p,42,
2088 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2089 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2090 if (*lp_logon_path())
2092 strcpy(p2,lp_logon_path());
2094 else
2096 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2097 strcpy(p2, vuser->home_share);
2098 #else
2099 strcpy(p2,"\\\\%L\\%U");
2100 #endif
2102 standard_sub_basic(p2);
2103 p2 = skip_string(p2,1);
2104 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2105 *p2++ = 0;
2106 SSVAL(p,52,0); /* flags */
2107 SIVAL(p,54,0); /* script_path */
2108 if (uLevel == 2)
2110 SIVAL(p,60,0); /* auth_flags */
2111 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2112 strcpy(p2,vuser->real_name); /* simeon */
2113 p2 = skip_string(p2,1);
2114 SIVAL(p,68,0); /* urs_comment */
2115 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2116 strcpy(p2,"");
2117 p2 = skip_string(p2,1);
2118 SIVAL(p,76,0); /* workstations */
2119 SIVAL(p,80,0); /* last_logon */
2120 SIVAL(p,84,0); /* last_logoff */
2121 SIVALS(p,88,-1); /* acct_expires */
2122 SIVALS(p,92,-1); /* max_storage */
2123 SSVAL(p,96,168); /* units_per_week */
2124 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2125 memset(p2,-1,21);
2126 p2 += 21;
2127 SSVALS(p,102,-1); /* bad_pw_count */
2128 SSVALS(p,104,-1); /* num_logons */
2129 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2130 strcpy(p2,"\\\\%L");
2131 standard_sub_basic(p2);
2132 p2 = skip_string(p2,1);
2133 SSVAL(p,110,49); /* country_code */
2134 SSVAL(p,112,860); /* code page */
2138 *rdata_len = PTR_DIFF(p2,*rdata);
2140 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2142 return(True);
2145 /*******************************************************************
2146 get groups that a user is a member of
2147 ******************************************************************/
2148 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2149 int mdrcnt,int mprcnt,
2150 char **rdata,char **rparam,
2151 int *rdata_len,int *rparam_len)
2153 char *str1 = param+2;
2154 char *str2 = skip_string(str1,1);
2155 char *UserName = skip_string(str2,1);
2156 char *p = skip_string(UserName,1);
2157 int uLevel = SVAL(p,0);
2158 char *p2;
2159 int count=0;
2161 *rparam_len = 8;
2162 *rparam = REALLOC(*rparam,*rparam_len);
2164 /* check it's a supported varient */
2165 if (strcmp(str1,"zWrLeh") != 0) return False;
2166 switch( uLevel ) {
2167 case 0: p2 = "B21"; break;
2168 default: return False;
2170 if (strcmp(p2,str2) != 0) return False;
2172 *rdata_len = mdrcnt + 1024;
2173 *rdata = REALLOC(*rdata,*rdata_len);
2175 SSVAL(*rparam,0,NERR_Success);
2176 SSVAL(*rparam,2,0); /* converter word */
2178 p = *rdata;
2180 /* XXXX we need a real SAM database some day */
2181 strcpy(p,"Users"); p += 21; count++;
2182 strcpy(p,"Domain Users"); p += 21; count++;
2183 strcpy(p,"Guests"); p += 21; count++;
2184 strcpy(p,"Domain Guests"); p += 21; count++;
2186 *rdata_len = PTR_DIFF(p,*rdata);
2188 SSVAL(*rparam,4,count); /* is this right?? */
2189 SSVAL(*rparam,6,count); /* is this right?? */
2191 return(True);
2195 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2196 int mdrcnt,int mprcnt,
2197 char **rdata,char **rparam,
2198 int *rdata_len,int *rparam_len)
2200 char *str1 = param+2;
2201 char *str2 = skip_string(str1,1);
2202 char *p = skip_string(str2,1);
2203 int uLevel;
2204 struct pack_desc desc;
2205 char* name;
2207 uLevel = SVAL(p,0);
2208 name = p + 2;
2210 bzero(&desc,sizeof(desc));
2212 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2214 /* check it's a supported varient */
2215 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2216 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2217 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2218 desc.base = *rdata;
2219 desc.buflen = mdrcnt;
2220 desc.subformat = NULL;
2221 desc.format = str2;
2223 if (init_package(&desc,1,0))
2225 PACKI(&desc,"W",0); /* code */
2226 PACKS(&desc,"B21",name); /* eff. name */
2227 PACKS(&desc,"B",""); /* pad */
2228 PACKI(&desc,"W",
2229 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2230 PACKI(&desc,"D",0); /* auth flags XXX */
2231 PACKI(&desc,"W",0); /* num logons */
2232 PACKI(&desc,"W",0); /* bad pw count */
2233 PACKI(&desc,"D",0); /* last logon */
2234 PACKI(&desc,"D",-1); /* last logoff */
2235 PACKI(&desc,"D",-1); /* logoff time */
2236 PACKI(&desc,"D",-1); /* kickoff time */
2237 PACKI(&desc,"D",0); /* password age */
2238 PACKI(&desc,"D",0); /* password can change */
2239 PACKI(&desc,"D",-1); /* password must change */
2241 fstring mypath;
2242 strcpy(mypath,"\\\\");
2243 strcat(mypath,local_machine);
2244 strupper(mypath);
2245 PACKS(&desc,"z",mypath); /* computer */
2247 PACKS(&desc,"z",myworkgroup);/* domain */
2248 PACKS(&desc,"z",lp_logon_script()); /* script path */
2249 PACKI(&desc,"D",0x00000000); /* reserved */
2252 *rdata_len = desc.usedlen;
2253 *rparam_len = 6;
2254 *rparam = REALLOC(*rparam,*rparam_len);
2255 SSVALS(*rparam,0,desc.errcode);
2256 SSVAL(*rparam,2,0);
2257 SSVAL(*rparam,4,desc.neededlen);
2259 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2260 return(True);
2264 /****************************************************************************
2265 api_WAccessGetUserPerms
2266 ****************************************************************************/
2267 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2268 int mdrcnt,int mprcnt,
2269 char **rdata,char **rparam,
2270 int *rdata_len,int *rparam_len)
2272 char *str1 = param+2;
2273 char *str2 = skip_string(str1,1);
2274 char *user = skip_string(str2,1);
2275 char *resource = skip_string(user,1);
2277 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2279 /* check it's a supported varient */
2280 if (strcmp(str1,"zzh") != 0) return False;
2281 if (strcmp(str2,"") != 0) return False;
2283 *rparam_len = 6;
2284 *rparam = REALLOC(*rparam,*rparam_len);
2285 SSVALS(*rparam,0,0); /* errorcode */
2286 SSVAL(*rparam,2,0); /* converter word */
2287 SSVAL(*rparam,4,0x7f); /* permission flags */
2289 return(True);
2292 /****************************************************************************
2293 api_WPrintJobEnumerate
2294 ****************************************************************************/
2295 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2296 int mdrcnt,int mprcnt,
2297 char **rdata,char **rparam,
2298 int *rdata_len,int *rparam_len)
2300 char *str1 = param+2;
2301 char *str2 = skip_string(str1,1);
2302 char *p = skip_string(str2,1);
2303 int uJobId = SVAL(p,0);
2304 int uLevel,cbBuf;
2305 int count;
2306 int i;
2307 int snum;
2308 int job;
2309 struct pack_desc desc;
2310 print_queue_struct *queue=NULL;
2311 print_status_struct status;
2313 uLevel = SVAL(p,2);
2314 cbBuf = SVAL(p,4);
2316 bzero(&desc,sizeof(desc));
2317 bzero(&status,sizeof(status));
2319 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2321 /* check it's a supported varient */
2322 if (strcmp(str1,"WWrLh") != 0) return False;
2323 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2325 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2326 job = uJobId & 0xFF;
2328 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2330 count = get_printqueue(snum,cnum,&queue,&status);
2331 for (i = 0; i < count; i++) {
2332 if ((queue[i].job % 0xFF) == job) break;
2334 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2335 desc.base = *rdata;
2336 desc.buflen = mdrcnt;
2338 if (init_package(&desc,1,0)) {
2339 if (i < count) {
2340 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2341 *rdata_len = desc.usedlen;
2343 else {
2344 desc.errcode = NERR_JobNotFound;
2345 *rdata_len = 0;
2349 *rparam_len = 6;
2350 *rparam = REALLOC(*rparam,*rparam_len);
2351 SSVALS(*rparam,0,desc.errcode);
2352 SSVAL(*rparam,2,0);
2353 SSVAL(*rparam,4,desc.neededlen);
2355 if (queue) free(queue);
2357 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2358 return(True);
2361 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2362 int mdrcnt,int mprcnt,
2363 char **rdata,char **rparam,
2364 int *rdata_len,int *rparam_len)
2366 char *str1 = param+2;
2367 char *str2 = skip_string(str1,1);
2368 char *p = skip_string(str2,1);
2369 char* name = p;
2370 int uLevel,cbBuf;
2371 int count;
2372 int i, succnt=0;
2373 int snum;
2374 struct pack_desc desc;
2375 print_queue_struct *queue=NULL;
2376 print_status_struct status;
2378 bzero(&desc,sizeof(desc));
2379 bzero(&status,sizeof(status));
2381 p = skip_string(p,1);
2382 uLevel = SVAL(p,0);
2383 cbBuf = SVAL(p,2);
2385 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2387 /* check it's a supported varient */
2388 if (strcmp(str1,"zWrLeh") != 0) return False;
2389 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2390 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2392 snum = lp_servicenumber(name);
2393 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2394 int pnum = lp_servicenumber(PRINTERS_NAME);
2395 if (pnum >= 0) {
2396 lp_add_printer(name,pnum);
2397 snum = lp_servicenumber(name);
2401 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2403 count = get_printqueue(snum,cnum,&queue,&status);
2404 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2405 desc.base = *rdata;
2406 desc.buflen = mdrcnt;
2408 if (init_package(&desc,count,0)) {
2409 succnt = 0;
2410 for (i = 0; i < count; i++) {
2411 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2412 if (desc.errcode == NERR_Success) succnt = i+1;
2416 *rdata_len = desc.usedlen;
2418 *rparam_len = 8;
2419 *rparam = REALLOC(*rparam,*rparam_len);
2420 SSVALS(*rparam,0,desc.errcode);
2421 SSVAL(*rparam,2,0);
2422 SSVAL(*rparam,4,succnt);
2423 SSVAL(*rparam,6,count);
2425 if (queue) free(queue);
2427 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2428 return(True);
2431 static int check_printdest_info(struct pack_desc* desc,
2432 int uLevel, char* id)
2434 desc->subformat = NULL;
2435 switch( uLevel ) {
2436 case 0: desc->format = "B9"; break;
2437 case 1: desc->format = "B9B21WWzW"; break;
2438 case 2: desc->format = "z"; break;
2439 case 3: desc->format = "zzzWWzzzWW"; break;
2440 default: return False;
2442 if (strcmp(desc->format,id) != 0) return False;
2443 return True;
2446 static void fill_printdest_info(int cnum, int snum, int uLevel,
2447 struct pack_desc* desc)
2449 char buf[100];
2450 strcpy(buf,SERVICE(snum));
2451 strupper(buf);
2452 if (uLevel <= 1) {
2453 PACKS(desc,"B9",buf); /* szName */
2454 if (uLevel == 1) {
2455 PACKS(desc,"B21",""); /* szUserName */
2456 PACKI(desc,"W",0); /* uJobId */
2457 PACKI(desc,"W",0); /* fsStatus */
2458 PACKS(desc,"z",""); /* pszStatus */
2459 PACKI(desc,"W",0); /* time */
2462 if (uLevel == 2 || uLevel == 3) {
2463 PACKS(desc,"z",buf); /* pszPrinterName */
2464 if (uLevel == 3) {
2465 PACKS(desc,"z",""); /* pszUserName */
2466 PACKS(desc,"z",""); /* pszLogAddr */
2467 PACKI(desc,"W",0); /* uJobId */
2468 PACKI(desc,"W",0); /* fsStatus */
2469 PACKS(desc,"z",""); /* pszStatus */
2470 PACKS(desc,"z",""); /* pszComment */
2471 PACKS(desc,"z","NULL"); /* pszDrivers */
2472 PACKI(desc,"W",0); /* time */
2473 PACKI(desc,"W",0); /* pad1 */
2478 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2479 int mdrcnt,int mprcnt,
2480 char **rdata,char **rparam,
2481 int *rdata_len,int *rparam_len)
2483 char *str1 = param+2;
2484 char *str2 = skip_string(str1,1);
2485 char *p = skip_string(str2,1);
2486 char* PrinterName = p;
2487 int uLevel,cbBuf;
2488 struct pack_desc desc;
2489 int snum;
2491 bzero(&desc,sizeof(desc));
2493 p = skip_string(p,1);
2494 uLevel = SVAL(p,0);
2495 cbBuf = SVAL(p,2);
2497 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2499 /* check it's a supported varient */
2500 if (strcmp(str1,"zWrLh") != 0) return False;
2501 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2503 snum = lp_servicenumber(PrinterName);
2504 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2505 int pnum = lp_servicenumber(PRINTERS_NAME);
2506 if (pnum >= 0) {
2507 lp_add_printer(PrinterName,pnum);
2508 snum = lp_servicenumber(PrinterName);
2512 if (snum < 0) {
2513 *rdata_len = 0;
2514 desc.errcode = NERR_DestNotFound;
2515 desc.neededlen = 0;
2517 else {
2518 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2519 desc.base = *rdata;
2520 desc.buflen = mdrcnt;
2521 if (init_package(&desc,1,0)) {
2522 fill_printdest_info(cnum,snum,uLevel,&desc);
2524 *rdata_len = desc.usedlen;
2527 *rparam_len = 6;
2528 *rparam = REALLOC(*rparam,*rparam_len);
2529 SSVALS(*rparam,0,desc.errcode);
2530 SSVAL(*rparam,2,0);
2531 SSVAL(*rparam,4,desc.neededlen);
2533 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2534 return(True);
2537 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2538 int mdrcnt,int mprcnt,
2539 char **rdata,char **rparam,
2540 int *rdata_len,int *rparam_len)
2542 char *str1 = param+2;
2543 char *str2 = skip_string(str1,1);
2544 char *p = skip_string(str2,1);
2545 int uLevel,cbBuf;
2546 int queuecnt;
2547 int i, n, succnt=0;
2548 struct pack_desc desc;
2549 int services = lp_numservices();
2551 bzero(&desc,sizeof(desc));
2553 uLevel = SVAL(p,0);
2554 cbBuf = SVAL(p,2);
2556 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2558 /* check it's a supported varient */
2559 if (strcmp(str1,"WrLeh") != 0) return False;
2560 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2562 queuecnt = 0;
2563 for (i = 0; i < services; i++)
2564 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2565 queuecnt++;
2567 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2568 desc.base = *rdata;
2569 desc.buflen = mdrcnt;
2570 if (init_package(&desc,queuecnt,0)) {
2571 succnt = 0;
2572 n = 0;
2573 for (i = 0; i < services; i++) {
2574 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2575 fill_printdest_info(cnum,i,uLevel,&desc);
2576 n++;
2577 if (desc.errcode == NERR_Success) succnt = n;
2582 *rdata_len = desc.usedlen;
2584 *rparam_len = 8;
2585 *rparam = REALLOC(*rparam,*rparam_len);
2586 SSVALS(*rparam,0,desc.errcode);
2587 SSVAL(*rparam,2,0);
2588 SSVAL(*rparam,4,succnt);
2589 SSVAL(*rparam,6,queuecnt);
2591 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2592 return(True);
2595 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2596 int mdrcnt,int mprcnt,
2597 char **rdata,char **rparam,
2598 int *rdata_len,int *rparam_len)
2600 char *str1 = param+2;
2601 char *str2 = skip_string(str1,1);
2602 char *p = skip_string(str2,1);
2603 int uLevel,cbBuf;
2604 int succnt;
2605 struct pack_desc desc;
2607 bzero(&desc,sizeof(desc));
2609 uLevel = SVAL(p,0);
2610 cbBuf = SVAL(p,2);
2612 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2614 /* check it's a supported varient */
2615 if (strcmp(str1,"WrLeh") != 0) return False;
2616 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2618 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2619 desc.base = *rdata;
2620 desc.buflen = mdrcnt;
2621 if (init_package(&desc,1,0)) {
2622 PACKS(&desc,"B41","NULL");
2625 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2627 *rdata_len = desc.usedlen;
2629 *rparam_len = 8;
2630 *rparam = REALLOC(*rparam,*rparam_len);
2631 SSVALS(*rparam,0,desc.errcode);
2632 SSVAL(*rparam,2,0);
2633 SSVAL(*rparam,4,succnt);
2634 SSVAL(*rparam,6,1);
2636 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2637 return(True);
2640 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2641 int mdrcnt,int mprcnt,
2642 char **rdata,char **rparam,
2643 int *rdata_len,int *rparam_len)
2645 char *str1 = param+2;
2646 char *str2 = skip_string(str1,1);
2647 char *p = skip_string(str2,1);
2648 int uLevel,cbBuf;
2649 int succnt;
2650 struct pack_desc desc;
2652 bzero(&desc,sizeof(desc));
2654 uLevel = SVAL(p,0);
2655 cbBuf = SVAL(p,2);
2657 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2659 /* check it's a supported varient */
2660 if (strcmp(str1,"WrLeh") != 0) return False;
2661 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2663 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2664 desc.base = *rdata;
2665 desc.buflen = mdrcnt;
2666 desc.format = str2;
2667 if (init_package(&desc,1,0)) {
2668 PACKS(&desc,"B13","lpd");
2671 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2673 *rdata_len = desc.usedlen;
2675 *rparam_len = 8;
2676 *rparam = REALLOC(*rparam,*rparam_len);
2677 SSVALS(*rparam,0,desc.errcode);
2678 SSVAL(*rparam,2,0);
2679 SSVAL(*rparam,4,succnt);
2680 SSVAL(*rparam,6,1);
2682 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2683 return(True);
2686 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2687 int mdrcnt,int mprcnt,
2688 char **rdata,char **rparam,
2689 int *rdata_len,int *rparam_len)
2691 char *str1 = param+2;
2692 char *str2 = skip_string(str1,1);
2693 char *p = skip_string(str2,1);
2694 int uLevel,cbBuf;
2695 int succnt;
2696 struct pack_desc desc;
2698 bzero(&desc,sizeof(desc));
2700 uLevel = SVAL(p,0);
2701 cbBuf = SVAL(p,2);
2703 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2705 /* check it's a supported varient */
2706 if (strcmp(str1,"WrLeh") != 0) return False;
2707 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2709 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2710 bzero(&desc,sizeof(desc));
2711 desc.base = *rdata;
2712 desc.buflen = mdrcnt;
2713 desc.format = str2;
2714 if (init_package(&desc,1,0)) {
2715 PACKS(&desc,"B13","lp0");
2718 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2720 *rdata_len = desc.usedlen;
2722 *rparam_len = 8;
2723 *rparam = REALLOC(*rparam,*rparam_len);
2724 SSVALS(*rparam,0,desc.errcode);
2725 SSVAL(*rparam,2,0);
2726 SSVAL(*rparam,4,succnt);
2727 SSVAL(*rparam,6,1);
2729 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2730 return(True);
2734 struct
2736 char * name;
2737 char * pipename;
2738 int subcommand;
2739 BOOL (*fn) ();
2740 } api_fd_commands [] =
2742 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2743 { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP },
2744 { NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2747 /****************************************************************************
2748 handle remote api calls delivered to a named pipe already opened.
2749 ****************************************************************************/
2750 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2751 uint16 *setup,char *data,char *params,
2752 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2754 char *rdata = NULL;
2755 char *rparam = NULL;
2756 int rdata_len = 0;
2757 int rparam_len = 0;
2758 BOOL reply=False;
2759 int i;
2760 int fd;
2761 int subcommand;
2763 /* First find out the name of this file. */
2764 if (suwcnt != 2)
2766 DEBUG(0,("Unexpected named pipe transaction.\n"));
2767 return(-1);
2770 /* Get the file handle and hence the file name. */
2771 fd = setup[1];
2772 subcommand = setup[0];
2774 DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2775 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2776 tdscnt,tpscnt,mdrcnt,mprcnt));
2778 for (i=0;api_fd_commands[i].name;i++)
2779 if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2780 api_fd_commands[i].subcommand == subcommand &&
2781 api_fd_commands[i].fn)
2783 DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2784 break;
2787 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2788 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2790 reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2791 &rdata,&rparam,&rdata_len,&rparam_len);
2793 if (rdata_len > mdrcnt ||
2794 rparam_len > mprcnt)
2796 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2797 &rdata,&rparam,&rdata_len,&rparam_len);
2801 /* if we get False back then it's actually unsupported */
2802 if (!reply)
2803 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2804 &rdata,&rparam,&rdata_len,&rparam_len);
2806 /* now send the reply */
2807 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2809 if (rdata)
2810 free(rdata);
2811 if (rparam)
2812 free(rparam);
2814 return(-1);
2819 /****************************************************************************
2820 the buffer was too small
2821 ****************************************************************************/
2822 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
2823 int mdrcnt,int mprcnt,
2824 char **rdata,char **rparam,
2825 int *rdata_len,int *rparam_len)
2827 *rparam_len = MIN(*rparam_len,mprcnt);
2828 *rparam = REALLOC(*rparam,*rparam_len);
2830 *rdata_len = 0;
2832 SSVAL(*rparam,0,NERR_BufTooSmall);
2834 DEBUG(3,("Supplied buffer too small in API command\n"));
2836 return(True);
2840 /****************************************************************************
2841 the request is not supported
2842 ****************************************************************************/
2843 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
2844 int mdrcnt,int mprcnt,
2845 char **rdata,char **rparam,
2846 int *rdata_len,int *rparam_len)
2848 *rparam_len = 4;
2849 *rparam = REALLOC(*rparam,*rparam_len);
2851 *rdata_len = 0;
2853 SSVAL(*rparam,0,NERR_notsupported);
2854 SSVAL(*rparam,2,0); /* converter word */
2856 DEBUG(3,("Unsupported API command\n"));
2858 return(True);
2864 struct
2866 char *name;
2867 int id;
2868 BOOL (*fn)();
2869 int flags;
2870 } api_commands[] = {
2871 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
2872 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
2873 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
2874 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
2875 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
2876 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
2877 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
2878 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
2879 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
2880 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
2881 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
2882 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
2883 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
2884 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
2885 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
2886 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
2887 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
2888 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
2889 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
2890 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
2891 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
2892 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
2893 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
2894 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
2895 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
2896 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
2899 /****************************************************************************
2900 handle remote api calls
2901 ****************************************************************************/
2902 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
2903 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2905 int api_command = SVAL(params,0);
2906 char *rdata = NULL;
2907 char *rparam = NULL;
2908 int rdata_len = 0;
2909 int rparam_len = 0;
2910 BOOL reply=False;
2911 int i;
2913 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2914 api_command,params+2,skip_string(params+2,1),
2915 tdscnt,tpscnt,mdrcnt,mprcnt));
2917 for (i=0;api_commands[i].name;i++)
2918 if (api_commands[i].id == api_command && api_commands[i].fn)
2920 DEBUG(3,("Doing %s\n",api_commands[i].name));
2921 break;
2924 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2925 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2927 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2928 &rdata,&rparam,&rdata_len,&rparam_len);
2931 if (rdata_len > mdrcnt ||
2932 rparam_len > mprcnt)
2934 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2935 &rdata,&rparam,&rdata_len,&rparam_len);
2939 /* if we get False back then it's actually unsupported */
2940 if (!reply)
2941 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2942 &rdata,&rparam,&rdata_len,&rparam_len);
2946 /* now send the reply */
2947 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2949 if (rdata)
2950 free(rdata);
2951 if (rparam)
2952 free(rparam);
2954 return(-1);
2957 /****************************************************************************
2958 handle named pipe commands
2959 ****************************************************************************/
2960 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
2961 uint16 *setup,char *data,char *params,
2962 int suwcnt,int tdscnt,int tpscnt,
2963 int msrcnt,int mdrcnt,int mprcnt)
2966 if (strequal(name,"LANMAN"))
2967 return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2969 if (strlen(name) < 1)
2970 return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
2973 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2974 name,(int)setup[0],(int)setup[1]));
2976 return(0);
2980 /****************************************************************************
2981 reply to a SMBtrans
2982 ****************************************************************************/
2983 int reply_trans(char *inbuf,char *outbuf)
2985 fstring name;
2987 char *data=NULL,*params=NULL;
2988 uint16 *setup=NULL;
2990 int outsize = 0;
2991 int cnum = SVAL(inbuf,smb_tid);
2992 uint16 vuid = SVAL(inbuf,smb_uid);
2994 int tpscnt = SVAL(inbuf,smb_vwv0);
2995 int tdscnt = SVAL(inbuf,smb_vwv1);
2996 int mprcnt = SVAL(inbuf,smb_vwv2);
2997 int mdrcnt = SVAL(inbuf,smb_vwv3);
2998 int msrcnt = CVAL(inbuf,smb_vwv4);
2999 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3000 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3001 int pscnt = SVAL(inbuf,smb_vwv9);
3002 int psoff = SVAL(inbuf,smb_vwv10);
3003 int dscnt = SVAL(inbuf,smb_vwv11);
3004 int dsoff = SVAL(inbuf,smb_vwv12);
3005 int suwcnt = CVAL(inbuf,smb_vwv13);
3007 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
3009 if (tdscnt)
3011 data = (char *)malloc(tdscnt);
3012 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3014 if (tpscnt)
3016 params = (char *)malloc(tpscnt);
3017 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3020 if (suwcnt)
3022 int i;
3023 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3024 for (i=0;i<suwcnt;i++)
3025 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3029 if (pscnt < tpscnt || dscnt < tdscnt)
3031 /* We need to send an interim response then receive the rest
3032 of the parameter/data bytes */
3033 outsize = set_message(outbuf,0,0,True);
3034 show_msg(outbuf);
3035 send_smb(Client,outbuf);
3038 /* receive the rest of the trans packet */
3039 while (pscnt < tpscnt || dscnt < tdscnt)
3041 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3043 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
3044 CVAL(inbuf, smb_com) != SMBtrans)
3046 DEBUG(2,("Invalid secondary trans2 packet\n"));
3047 if (params) free(params);
3048 if (data) free(data);
3049 if (setup) free(setup);
3050 return(ERROR(ERRSRV,ERRerror));
3053 show_msg(inbuf);
3055 tpscnt = SVAL(inbuf,smb_vwv0);
3056 tdscnt = SVAL(inbuf,smb_vwv1);
3058 pcnt = SVAL(inbuf,smb_vwv2);
3059 poff = SVAL(inbuf,smb_vwv3);
3060 pdisp = SVAL(inbuf,smb_vwv4);
3062 dcnt = SVAL(inbuf,smb_vwv5);
3063 doff = SVAL(inbuf,smb_vwv6);
3064 ddisp = SVAL(inbuf,smb_vwv7);
3066 pscnt += pcnt;
3067 dscnt += dcnt;
3069 if (pcnt)
3070 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3071 if (dcnt)
3072 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3076 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3079 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3080 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3081 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3084 if (data) free(data);
3085 if (params) free(params);
3086 if (setup) free(setup);
3088 if (close_on_completion)
3089 close_cnum(cnum,vuid);
3091 if (one_way)
3092 return(-1);
3094 if (outsize == 0)
3095 return(ERROR(ERRSRV,ERRnosupport));
3097 return(outsize);