removed all of lukes recent changes. I need to do a p2 release but
[Samba/gbeck.git] / source / smbd / ipc.c
blobdd9b9661ae8e99cc424bd72d53cd87903da8c7fe
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
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.
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.
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.
22 This file handles the named pipe and mailslot calls
23 in the SMBtrans protocol
26 #include "includes.h"
28 #ifdef CHECK_TYPES
29 #undef CHECK_TYPES
30 #endif
31 #define CHECK_TYPES 0
33 extern int DEBUGLEVEL;
34 extern int maxxmit;
35 extern files_struct Files[];
36 extern connection_struct Connections[];
38 extern fstring local_machine;
40 #define NERR_Success 0
41 #define NERR_badpass 86
42 #define NERR_notsupported 50
44 #define NERR_BASE (2100)
45 #define NERR_BufTooSmall (NERR_BASE+23)
46 #define NERR_JobNotFound (NERR_BASE+51)
47 #define NERR_DestNotFound (NERR_BASE+52)
48 #define ERROR_INVALID_LEVEL 124
49 #define ERROR_MORE_DATA 234
51 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
53 #define ACCESS_READ 0x01
54 #define ACCESS_WRITE 0x02
55 #define ACCESS_CREATE 0x04
57 #define SHPWLEN 8 /* share password length */
58 #define NNLEN 12 /* 8.3 net name length */
59 #define SNLEN 15 /* service name length */
60 #define QNLEN 12 /* queue name maximum length */
62 #define MAJOR_VERSION 4
63 #define MINOR_VERSION 1
65 extern int Client;
67 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
68 int mdrcnt,int mprcnt,
69 char **rdata,char **rparam,
70 int *rdata_len,int *rparam_len);
71 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
72 int mdrcnt,int mprcnt,
73 char **rdata,char **rparam,
74 int *rdata_len,int *rparam_len);
77 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
79 pstring buf;
80 int l;
82 if (!src || !dst || !n || !(*dst)) return(0);
84 StrnCpy(buf,src,sizeof(buf)/2);
85 string_sub(buf,"%S",lp_servicename(snum));
86 standard_sub(cnum,buf);
87 StrnCpy(*dst,buf,*n);
88 l = strlen(*dst) + 1;
89 (*dst) += l;
90 (*n) -= l;
91 return l;
94 static int CopyAndAdvance(char** dst, char* src, int* n)
96 int l;
97 if (!src || !dst || !n || !(*dst)) return(0);
98 StrnCpy(*dst,src,*n);
99 l = strlen(*dst) + 1;
100 (*dst) += l;
101 (*n) -= l;
102 return l;
105 static int StrlenExpanded(int cnum, int snum, char* s)
107 pstring buf;
108 if (!s) return(0);
109 StrnCpy(buf,s,sizeof(buf)/2);
110 string_sub(buf,"%S",lp_servicename(snum));
111 standard_sub(cnum,buf);
112 return strlen(buf) + 1;
115 static char* Expand(int cnum, int snum, char* s)
117 static pstring buf;
118 if (!s) return(NULL);
119 StrnCpy(buf,s,sizeof(buf)/2);
120 string_sub(buf,"%S",lp_servicename(snum));
121 standard_sub(cnum,buf);
122 return &buf[0];
125 /*******************************************************************
126 check a API string for validity when we only need to check the prefix
127 ******************************************************************/
128 static BOOL prefix_ok(char *str,char *prefix)
130 return(strncmp(str,prefix,strlen(prefix)) == 0);
134 /****************************************************************************
135 send a trans reply
136 ****************************************************************************/
137 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
138 int ldata,int lparam,int lsetup)
140 int i;
141 int this_ldata,this_lparam;
142 int tot_data=0,tot_param=0;
143 int align;
145 this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */
146 this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam));
148 align = (this_lparam%4);
150 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
151 if (this_lparam)
152 memcpy(smb_buf(outbuf),param,this_lparam);
153 if (this_ldata)
154 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
156 SSVAL(outbuf,smb_vwv0,lparam);
157 SSVAL(outbuf,smb_vwv1,ldata);
158 SSVAL(outbuf,smb_vwv3,this_lparam);
159 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
160 SSVAL(outbuf,smb_vwv5,0);
161 SSVAL(outbuf,smb_vwv6,this_ldata);
162 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
163 SSVAL(outbuf,smb_vwv8,0);
164 SSVAL(outbuf,smb_vwv9,lsetup);
165 for (i=0;i<lsetup;i++)
166 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
168 show_msg(outbuf);
169 send_smb(Client,outbuf);
171 tot_data = this_ldata;
172 tot_param = this_lparam;
174 while (tot_data < ldata || tot_param < lparam)
176 this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
177 this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
179 align = (this_lparam%4);
181 set_message(outbuf,10,this_ldata+this_lparam+align,False);
182 if (this_lparam)
183 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
184 if (this_ldata)
185 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
187 SSVAL(outbuf,smb_vwv3,this_lparam);
188 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
189 SSVAL(outbuf,smb_vwv5,tot_param);
190 SSVAL(outbuf,smb_vwv6,this_ldata);
191 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
192 SSVAL(outbuf,smb_vwv8,tot_data);
193 SSVAL(outbuf,smb_vwv9,0);
195 show_msg(outbuf);
196 send_smb(Client,outbuf);
198 tot_data += this_ldata;
199 tot_param += this_lparam;
203 struct pack_desc {
204 char* format; /* formatstring for structure */
205 char* subformat; /* subformat for structure */
206 char* base; /* baseaddress of buffer */
207 int buflen; /* remaining size for fixed part; on init: length of base */
208 int subcount; /* count of substructures */
209 char* structbuf; /* pointer into buffer for remaining fixed part */
210 int stringlen; /* remaining size for variable part */
211 char* stringbuf; /* pointer into buffer for remaining variable part */
212 int neededlen; /* total needed size */
213 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
214 char* curpos; /* current position; pointer into format or subformat */
215 int errcode;
218 static int get_counter(char** p)
220 int i, n;
221 if (!p || !(*p)) return(1);
222 if (!isdigit(**p)) return 1;
223 for (n = 0;;) {
224 i = **p;
225 if (isdigit(i))
226 n = 10 * n + (i - '0');
227 else
228 return n;
229 (*p)++;
233 static int getlen(char* p)
235 int n = 0;
236 if (!p) return(0);
237 while (*p) {
238 switch( *p++ ) {
239 case 'W': /* word (2 byte) */
240 n += 2;
241 break;
242 case 'N': /* count of substructures (word) at end */
243 n += 2;
244 break;
245 case 'D': /* double word (4 byte) */
246 case 'z': /* offset to zero terminated string (4 byte) */
247 case 'l': /* offset to user data (4 byte) */
248 n += 4;
249 break;
250 case 'b': /* offset to data (with counter) (4 byte) */
251 n += 4;
252 get_counter(&p);
253 break;
254 case 'B': /* byte (with optional counter) */
255 n += get_counter(&p);
256 break;
259 return n;
262 static BOOL init_package(struct pack_desc* p, int count, int subcount)
264 int n = p->buflen;
265 int i;
267 if (!p->format || !p->base) return(False);
269 i = count * getlen(p->format);
270 if (p->subformat) i += subcount * getlen(p->subformat);
271 p->structbuf = p->base;
272 p->neededlen = 0;
273 p->usedlen = 0;
274 p->subcount = 0;
275 p->curpos = p->format;
276 if (i > n) {
277 i = n = 0;
278 p->errcode = NERR_BufTooSmall;
281 p->errcode = NERR_Success;
282 p->buflen = i;
283 n -= i;
284 p->stringbuf = p->base + i;
285 p->stringlen = n;
286 return(p->errcode == NERR_Success);
289 #ifdef __STDC__
290 static int package(struct pack_desc* p, ...)
292 #else
293 static int package(va_alist)
294 va_dcl
296 struct pack_desc* p;
297 #endif
298 va_list args;
299 int needed=0, stringneeded;
300 char* str=NULL;
301 int is_string=0, stringused;
302 int32 temp;
304 #ifdef __STDC__
305 va_start(args,p);
306 #else
307 va_start(args);
308 p = va_arg(args,struct pack_desc *);
309 #endif
311 if (!*p->curpos) {
312 if (!p->subcount)
313 p->curpos = p->format;
314 else {
315 p->curpos = p->subformat;
316 p->subcount--;
319 #if CHECK_TYPES
320 str = va_arg(args,char*);
321 if (strncmp(str,p->curpos,strlen(str)) != 0) {
322 DEBUG(2,("type error in package: %s instead of %*s\n",str,
323 strlen(str),p->curpos));
324 va_end(args);
325 #if AJT
326 ajt_panic();
327 #endif
328 return 0;
330 #endif
331 stringneeded = -1;
333 if (!p->curpos) return(0);
335 switch( *p->curpos++ ) {
336 case 'W': /* word (2 byte) */
337 needed = 2;
338 temp = va_arg(args,int);
339 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
340 break;
341 case 'N': /* count of substructures (word) at end */
342 needed = 2;
343 p->subcount = va_arg(args,int);
344 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
345 break;
346 case 'D': /* double word (4 byte) */
347 needed = 4;
348 temp = va_arg(args,int);
349 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
350 break;
351 case 'B': /* byte (with optional counter) */
352 needed = get_counter(&p->curpos);
354 char *s = va_arg(args,char*);
355 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
357 break;
358 case 'z': /* offset to zero terminated string (4 byte) */
359 str = va_arg(args,char*);
360 stringneeded = (str ? strlen(str)+1 : 0);
361 is_string = 1;
362 break;
363 case 'l': /* offset to user data (4 byte) */
364 str = va_arg(args,char*);
365 stringneeded = va_arg(args,int);
366 is_string = 0;
367 break;
368 case 'b': /* offset to data (with counter) (4 byte) */
369 str = va_arg(args,char*);
370 stringneeded = get_counter(&p->curpos);
371 is_string = 0;
372 break;
374 va_end(args);
375 if (stringneeded >= 0) {
376 needed = 4;
377 if (p->buflen >= needed) {
378 stringused = stringneeded;
379 if (stringused > p->stringlen) {
380 stringused = (is_string ? p->stringlen : 0);
381 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
383 if (!stringused)
384 SIVAL(p->structbuf,0,0);
385 else {
386 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
387 memcpy(p->stringbuf,str?str:"",stringused);
388 if (is_string) p->stringbuf[stringused-1] = '\0';
389 p->stringbuf += stringused;
390 p->stringlen -= stringused;
391 p->usedlen += stringused;
394 p->neededlen += stringneeded;
396 p->neededlen += needed;
397 if (p->buflen >= needed) {
398 p->structbuf += needed;
399 p->buflen -= needed;
400 p->usedlen += needed;
402 else {
403 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
405 return 1;
408 #if CHECK_TYPES
409 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
410 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
411 #else
412 #define PACK(desc,t,v) package(desc,v)
413 #define PACKl(desc,t,v,l) package(desc,v,l)
414 #endif
416 static void PACKI(struct pack_desc* desc,char *t,int v)
418 PACK(desc,t,v);
421 static void PACKS(struct pack_desc* desc,char *t,char *v)
423 PACK(desc,t,v);
427 /****************************************************************************
428 get a print queue
429 ****************************************************************************/
431 static void PackDriverData(struct pack_desc* desc)
433 char drivdata[4+4+32];
434 SIVAL(drivdata,0,sizeof drivdata); /* cb */
435 SIVAL(drivdata,4,1000); /* lVersion */
436 memset(drivdata+8,0,32); /* szDeviceName */
437 strcpy(drivdata+8,"NULL");
438 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
441 static int check_printq_info(struct pack_desc* desc,
442 int uLevel, const char* id1, const char* id2)
444 desc->subformat = NULL;
445 switch( uLevel ) {
446 case 0:
447 desc->format = "B13";
448 break;
449 case 1:
450 desc->format = "B13BWWWzzzzzWW";
451 break;
452 case 2:
453 desc->format = "B13BWWWzzzzzWN";
454 desc->subformat = "WB21BB16B10zWWzDDz";
455 break;
456 case 3:
457 desc->format = "zWWWWzzzzWWzzl";
458 break;
459 case 4:
460 desc->format = "zWWWWzzzzWNzzl";
461 desc->subformat = "WWzWWDDzz";
462 break;
463 case 5:
464 desc->format = "z";
465 break;
466 default: return False;
468 if (strcmp(desc->format,id1) != 0) return False;
469 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
470 return True;
473 static void fill_printjob_info(int cnum, int snum, int uLevel,
474 struct pack_desc* desc,
475 print_queue_struct* queue, int n)
477 time_t t = queue->time;
479 /* the client expects localtime */
480 t -= TimeDiff(t);
482 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
483 if (uLevel == 1) {
484 PACKS(desc,"B21",queue->user); /* szUserName */
485 PACKS(desc,"B",""); /* pad */
486 PACKS(desc,"B16",""); /* szNotifyName */
487 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
488 PACKS(desc,"z",""); /* pszParms */
489 PACKI(desc,"W",n+1); /* uPosition */
490 PACKI(desc,"W",queue->status); /* fsStatus */
491 PACKS(desc,"z",""); /* pszStatus */
492 PACKI(desc,"D",t); /* ulSubmitted */
493 PACKI(desc,"D",queue->size); /* ulSize */
494 PACKS(desc,"z",queue->file); /* pszComment */
496 if (uLevel == 2 || uLevel == 3) {
497 PACKI(desc,"W",queue->priority); /* uPriority */
498 PACKS(desc,"z",queue->user); /* pszUserName */
499 PACKI(desc,"W",n+1); /* uPosition */
500 PACKI(desc,"W",queue->status); /* fsStatus */
501 PACKI(desc,"D",t); /* ulSubmitted */
502 PACKI(desc,"D",queue->size); /* ulSize */
503 PACKS(desc,"z","Samba"); /* pszComment */
504 PACKS(desc,"z",queue->file); /* pszDocument */
505 if (uLevel == 3) {
506 PACKS(desc,"z",""); /* pszNotifyName */
507 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
508 PACKS(desc,"z",""); /* pszParms */
509 PACKS(desc,"z",""); /* pszStatus */
510 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
511 PACKS(desc,"z","lpd"); /* pszQProcName */
512 PACKS(desc,"z",""); /* pszQProcParms */
513 PACKS(desc,"z","NULL"); /* pszDriverName */
514 PackDriverData(desc); /* pDriverData */
515 PACKS(desc,"z",""); /* pszPrinterName */
520 static void fill_printq_info(int cnum, int snum, int uLevel,
521 struct pack_desc* desc,
522 int count, print_queue_struct* queue,
523 print_status_struct* status)
525 if (uLevel < 3) {
526 PACKS(desc,"B13",SERVICE(snum));
527 } else {
528 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
530 if (uLevel == 1 || uLevel == 2) {
531 PACKS(desc,"B",""); /* alignment */
532 PACKI(desc,"W",5); /* priority */
533 PACKI(desc,"W",0); /* start time */
534 PACKI(desc,"W",0); /* until time */
535 PACKS(desc,"z",""); /* pSepFile */
536 PACKS(desc,"z","lpd"); /* pPrProc */
537 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
538 PACKS(desc,"z",""); /* pParms */
539 if (snum < 0) {
540 PACKS(desc,"z","UNKNOWN PRINTER");
541 PACKI(desc,"W",LPSTAT_ERROR);
543 else if (!status || !status->message[0]) {
544 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
545 PACKI(desc,"W",LPSTAT_OK); /* status */
546 } else {
547 PACKS(desc,"z",status->message);
548 PACKI(desc,"W",status->status); /* status */
550 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
552 if (uLevel == 3 || uLevel == 4) {
553 PACKI(desc,"W",5); /* uPriority */
554 PACKI(desc,"W",0); /* uStarttime */
555 PACKI(desc,"W",0); /* uUntiltime */
556 PACKI(desc,"W",5); /* pad1 */
557 PACKS(desc,"z",""); /* pszSepFile */
558 PACKS(desc,"z","WinPrint"); /* pszPrProc */
559 PACKS(desc,"z",""); /* pszParms */
560 if (!status || !status->message[0]) {
561 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
562 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
563 } else {
564 PACKS(desc,"z",status->message); /* pszComment */
565 PACKI(desc,"W",status->status); /* fsStatus */
567 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
568 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
569 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
570 PackDriverData(desc); /* pDriverData */
572 if (uLevel == 2 || uLevel == 4) {
573 int i;
574 for (i=0;i<count;i++)
575 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
578 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
581 static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
582 int mdrcnt,int mprcnt,
583 char **rdata,char **rparam,
584 int *rdata_len,int *rparam_len)
586 char *str1 = param+2;
587 char *str2 = skip_string(str1,1);
588 char *p = skip_string(str2,1);
589 char *QueueName = p;
590 int uLevel,cbBuf;
591 int count=0;
592 int snum;
593 char* str3;
594 struct pack_desc desc;
595 print_queue_struct *queue=NULL;
596 print_status_struct status;
598 bzero(&status,sizeof(status));
599 bzero(&desc,sizeof(desc));
601 p = skip_string(p,1);
602 uLevel = SVAL(p,0);
603 cbBuf = SVAL(p,2);
604 str3 = p + 4;
606 /* remove any trailing username */
607 if ((p = strchr(QueueName,'%'))) *p = 0;
609 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
611 /* check it's a supported varient */
612 if (!prefix_ok(str1,"zWrLh")) return False;
613 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
615 snum = lp_servicenumber(QueueName);
616 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
617 int pnum = lp_servicenumber(PRINTERS_NAME);
618 if (pnum >= 0) {
619 lp_add_printer(QueueName,pnum);
620 snum = lp_servicenumber(QueueName);
624 if (snum < 0 || !VALID_SNUM(snum)) return(False);
626 count = get_printqueue(snum,cnum,&queue,&status);
627 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
628 desc.base = *rdata;
629 desc.buflen = mdrcnt;
630 if (init_package(&desc,1,count)) {
631 desc.subcount = count;
632 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
635 *rdata_len = desc.usedlen;
637 *rparam_len = 6;
638 *rparam = REALLOC(*rparam,*rparam_len);
639 SSVALS(*rparam,0,desc.errcode);
640 SSVAL(*rparam,2,0);
641 SSVAL(*rparam,4,desc.neededlen);
643 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
645 if (queue) free(queue);
647 return(True);
651 /****************************************************************************
652 view list of all print jobs on all queues
653 ****************************************************************************/
654 static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
655 int mdrcnt, int mprcnt,
656 char **rdata, char** rparam,
657 int *rdata_len, int *rparam_len)
659 char *param_format = param+2;
660 char *output_format1 = skip_string(param_format,1);
661 char *p = skip_string(output_format1,1);
662 int uLevel = SVAL(p,0);
663 char *output_format2 = p + 4;
664 int services = lp_numservices();
665 int i, n;
666 struct pack_desc desc;
667 print_queue_struct **queue = NULL;
668 print_status_struct *status = NULL;
669 int* subcntarr = NULL;
670 int queuecnt, subcnt=0, succnt=0;
672 bzero(&desc,sizeof(desc));
674 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
676 if (!prefix_ok(param_format,"WrLeh")) return False;
677 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
678 return False;
679 queuecnt = 0;
680 for (i = 0; i < services; i++)
681 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
682 queuecnt++;
683 if (uLevel > 0) {
684 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
685 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
686 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
687 memset(status,0,queuecnt*sizeof(print_status_struct));
688 subcntarr = (int*)malloc(queuecnt*sizeof(int));
689 subcnt = 0;
690 n = 0;
691 for (i = 0; i < services; i++)
692 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
693 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
694 subcnt += subcntarr[n];
695 n++;
698 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
699 desc.base = *rdata;
700 desc.buflen = mdrcnt;
702 if (init_package(&desc,queuecnt,subcnt)) {
703 n = 0;
704 succnt = 0;
705 for (i = 0; i < services; i++)
706 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
707 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
708 n++;
709 if (desc.errcode == NERR_Success) succnt = n;
713 if (subcntarr) free(subcntarr);
715 *rdata_len = desc.usedlen;
716 *rparam_len = 8;
717 *rparam = REALLOC(*rparam,*rparam_len);
718 SSVALS(*rparam,0,desc.errcode);
719 SSVAL(*rparam,2,0);
720 SSVAL(*rparam,4,succnt);
721 SSVAL(*rparam,6,queuecnt);
723 for (i = 0; i < queuecnt; i++) {
724 if (queue && queue[i]) free(queue[i]);
727 if (queue) free(queue);
728 if (status) free(status);
730 return True;
733 /****************************************************************************
734 get info level for a server list query
735 ****************************************************************************/
736 static BOOL check_server_info(int uLevel, char* id)
738 switch( uLevel ) {
739 case 0:
740 if (strcmp(id,"B16") != 0) return False;
741 break;
742 case 1:
743 if (strcmp(id,"B16BBDz") != 0) return False;
744 break;
745 default:
746 return False;
748 return True;
751 struct srv_info_struct
753 fstring name;
754 uint32 type;
755 fstring comment;
756 fstring domain;
757 BOOL server_added;
761 /*******************************************************************
762 get server info lists from the files saved by nmbd. Return the
763 number of entries
764 ******************************************************************/
765 static int get_server_info(uint32 servertype,
766 struct srv_info_struct **servers,
767 char *domain)
769 FILE *f;
770 pstring fname;
771 int count=0;
772 int alloced=0;
773 pstring line;
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) servertype &= ~SV_TYPE_DOMAIN_ENUM;
790 DEBUG(4,("Servertype search: %8x\n",servertype));
792 while (!feof(f))
794 fstring stype;
795 struct srv_info_struct *s;
796 char *ptr = line;
797 BOOL ok = True;
798 *ptr = 0;
800 fgets(line,sizeof(line)-1,f);
801 if (!*line) continue;
803 if (count == alloced) {
804 alloced += 10;
805 (*servers) = (struct srv_info_struct *)
806 Realloc(*servers,sizeof(**servers)*alloced);
807 if (!(*servers)) return(0);
808 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
810 s = &(*servers)[count];
812 if (!next_token(&ptr,s->name , NULL)) continue;
813 if (!next_token(&ptr,stype , NULL)) continue;
814 if (!next_token(&ptr,s->comment, NULL)) continue;
815 if (!next_token(&ptr,s->domain , NULL)) {
816 /* this allows us to cope with an old nmbd */
817 strcpy(s->domain,lp_workgroup());
820 if (sscanf(stype,"%X",&s->type) != 1) {
821 DEBUG(4,("r:host file "));
822 ok = False;
825 /* doesn't match up: don't want it */
826 if (!(servertype & s->type)) {
827 DEBUG(4,("r:serv type "));
828 ok = False;
831 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
832 (s->type & SV_TYPE_DOMAIN_ENUM))
834 DEBUG(4,("s: dom mismatch "));
835 ok = False;
838 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
840 ok = False;
843 if (ok)
845 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
846 s->name, s->type, s->comment, s->domain));
848 s->server_added = True;
849 count++;
851 else
853 DEBUG(4,("%20s %8x %25s %15s\n",
854 s->name, s->type, s->comment, s->domain));
858 fclose(f);
859 return(count);
863 /*******************************************************************
864 fill in a server info structure
865 ******************************************************************/
866 static int fill_srv_info(struct srv_info_struct *service,
867 int uLevel, char **buf, int *buflen,
868 char **stringbuf, int *stringspace, char *baseaddr)
870 int struct_len;
871 char* p;
872 char* p2;
873 int l2;
874 int len;
876 switch (uLevel) {
877 case 0: struct_len = 16; break;
878 case 1: struct_len = 26; break;
879 default: return -1;
882 if (!buf)
884 len = 0;
885 switch (uLevel)
887 case 1:
888 len = strlen(service->comment)+1;
889 break;
892 if (buflen) *buflen = struct_len;
893 if (stringspace) *stringspace = len;
894 return struct_len + len;
897 len = struct_len;
898 p = *buf;
899 if (*buflen < struct_len) return -1;
900 if (stringbuf)
902 p2 = *stringbuf;
903 l2 = *stringspace;
905 else
907 p2 = p + struct_len;
908 l2 = *buflen - struct_len;
910 if (!baseaddr) baseaddr = p;
912 switch (uLevel)
914 case 0:
915 StrnCpy(p,service->name,15);
916 break;
918 case 1:
919 StrnCpy(p,service->name,15);
920 SIVAL(p,18,service->type);
921 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
922 len += CopyAndAdvance(&p2,service->comment,&l2);
923 break;
926 if (stringbuf)
928 *buf = p + struct_len;
929 *buflen -= struct_len;
930 *stringbuf = p2;
931 *stringspace = l2;
933 else
935 *buf = p2;
936 *buflen -= len;
938 return len;
942 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
944 return(strcmp(s1->name,s2->name));
947 /****************************************************************************
948 view list of servers available (or possibly domains). The info is
949 extracted from lists saved by nmbd on the local host
950 ****************************************************************************/
951 static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
952 int mdrcnt, int mprcnt, char **rdata,
953 char **rparam, int *rdata_len, int *rparam_len)
955 char *str1 = param+2;
956 char *str2 = skip_string(str1,1);
957 char *p = skip_string(str2,1);
958 int uLevel = SVAL(p,0);
959 int buf_len = SVAL(p,2);
960 uint32 servertype = IVAL(p,4);
961 char *p2;
962 int data_len, fixed_len, string_len;
963 int f_len, s_len;
964 struct srv_info_struct *servers=NULL;
965 int counted=0,total=0;
966 int i,missed;
967 fstring domain;
968 BOOL domain_request;
969 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
971 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
973 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
975 p += 8;
977 if (!prefix_ok(str1,"WrLehD")) return False;
978 if (!check_server_info(uLevel,str2)) return False;
980 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
981 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
982 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
984 if (strcmp(str1, "WrLehDz") == 0) {
985 StrnCpy(domain, p, sizeof(fstring)-1);
986 } else {
987 StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1);
990 if (lp_browse_list())
991 total = get_server_info(servertype,&servers,domain);
993 data_len = fixed_len = string_len = 0;
994 missed = 0;
996 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
999 char *lastname=NULL;
1001 for (i=0;i<total;i++)
1003 struct srv_info_struct *s = &servers[i];
1004 if (lastname && strequal(lastname,s->name)) continue;
1005 lastname = s->name;
1006 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1007 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1008 s->name, s->type, s->comment, s->domain));
1010 if (data_len <= buf_len) {
1011 counted++;
1012 fixed_len += f_len;
1013 string_len += s_len;
1014 } else {
1015 missed++;
1020 *rdata_len = fixed_len + string_len;
1021 *rdata = REALLOC(*rdata,*rdata_len);
1022 bzero(*rdata,*rdata_len);
1024 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1025 p = *rdata;
1026 f_len = fixed_len;
1027 s_len = string_len;
1030 char *lastname=NULL;
1031 int count2 = counted;
1032 for (i = 0; i < total && count2;i++)
1034 struct srv_info_struct *s = &servers[i];
1035 if (lastname && strequal(lastname,s->name)) continue;
1036 lastname = s->name;
1037 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1038 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1039 s->name, s->type, s->comment, s->domain));
1040 count2--;
1044 *rparam_len = 8;
1045 *rparam = REALLOC(*rparam,*rparam_len);
1046 SSVAL(*rparam,0,NERR_Success);
1047 SSVAL(*rparam,2,0);
1048 SSVAL(*rparam,4,counted);
1049 SSVAL(*rparam,6,counted+missed);
1051 if (servers) free(servers);
1053 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1054 domain,uLevel,counted,counted+missed));
1056 return(True);
1060 /****************************************************************************
1061 get info about a share
1062 ****************************************************************************/
1063 static BOOL check_share_info(int uLevel, char* id)
1065 switch( uLevel ) {
1066 case 0:
1067 if (strcmp(id,"B13") != 0) return False;
1068 break;
1069 case 1:
1070 if (strcmp(id,"B13BWz") != 0) return False;
1071 break;
1072 case 2:
1073 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1074 break;
1075 case 91:
1076 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1077 break;
1078 default: return False;
1080 return True;
1083 static int fill_share_info(int cnum, int snum, int uLevel,
1084 char** buf, int* buflen,
1085 char** stringbuf, int* stringspace, char* baseaddr)
1087 int struct_len;
1088 char* p;
1089 char* p2;
1090 int l2;
1091 int len;
1093 switch( uLevel ) {
1094 case 0: struct_len = 13; break;
1095 case 1: struct_len = 20; break;
1096 case 2: struct_len = 40; break;
1097 case 91: struct_len = 68; break;
1098 default: return -1;
1102 if (!buf)
1104 len = 0;
1105 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1106 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1107 if (buflen) *buflen = struct_len;
1108 if (stringspace) *stringspace = len;
1109 return struct_len + len;
1112 len = struct_len;
1113 p = *buf;
1114 if ((*buflen) < struct_len) return -1;
1115 if (stringbuf)
1117 p2 = *stringbuf;
1118 l2 = *stringspace;
1120 else
1122 p2 = p + struct_len;
1123 l2 = (*buflen) - struct_len;
1125 if (!baseaddr) baseaddr = p;
1127 StrnCpy(p,lp_servicename(snum),13);
1129 if (uLevel > 0)
1131 int type;
1132 CVAL(p,13) = 0;
1133 type = STYPE_DISKTREE;
1134 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1135 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1136 SSVAL(p,14,type); /* device type */
1137 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1138 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1141 if (uLevel > 1)
1143 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1144 SSVALS(p,22,-1); /* max uses */
1145 SSVAL(p,24,1); /* current uses */
1146 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1147 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1148 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1151 if (uLevel > 2)
1153 memset(p+40,0,SHPWLEN+2);
1154 SSVAL(p,50,0);
1155 SIVAL(p,52,0);
1156 SSVAL(p,56,0);
1157 SSVAL(p,58,0);
1158 SIVAL(p,60,0);
1159 SSVAL(p,64,0);
1160 SSVAL(p,66,0);
1163 if (stringbuf)
1165 (*buf) = p + struct_len;
1166 (*buflen) -= struct_len;
1167 (*stringbuf) = p2;
1168 (*stringspace) = l2;
1170 else
1172 (*buf) = p2;
1173 (*buflen) -= len;
1175 return len;
1178 static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
1179 int mdrcnt,int mprcnt,
1180 char **rdata,char **rparam,
1181 int *rdata_len,int *rparam_len)
1183 char *str1 = param+2;
1184 char *str2 = skip_string(str1,1);
1185 char *netname = skip_string(str2,1);
1186 char *p = skip_string(netname,1);
1187 int uLevel = SVAL(p,0);
1188 int snum = find_service(netname);
1190 if (snum < 0) return False;
1192 /* check it's a supported varient */
1193 if (!prefix_ok(str1,"zWrLh")) return False;
1194 if (!check_share_info(uLevel,str2)) return False;
1196 *rdata = REALLOC(*rdata,mdrcnt);
1197 p = *rdata;
1198 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1199 if (*rdata_len < 0) return False;
1201 *rparam_len = 6;
1202 *rparam = REALLOC(*rparam,*rparam_len);
1203 SSVAL(*rparam,0,NERR_Success);
1204 SSVAL(*rparam,2,0); /* converter word */
1205 SSVAL(*rparam,4,*rdata_len);
1207 return(True);
1210 /****************************************************************************
1211 view list of shares available
1212 ****************************************************************************/
1213 static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
1214 int mdrcnt,int mprcnt,
1215 char **rdata,char **rparam,
1216 int *rdata_len,int *rparam_len)
1218 char *str1 = param+2;
1219 char *str2 = skip_string(str1,1);
1220 char *p = skip_string(str2,1);
1221 int uLevel = SVAL(p,0);
1222 int buf_len = SVAL(p,2);
1223 char *p2;
1224 int count=lp_numservices();
1225 int total=0,counted=0;
1226 int i;
1227 int data_len, fixed_len, string_len;
1228 int f_len, s_len;
1230 if (!prefix_ok(str1,"WrLeh")) return False;
1231 if (!check_share_info(uLevel,str2)) return False;
1233 data_len = fixed_len = string_len = 0;
1234 for (i=0;i<count;i++)
1235 if (lp_browseable(i) && lp_snum_ok(i))
1237 total++;
1238 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1239 if (data_len <= buf_len)
1241 counted++;
1242 fixed_len += f_len;
1243 string_len += s_len;
1246 *rdata_len = fixed_len + string_len;
1247 *rdata = REALLOC(*rdata,*rdata_len);
1248 memset(*rdata,0,*rdata_len);
1250 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1251 p = *rdata;
1252 f_len = fixed_len;
1253 s_len = string_len;
1254 for (i = 0; i < count;i++)
1255 if (lp_browseable(i) && lp_snum_ok(i))
1256 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1257 break;
1259 *rparam_len = 8;
1260 *rparam = REALLOC(*rparam,*rparam_len);
1261 SSVAL(*rparam,0,NERR_Success);
1262 SSVAL(*rparam,2,0);
1263 SSVAL(*rparam,4,counted);
1264 SSVAL(*rparam,6,total);
1266 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1267 counted,total,uLevel,
1268 buf_len,*rdata_len,mdrcnt));
1269 return(True);
1274 /****************************************************************************
1275 get the time of day info
1276 ****************************************************************************/
1277 static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
1278 int mdrcnt,int mprcnt,
1279 char **rdata,char **rparam,
1280 int *rdata_len,int *rparam_len)
1282 char *p;
1283 *rparam_len = 4;
1284 *rparam = REALLOC(*rparam,*rparam_len);
1286 *rdata_len = 21;
1287 *rdata = REALLOC(*rdata,*rdata_len);
1289 SSVAL(*rparam,0,NERR_Success);
1290 SSVAL(*rparam,2,0); /* converter word */
1292 p = *rdata;
1295 struct tm *t;
1296 time_t unixdate = time(NULL);
1298 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1299 by NT in a "net time" operation,
1300 it seems to ignore the one below */
1302 /* the client expects to get localtime, not GMT, in this bit
1303 (I think, this needs testing) */
1304 t = LocalTime(&unixdate);
1306 SIVAL(p,4,0); /* msecs ? */
1307 CVAL(p,8) = t->tm_hour;
1308 CVAL(p,9) = t->tm_min;
1309 CVAL(p,10) = t->tm_sec;
1310 CVAL(p,11) = 0; /* hundredths of seconds */
1311 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1312 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1313 CVAL(p,16) = t->tm_mday;
1314 CVAL(p,17) = t->tm_mon + 1;
1315 SSVAL(p,18,1900+t->tm_year);
1316 CVAL(p,20) = t->tm_wday;
1320 return(True);
1323 /****************************************************************************
1324 set the user password
1325 ****************************************************************************/
1326 static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
1327 int mdrcnt,int mprcnt,
1328 char **rdata,char **rparam,
1329 int *rdata_len,int *rparam_len)
1331 char *p = skip_string(param+2,2);
1332 fstring user;
1333 fstring pass1,pass2;
1335 strcpy(user,p);
1337 p = skip_string(p,1);
1339 StrnCpy(pass1,p,16);
1340 StrnCpy(pass2,p+16,16);
1342 *rparam_len = 4;
1343 *rparam = REALLOC(*rparam,*rparam_len);
1345 *rdata_len = 0;
1347 SSVAL(*rparam,0,NERR_badpass);
1348 SSVAL(*rparam,2,0); /* converter word */
1350 DEBUG(3,("Set password for <%s>\n",user));
1352 if (password_ok(user,pass1,strlen(pass1),NULL,False) &&
1353 chgpasswd(user,pass1,pass2))
1355 SSVAL(*rparam,0,NERR_Success);
1358 bzero(pass1,sizeof(fstring));
1359 bzero(pass2,sizeof(fstring));
1361 return(True);
1364 /****************************************************************************
1365 delete a print job
1366 Form: <W> <>
1367 ****************************************************************************/
1368 static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
1369 int mdrcnt,int mprcnt,
1370 char **rdata,char **rparam,
1371 int *rdata_len,int *rparam_len)
1373 int function = SVAL(param,0);
1374 char *str1 = param+2;
1375 char *str2 = skip_string(str1,1);
1376 char *p = skip_string(str2,1);
1377 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1378 by the print queue api */
1379 int snum = (SVAL(p,0)>>8);
1380 int i, count;
1383 /* check it's a supported varient */
1384 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1385 return(False);
1387 *rparam_len = 4;
1388 *rparam = REALLOC(*rparam,*rparam_len);
1390 *rdata_len = 0;
1392 SSVAL(*rparam,0,NERR_Success);
1394 if (snum >= 0 && VALID_SNUM(snum))
1396 print_queue_struct *queue=NULL;
1397 lpq_reset(snum);
1398 count = get_printqueue(snum,cnum,&queue,NULL);
1400 for (i=0;i<count;i++)
1401 if ((queue[i].job%0xFF) == jobid)
1403 switch (function) {
1404 case 81: /* delete */
1405 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1406 del_printqueue(cnum,snum,queue[i].job);
1407 break;
1408 case 82: /* pause */
1409 case 83: /* resume */
1410 DEBUG(3,("%s queue entry %d\n",
1411 (function==82?"pausing":"resuming"),queue[i].job));
1412 status_printjob(cnum,snum,queue[i].job,
1413 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1414 break;
1416 break;
1419 if (i==count)
1420 SSVAL(*rparam,0,NERR_JobNotFound);
1422 if (queue) free(queue);
1425 SSVAL(*rparam,2,0); /* converter word */
1427 return(True);
1430 static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data,
1431 int mdrcnt,int mprcnt,
1432 char **rdata,char **rparam,
1433 int *rdata_len,int *rparam_len)
1435 char *str1 = param+2;
1436 char *str2 = skip_string(str1,1);
1437 char *QueueName = skip_string(str2,1);
1438 int snum;
1440 /* check it's a supported varient */
1441 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1442 return(False);
1444 *rparam_len = 4;
1445 *rparam = REALLOC(*rparam,*rparam_len);
1447 *rdata_len = 0;
1449 SSVAL(*rparam,0,NERR_Success);
1450 SSVAL(*rparam,2,0); /* converter word */
1452 snum = lp_servicenumber(QueueName);
1453 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1454 int pnum = lp_servicenumber(PRINTERS_NAME);
1455 if (pnum >= 0) {
1456 lp_add_printer(QueueName,pnum);
1457 snum = lp_servicenumber(QueueName);
1461 if (snum >= 0 && VALID_SNUM(snum)) {
1462 print_queue_struct *queue=NULL;
1463 int i, count;
1464 lpq_reset(snum);
1466 count = get_printqueue(snum,cnum,&queue,NULL);
1467 for (i = 0; i < count; i++)
1468 del_printqueue(cnum,snum,queue[i].job);
1470 if (queue) free(queue);
1473 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1475 return(True);
1479 /****************************************************************************
1480 set the property of a print job (undocumented?)
1481 ? function = 0xb -> set name of print job
1482 ? function = 0x6 -> move print job up/down
1483 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1484 or <WWsTP> <WB21BB16B10zWWzDDz>
1485 ****************************************************************************/
1486 static int check_printjob_info(struct pack_desc* desc,
1487 int uLevel, char* id)
1489 desc->subformat = NULL;
1490 switch( uLevel ) {
1491 case 0: desc->format = "W"; break;
1492 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1493 case 2: desc->format = "WWzWWDDzz"; break;
1494 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1495 default: return False;
1497 if (strcmp(desc->format,id) != 0) return False;
1498 return True;
1501 static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
1502 int mdrcnt,int mprcnt,
1503 char **rdata,char **rparam,
1504 int *rdata_len,int *rparam_len)
1506 struct pack_desc desc;
1507 char *str1 = param+2;
1508 char *str2 = skip_string(str1,1);
1509 char *p = skip_string(str2,1);
1510 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1511 by the print queue api */
1512 int snum = (SVAL(p,0)>>8);
1513 int uLevel = SVAL(p,2);
1514 int function = SVAL(p,4); /* what is this ?? */
1515 int i;
1516 char *s = data;
1518 *rparam_len = 4;
1519 *rparam = REALLOC(*rparam,*rparam_len);
1521 *rdata_len = 0;
1523 /* check it's a supported varient */
1524 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1525 return(False);
1527 switch (function) {
1528 case 0x6: /* change job place in the queue, data gives the new place */
1529 if (snum >= 0 && VALID_SNUM(snum))
1531 print_queue_struct *queue=NULL;
1532 int count;
1534 lpq_reset(snum);
1535 count = get_printqueue(snum,cnum,&queue,NULL);
1536 for (i=0;i<count;i++) /* find job */
1537 if ((queue[i].job%0xFF) == jobid) break;
1539 if (i==count) {
1540 desc.errcode=NERR_JobNotFound;
1541 if (queue) free(queue);
1543 else {
1544 desc.errcode=NERR_Success;
1545 i++;
1546 #if 0
1548 int place= SVAL(data,0);
1549 /* we currently have no way of doing this. Can any unix do it? */
1550 if (i < place) /* move down */;
1551 else if (i > place ) /* move up */;
1553 #endif
1554 desc.errcode=NERR_notsupported; /* not yet supported */
1555 if (queue) free(queue);
1558 else desc.errcode=NERR_JobNotFound;
1559 break;
1560 case 0xb: /* change print job name, data gives the name */
1561 /* jobid, snum should be zero */
1562 if (isalpha(*s))
1564 pstring name;
1565 int l = 0;
1566 while (l<64 && *s)
1568 if (issafe(*s)) name[l++] = *s;
1569 s++;
1571 name[l] = 0;
1573 DEBUG(3,("Setting print name to %s\n",name));
1575 for (i=0;i<MAX_OPEN_FILES;i++)
1576 if (Files[i].open && Files[i].print_file)
1578 pstring wd;
1579 GetWd(wd);
1580 unbecome_user();
1582 if (!become_user(Files[i].cnum,uid) ||
1583 !become_service(Files[i].cnum,True))
1584 break;
1586 if (sys_rename(Files[i].name,name) == 0)
1587 string_set(&Files[i].name,name);
1588 break;
1591 desc.errcode=NERR_Success;
1593 break;
1594 default: /* not implemented */
1595 return False;
1598 SSVALS(*rparam,0,desc.errcode);
1599 SSVAL(*rparam,2,0); /* converter word */
1601 return(True);
1605 /****************************************************************************
1606 get info about the server
1607 ****************************************************************************/
1608 static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
1609 int mdrcnt,int mprcnt,
1610 char **rdata,char **rparam,
1611 int *rdata_len,int *rparam_len)
1613 char *str1 = param+2;
1614 char *str2 = skip_string(str1,1);
1615 char *p = skip_string(str2,1);
1616 int uLevel = SVAL(p,0);
1617 char *p2;
1618 int struct_len;
1620 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1622 /* check it's a supported varient */
1623 if (!prefix_ok(str1,"WrLh")) return False;
1624 switch( uLevel ) {
1625 case 0:
1626 if (strcmp(str2,"B16") != 0) return False;
1627 struct_len = 16;
1628 break;
1629 case 1:
1630 if (strcmp(str2,"B16BBDz") != 0) return False;
1631 struct_len = 26;
1632 break;
1633 case 2:
1634 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1635 != 0) return False;
1636 struct_len = 134;
1637 break;
1638 case 3:
1639 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1640 != 0) return False;
1641 struct_len = 144;
1642 break;
1643 case 20:
1644 if (strcmp(str2,"DN") != 0) return False;
1645 struct_len = 6;
1646 break;
1647 case 50:
1648 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1649 struct_len = 42;
1650 break;
1651 default: return False;
1654 *rdata_len = mdrcnt;
1655 *rdata = REALLOC(*rdata,*rdata_len);
1657 p = *rdata;
1658 p2 = p + struct_len;
1659 if (uLevel != 20) {
1660 StrnCpy(p,local_machine,16);
1661 strupper(p);
1663 p += 16;
1664 if (uLevel > 0)
1666 struct srv_info_struct *servers=NULL;
1667 int i,count;
1668 pstring comment;
1669 uint32 servertype=DFLT_SERVER_TYPE;
1671 strcpy(comment,lp_serverstring());
1673 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
1674 for (i=0;i<count;i++)
1675 if (strequal(servers[i].name,local_machine)) {
1676 servertype = servers[i].type;
1677 strcpy(comment,servers[i].comment);
1680 if (servers) free(servers);
1682 SCVAL(p,0,MAJOR_VERSION);
1683 SCVAL(p,1,MINOR_VERSION);
1684 SIVAL(p,2,servertype);
1686 if (mdrcnt == struct_len) {
1687 SIVAL(p,6,0);
1688 } else {
1689 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1690 standard_sub(cnum,comment);
1691 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1692 p2 = skip_string(p2,1);
1695 if (uLevel > 1)
1697 return False; /* not yet implemented */
1700 *rdata_len = PTR_DIFF(p2,*rdata);
1702 *rparam_len = 6;
1703 *rparam = REALLOC(*rparam,*rparam_len);
1704 SSVAL(*rparam,0,NERR_Success);
1705 SSVAL(*rparam,2,0); /* converter word */
1706 SSVAL(*rparam,4,*rdata_len);
1708 return(True);
1712 /****************************************************************************
1713 get info about the server
1714 ****************************************************************************/
1715 static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
1716 int mdrcnt,int mprcnt,
1717 char **rdata,char **rparam,
1718 int *rdata_len,int *rparam_len)
1720 char *str1 = param+2;
1721 char *str2 = skip_string(str1,1);
1722 char *p = skip_string(str2,1);
1723 char *p2;
1724 extern pstring sesssetup_user;
1725 int level = SVAL(p,0);
1727 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1729 *rparam_len = 6;
1730 *rparam = REALLOC(*rparam,*rparam_len);
1732 /* check it's a supported varient */
1733 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1734 return(False);
1736 *rdata_len = mdrcnt + 1024;
1737 *rdata = REALLOC(*rdata,*rdata_len);
1739 SSVAL(*rparam,0,NERR_Success);
1740 SSVAL(*rparam,2,0); /* converter word */
1742 p = *rdata;
1743 p2 = p + 22;
1745 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1746 strcpy(p2,local_machine);
1747 p2 = skip_string(p2,1);
1748 p += 4;
1750 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1751 strcpy(p2,sesssetup_user);
1752 p2 = skip_string(p2,1);
1753 p += 4;
1755 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1756 strcpy(p2,lp_workgroup());
1757 p2 = skip_string(p2,1);
1758 p += 4;
1760 SCVAL(p,0,MAJOR_VERSION);
1761 SCVAL(p,1,MINOR_VERSION);
1762 p += 2;
1764 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1765 strcpy(p2,lp_workgroup()); /* login domain?? */
1766 p2 = skip_string(p2,1);
1767 p += 4;
1769 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1770 strcpy(p2,"");
1771 p2 = skip_string(p2,1);
1772 p += 4;
1774 *rdata_len = PTR_DIFF(p2,*rdata);
1776 SSVAL(*rparam,4,*rdata_len);
1778 return(True);
1782 /****************************************************************************
1783 get info about a user
1784 ****************************************************************************/
1786 #define USER_PRIV_GUEST 0
1787 #define USER_PRIV_USER 1
1788 #define USER_PRIV_ADMIN 2
1790 static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
1791 int mdrcnt,int mprcnt,
1792 char **rdata,char **rparam,
1793 int *rdata_len,int *rparam_len)
1795 char *str1 = param+2;
1796 char *str2 = skip_string(str1,1);
1797 char *UserName = skip_string(str2,1);
1798 char *p = skip_string(UserName,1);
1799 int uLevel = SVAL(p,0);
1800 char *p2;
1802 *rparam_len = 6;
1803 *rparam = REALLOC(*rparam,*rparam_len);
1805 /* check it's a supported varient */
1806 if (strcmp(str1,"zWrLh") != 0) return False;
1807 switch( uLevel ) {
1808 case 0: p2 = "B21"; break;
1809 case 1: p2 = "B21BB16DWzzWz"; break;
1810 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1811 case 10: p2 = "B21Bzzz"; break;
1812 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1813 default: return False;
1815 if (strcmp(p2,str2) != 0) return False;
1817 *rdata_len = mdrcnt + 1024;
1818 *rdata = REALLOC(*rdata,*rdata_len);
1820 SSVAL(*rparam,0,NERR_Success);
1821 SSVAL(*rparam,2,0); /* converter word */
1823 p = *rdata;
1824 p2 = p + 86;
1826 memset(p,0,21);
1827 strcpy(p,UserName);
1828 if (uLevel > 0) {
1829 SCVAL(p,21,0);
1830 *p2 = 0;
1831 if (uLevel >= 10) {
1832 SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
1833 strcpy(p2,"<Comment>");
1834 p2 = skip_string(p2,1);
1835 SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
1836 strcpy(p2,"<UserComment>");
1837 p2 = skip_string(p2,1);
1838 SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
1839 strcpy(p2,"<FullName>");
1840 p2 = skip_string(p2,1);
1842 if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
1843 SSVAL(p,34,
1844 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
1845 SIVAL(p,36,0); /* auth flags */
1846 SIVALS(p,40,-1); /* password age */
1847 SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
1848 strcpy(p2,"\\\\%L\\HOMES");
1849 standard_sub_basic(p2);
1850 p2 = skip_string(p2,1);
1851 SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
1852 strcpy(p2,"");
1853 p2 = skip_string(p2,1);
1854 SIVAL(p,52,0); /* last logon */
1855 SIVAL(p,56,0); /* last logoff */
1856 SSVALS(p,60,-1); /* bad pw counts */
1857 SSVALS(p,62,-1); /* num logons */
1858 SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
1859 strcpy(p2,"\\\\*");
1860 p2 = skip_string(p2,1);
1861 SSVAL(p,68,0); /* country code */
1863 SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
1864 strcpy(p2,"");
1865 p2 = skip_string(p2,1);
1867 SIVALS(p,74,-1); /* max storage */
1868 SSVAL(p,78,168); /* units per week */
1869 SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
1870 memset(p2,-1,21);
1871 SCVAL(p2,21,0); /* fix zero termination */
1872 p2 = skip_string(p2,1);
1874 SSVAL(p,84,0); /* code page */
1876 if (uLevel == 1 || uLevel == 2) {
1877 memset(p+22,' ',16); /* password */
1878 SIVALS(p,38,-1); /* password age */
1879 SSVAL(p,42,
1880 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
1881 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
1882 strcpy(p2,"\\\\%L\\HOMES");
1883 standard_sub_basic(p2);
1884 p2 = skip_string(p2,1);
1885 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
1886 *p2++ = 0;
1887 SSVAL(p,52,0); /* flags */
1888 SIVAL(p,54,0); /* script_path */
1889 if (uLevel == 2) {
1890 SIVAL(p,60,0); /* auth_flags */
1891 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
1892 strcpy(p2,"<Full Name>");
1893 p2 = skip_string(p2,1);
1894 SIVAL(p,68,0); /* urs_comment */
1895 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
1896 strcpy(p2,"");
1897 p2 = skip_string(p2,1);
1898 SIVAL(p,76,0); /* workstations */
1899 SIVAL(p,80,0); /* last_logon */
1900 SIVAL(p,84,0); /* last_logoff */
1901 SIVALS(p,88,-1); /* acct_expires */
1902 SIVALS(p,92,-1); /* max_storage */
1903 SSVAL(p,96,168); /* units_per_week */
1904 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
1905 memset(p2,-1,21);
1906 p2 += 21;
1907 SSVALS(p,102,-1); /* bad_pw_count */
1908 SSVALS(p,104,-1); /* num_logons */
1909 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
1910 strcpy(p2,"\\\\%L");
1911 standard_sub_basic(p2);
1912 p2 = skip_string(p2,1);
1913 SSVAL(p,110,49); /* country_code */
1914 SSVAL(p,112,860); /* code page */
1919 *rdata_len = PTR_DIFF(p2,*rdata);
1921 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
1923 return(True);
1927 /*******************************************************************
1928 get groups that a user is a member of
1929 ******************************************************************/
1930 static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
1931 int mdrcnt,int mprcnt,
1932 char **rdata,char **rparam,
1933 int *rdata_len,int *rparam_len)
1935 char *str1 = param+2;
1936 char *str2 = skip_string(str1,1);
1937 char *UserName = skip_string(str2,1);
1938 char *p = skip_string(UserName,1);
1939 int uLevel = SVAL(p,0);
1940 char *p2;
1941 int count=0;
1943 *rparam_len = 8;
1944 *rparam = REALLOC(*rparam,*rparam_len);
1946 /* check it's a supported varient */
1947 if (strcmp(str1,"zWrLeh") != 0) return False;
1948 switch( uLevel ) {
1949 case 0: p2 = "B21"; break;
1950 default: return False;
1952 if (strcmp(p2,str2) != 0) return False;
1954 *rdata_len = mdrcnt + 1024;
1955 *rdata = REALLOC(*rdata,*rdata_len);
1957 SSVAL(*rparam,0,NERR_Success);
1958 SSVAL(*rparam,2,0); /* converter word */
1960 p = *rdata;
1962 /* XXXX we need a real SAM database some day */
1963 strcpy(p,"Users"); p += 21; count++;
1964 strcpy(p,"Domain Users"); p += 21; count++;
1965 strcpy(p,"Guests"); p += 21; count++;
1966 strcpy(p,"Domain Guests"); p += 21; count++;
1968 *rdata_len = PTR_DIFF(p,*rdata);
1970 SSVAL(*rparam,4,count); /* is this right?? */
1971 SSVAL(*rparam,6,count); /* is this right?? */
1973 return(True);
1977 static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
1978 int mdrcnt,int mprcnt,
1979 char **rdata,char **rparam,
1980 int *rdata_len,int *rparam_len)
1982 char *str1 = param+2;
1983 char *str2 = skip_string(str1,1);
1984 char *p = skip_string(str2,1);
1985 int uLevel;
1986 struct pack_desc desc;
1987 char* name;
1989 uLevel = SVAL(p,0);
1990 name = p + 2;
1992 bzero(&desc,sizeof(desc));
1994 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
1996 /* check it's a supported varient */
1997 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
1998 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
1999 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2000 desc.base = *rdata;
2001 desc.buflen = mdrcnt;
2002 desc.subformat = NULL;
2003 desc.format = str2;
2007 if (init_package(&desc,1,0)) {
2008 PACKI(&desc,"W",0); /* code */
2009 PACKS(&desc,"B21",name); /* eff. name */
2010 PACKS(&desc,"B",""); /* pad */
2011 PACKI(&desc,"W",
2012 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2013 PACKI(&desc,"D",0); /* auth flags XXX */
2014 PACKI(&desc,"W",0); /* num logons */
2015 PACKI(&desc,"W",0); /* bad pw count */
2016 PACKI(&desc,"D",-1); /* last logon */
2017 PACKI(&desc,"D",-1); /* last logoff */
2018 PACKI(&desc,"D",-1); /* logoff time */
2019 PACKI(&desc,"D",-1); /* kickoff time */
2020 PACKI(&desc,"D",0); /* password age */
2021 PACKI(&desc,"D",0); /* password can change */
2022 PACKI(&desc,"D",-1); /* password must change */
2024 fstring mypath;
2025 strcpy(mypath,"\\\\");
2026 strcat(mypath,local_machine);
2027 strupper(mypath);
2028 PACKS(&desc,"z",mypath); /* computer */
2030 PACKS(&desc,"z",lp_workgroup());/* domain */
2031 PACKS(&desc,"z",lp_logon_script()); /* script path */
2032 PACKI(&desc,"D",0); /* reserved */
2035 *rdata_len = desc.usedlen;
2036 *rparam_len = 6;
2037 *rparam = REALLOC(*rparam,*rparam_len);
2038 SSVALS(*rparam,0,desc.errcode);
2039 SSVAL(*rparam,2,0);
2040 SSVAL(*rparam,4,desc.neededlen);
2042 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2043 return(True);
2047 /****************************************************************************
2048 api_WAccessGetUserPerms
2049 ****************************************************************************/
2050 static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
2051 int mdrcnt,int mprcnt,
2052 char **rdata,char **rparam,
2053 int *rdata_len,int *rparam_len)
2055 char *str1 = param+2;
2056 char *str2 = skip_string(str1,1);
2057 char *user = skip_string(str2,1);
2058 char *resource = skip_string(user,1);
2060 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2062 /* check it's a supported varient */
2063 if (strcmp(str1,"zzh") != 0) return False;
2064 if (strcmp(str2,"") != 0) return False;
2066 *rparam_len = 6;
2067 *rparam = REALLOC(*rparam,*rparam_len);
2068 SSVALS(*rparam,0,0); /* errorcode */
2069 SSVAL(*rparam,2,0); /* converter word */
2070 SSVAL(*rparam,4,0x7f); /* permission flags */
2072 return(True);
2075 /****************************************************************************
2076 api_WPrintJobEnumerate
2077 ****************************************************************************/
2078 static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
2079 int mdrcnt,int mprcnt,
2080 char **rdata,char **rparam,
2081 int *rdata_len,int *rparam_len)
2083 char *str1 = param+2;
2084 char *str2 = skip_string(str1,1);
2085 char *p = skip_string(str2,1);
2086 int uJobId = SVAL(p,0);
2087 int uLevel,cbBuf;
2088 int count;
2089 int i;
2090 int snum;
2091 int job;
2092 struct pack_desc desc;
2093 print_queue_struct *queue=NULL;
2094 print_status_struct status;
2096 uLevel = SVAL(p,2);
2097 cbBuf = SVAL(p,4);
2099 bzero(&desc,sizeof(desc));
2100 bzero(&status,sizeof(status));
2102 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2104 /* check it's a supported varient */
2105 if (strcmp(str1,"WWrLh") != 0) return False;
2106 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2108 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2109 job = uJobId & 0xFF;
2111 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2113 count = get_printqueue(snum,cnum,&queue,&status);
2114 for (i = 0; i < count; i++) {
2115 if ((queue[i].job % 0xFF) == job) break;
2117 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2118 desc.base = *rdata;
2119 desc.buflen = mdrcnt;
2121 if (init_package(&desc,1,0)) {
2122 if (i < count) {
2123 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2124 *rdata_len = desc.usedlen;
2126 else {
2127 desc.errcode = NERR_JobNotFound;
2128 *rdata_len = 0;
2132 *rparam_len = 6;
2133 *rparam = REALLOC(*rparam,*rparam_len);
2134 SSVALS(*rparam,0,desc.errcode);
2135 SSVAL(*rparam,2,0);
2136 SSVAL(*rparam,4,desc.neededlen);
2138 if (queue) free(queue);
2140 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2141 return(True);
2144 static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
2145 int mdrcnt,int mprcnt,
2146 char **rdata,char **rparam,
2147 int *rdata_len,int *rparam_len)
2149 char *str1 = param+2;
2150 char *str2 = skip_string(str1,1);
2151 char *p = skip_string(str2,1);
2152 char* name = p;
2153 int uLevel,cbBuf;
2154 int count;
2155 int i, succnt=0;
2156 int snum;
2157 struct pack_desc desc;
2158 print_queue_struct *queue=NULL;
2159 print_status_struct status;
2161 bzero(&desc,sizeof(desc));
2162 bzero(&status,sizeof(status));
2164 p = skip_string(p,1);
2165 uLevel = SVAL(p,0);
2166 cbBuf = SVAL(p,2);
2168 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2170 /* check it's a supported varient */
2171 if (strcmp(str1,"zWrLeh") != 0) return False;
2172 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2173 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2175 snum = lp_servicenumber(name);
2176 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2177 int pnum = lp_servicenumber(PRINTERS_NAME);
2178 if (pnum >= 0) {
2179 lp_add_printer(name,pnum);
2180 snum = lp_servicenumber(name);
2184 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2186 count = get_printqueue(snum,cnum,&queue,&status);
2187 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2188 desc.base = *rdata;
2189 desc.buflen = mdrcnt;
2191 if (init_package(&desc,count,0)) {
2192 succnt = 0;
2193 for (i = 0; i < count; i++) {
2194 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2195 if (desc.errcode == NERR_Success) succnt = i+1;
2199 *rdata_len = desc.usedlen;
2201 *rparam_len = 8;
2202 *rparam = REALLOC(*rparam,*rparam_len);
2203 SSVALS(*rparam,0,desc.errcode);
2204 SSVAL(*rparam,2,0);
2205 SSVAL(*rparam,4,succnt);
2206 SSVAL(*rparam,6,count);
2208 if (queue) free(queue);
2210 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2211 return(True);
2214 static int check_printdest_info(struct pack_desc* desc,
2215 int uLevel, char* id)
2217 desc->subformat = NULL;
2218 switch( uLevel ) {
2219 case 0: desc->format = "B9"; break;
2220 case 1: desc->format = "B9B21WWzW"; break;
2221 case 2: desc->format = "z"; break;
2222 case 3: desc->format = "zzzWWzzzWW"; break;
2223 default: return False;
2225 if (strcmp(desc->format,id) != 0) return False;
2226 return True;
2229 static void fill_printdest_info(int cnum, int snum, int uLevel,
2230 struct pack_desc* desc)
2232 char buf[100];
2233 strcpy(buf,SERVICE(snum));
2234 strupper(buf);
2235 if (uLevel <= 1) {
2236 PACKS(desc,"B9",buf); /* szName */
2237 if (uLevel == 1) {
2238 PACKS(desc,"B21",""); /* szUserName */
2239 PACKI(desc,"W",0); /* uJobId */
2240 PACKI(desc,"W",0); /* fsStatus */
2241 PACKS(desc,"z",""); /* pszStatus */
2242 PACKI(desc,"W",0); /* time */
2245 if (uLevel == 2 || uLevel == 3) {
2246 PACKS(desc,"z",buf); /* pszPrinterName */
2247 if (uLevel == 3) {
2248 PACKS(desc,"z",""); /* pszUserName */
2249 PACKS(desc,"z",""); /* pszLogAddr */
2250 PACKI(desc,"W",0); /* uJobId */
2251 PACKI(desc,"W",0); /* fsStatus */
2252 PACKS(desc,"z",""); /* pszStatus */
2253 PACKS(desc,"z",""); /* pszComment */
2254 PACKS(desc,"z","NULL"); /* pszDrivers */
2255 PACKI(desc,"W",0); /* time */
2256 PACKI(desc,"W",0); /* pad1 */
2261 static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
2262 int mdrcnt,int mprcnt,
2263 char **rdata,char **rparam,
2264 int *rdata_len,int *rparam_len)
2266 char *str1 = param+2;
2267 char *str2 = skip_string(str1,1);
2268 char *p = skip_string(str2,1);
2269 char* PrinterName = p;
2270 int uLevel,cbBuf;
2271 struct pack_desc desc;
2272 int snum;
2274 bzero(&desc,sizeof(desc));
2276 p = skip_string(p,1);
2277 uLevel = SVAL(p,0);
2278 cbBuf = SVAL(p,2);
2280 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2282 /* check it's a supported varient */
2283 if (strcmp(str1,"zWrLh") != 0) return False;
2284 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2286 snum = lp_servicenumber(PrinterName);
2287 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2288 int pnum = lp_servicenumber(PRINTERS_NAME);
2289 if (pnum >= 0) {
2290 lp_add_printer(PrinterName,pnum);
2291 snum = lp_servicenumber(PrinterName);
2295 if (snum < 0) {
2296 *rdata_len = 0;
2297 desc.errcode = NERR_DestNotFound;
2298 desc.neededlen = 0;
2300 else {
2301 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2302 desc.base = *rdata;
2303 desc.buflen = mdrcnt;
2304 if (init_package(&desc,1,0)) {
2305 fill_printdest_info(cnum,snum,uLevel,&desc);
2307 *rdata_len = desc.usedlen;
2310 *rparam_len = 6;
2311 *rparam = REALLOC(*rparam,*rparam_len);
2312 SSVALS(*rparam,0,desc.errcode);
2313 SSVAL(*rparam,2,0);
2314 SSVAL(*rparam,4,desc.neededlen);
2316 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2317 return(True);
2320 static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
2321 int mdrcnt,int mprcnt,
2322 char **rdata,char **rparam,
2323 int *rdata_len,int *rparam_len)
2325 char *str1 = param+2;
2326 char *str2 = skip_string(str1,1);
2327 char *p = skip_string(str2,1);
2328 int uLevel,cbBuf;
2329 int queuecnt;
2330 int i, n, succnt=0;
2331 struct pack_desc desc;
2332 int services = lp_numservices();
2334 bzero(&desc,sizeof(desc));
2336 uLevel = SVAL(p,0);
2337 cbBuf = SVAL(p,2);
2339 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2341 /* check it's a supported varient */
2342 if (strcmp(str1,"WrLeh") != 0) return False;
2343 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2345 queuecnt = 0;
2346 for (i = 0; i < services; i++)
2347 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2348 queuecnt++;
2350 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2351 desc.base = *rdata;
2352 desc.buflen = mdrcnt;
2353 if (init_package(&desc,queuecnt,0)) {
2354 succnt = 0;
2355 n = 0;
2356 for (i = 0; i < services; i++) {
2357 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2358 fill_printdest_info(cnum,i,uLevel,&desc);
2359 n++;
2360 if (desc.errcode == NERR_Success) succnt = n;
2365 *rdata_len = desc.usedlen;
2367 *rparam_len = 8;
2368 *rparam = REALLOC(*rparam,*rparam_len);
2369 SSVALS(*rparam,0,desc.errcode);
2370 SSVAL(*rparam,2,0);
2371 SSVAL(*rparam,4,succnt);
2372 SSVAL(*rparam,6,queuecnt);
2374 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2375 return(True);
2378 static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
2379 int mdrcnt,int mprcnt,
2380 char **rdata,char **rparam,
2381 int *rdata_len,int *rparam_len)
2383 char *str1 = param+2;
2384 char *str2 = skip_string(str1,1);
2385 char *p = skip_string(str2,1);
2386 int uLevel,cbBuf;
2387 int succnt;
2388 struct pack_desc desc;
2390 bzero(&desc,sizeof(desc));
2392 uLevel = SVAL(p,0);
2393 cbBuf = SVAL(p,2);
2395 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2397 /* check it's a supported varient */
2398 if (strcmp(str1,"WrLeh") != 0) return False;
2399 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2401 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2402 desc.base = *rdata;
2403 desc.buflen = mdrcnt;
2404 if (init_package(&desc,1,0)) {
2405 PACKS(&desc,"B41","NULL");
2408 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2410 *rdata_len = desc.usedlen;
2412 *rparam_len = 8;
2413 *rparam = REALLOC(*rparam,*rparam_len);
2414 SSVALS(*rparam,0,desc.errcode);
2415 SSVAL(*rparam,2,0);
2416 SSVAL(*rparam,4,succnt);
2417 SSVAL(*rparam,6,1);
2419 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2420 return(True);
2423 static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
2424 int mdrcnt,int mprcnt,
2425 char **rdata,char **rparam,
2426 int *rdata_len,int *rparam_len)
2428 char *str1 = param+2;
2429 char *str2 = skip_string(str1,1);
2430 char *p = skip_string(str2,1);
2431 int uLevel,cbBuf;
2432 int succnt;
2433 struct pack_desc desc;
2435 bzero(&desc,sizeof(desc));
2437 uLevel = SVAL(p,0);
2438 cbBuf = SVAL(p,2);
2440 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2442 /* check it's a supported varient */
2443 if (strcmp(str1,"WrLeh") != 0) return False;
2444 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2446 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2447 desc.base = *rdata;
2448 desc.buflen = mdrcnt;
2449 desc.format = str2;
2450 if (init_package(&desc,1,0)) {
2451 PACKS(&desc,"B13","lpd");
2454 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2456 *rdata_len = desc.usedlen;
2458 *rparam_len = 8;
2459 *rparam = REALLOC(*rparam,*rparam_len);
2460 SSVALS(*rparam,0,desc.errcode);
2461 SSVAL(*rparam,2,0);
2462 SSVAL(*rparam,4,succnt);
2463 SSVAL(*rparam,6,1);
2465 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2466 return(True);
2469 static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
2470 int mdrcnt,int mprcnt,
2471 char **rdata,char **rparam,
2472 int *rdata_len,int *rparam_len)
2474 char *str1 = param+2;
2475 char *str2 = skip_string(str1,1);
2476 char *p = skip_string(str2,1);
2477 int uLevel,cbBuf;
2478 int succnt;
2479 struct pack_desc desc;
2481 bzero(&desc,sizeof(desc));
2483 uLevel = SVAL(p,0);
2484 cbBuf = SVAL(p,2);
2486 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2488 /* check it's a supported varient */
2489 if (strcmp(str1,"WrLeh") != 0) return False;
2490 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2492 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2493 bzero(&desc,sizeof(desc));
2494 desc.base = *rdata;
2495 desc.buflen = mdrcnt;
2496 desc.format = str2;
2497 if (init_package(&desc,1,0)) {
2498 PACKS(&desc,"B13","lp0");
2501 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2503 *rdata_len = desc.usedlen;
2505 *rparam_len = 8;
2506 *rparam = REALLOC(*rparam,*rparam_len);
2507 SSVALS(*rparam,0,desc.errcode);
2508 SSVAL(*rparam,2,0);
2509 SSVAL(*rparam,4,succnt);
2510 SSVAL(*rparam,6,1);
2512 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2513 return(True);
2517 struct
2519 char * name;
2520 char * pipename;
2521 int subcommand;
2522 BOOL (*fn) ();
2523 } api_fd_commands [] =
2525 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2526 { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP },
2527 { NULL, NULL, -1, api_Unsupported }
2530 /****************************************************************************
2531 handle remote api calls delivered to a named pipe already opened.
2532 ****************************************************************************/
2533 static int api_fd_reply(int cnum,int uid,char *outbuf,
2534 uint16 *setup,char *data,char *params,
2535 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2537 char *rdata = NULL;
2538 char *rparam = NULL;
2539 int rdata_len = 0;
2540 int rparam_len = 0;
2541 BOOL reply=False;
2542 int i;
2543 int fd;
2544 int subcommand;
2546 /* First find out the name of this file. */
2547 if (suwcnt != 2)
2549 DEBUG(0,("Unexpected named pipe transaction.\n"));
2550 return(-1);
2553 /* Get the file handle and hence the file name. */
2554 fd = setup[1];
2555 subcommand = setup[0];
2557 DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2558 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2559 tdscnt,tpscnt,mdrcnt,mprcnt));
2561 for (i=0;api_fd_commands[i].name;i++)
2562 if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2563 api_fd_commands[i].subcommand == subcommand &&
2564 api_fd_commands[i].fn)
2566 DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2567 break;
2570 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2571 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2573 reply = api_fd_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2574 &rdata,&rparam,&rdata_len,&rparam_len);
2576 if (rdata_len > mdrcnt ||
2577 rparam_len > mprcnt)
2579 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2580 &rdata,&rparam,&rdata_len,&rparam_len);
2584 /* if we get False back then it's actually unsupported */
2585 if (!reply)
2586 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2587 &rdata,&rparam,&rdata_len,&rparam_len);
2589 /* now send the reply */
2590 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2592 if (rdata)
2593 free(rdata);
2594 if (rparam)
2595 free(rparam);
2597 return(-1);
2602 /****************************************************************************
2603 the buffer was too small
2604 ****************************************************************************/
2605 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
2606 int mdrcnt,int mprcnt,
2607 char **rdata,char **rparam,
2608 int *rdata_len,int *rparam_len)
2610 *rparam_len = MIN(*rparam_len,mprcnt);
2611 *rparam = REALLOC(*rparam,*rparam_len);
2613 *rdata_len = 0;
2615 SSVAL(*rparam,0,NERR_BufTooSmall);
2617 DEBUG(3,("Supplied buffer too small in API command\n"));
2619 return(True);
2623 /****************************************************************************
2624 the request is not supported
2625 ****************************************************************************/
2626 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
2627 int mdrcnt,int mprcnt,
2628 char **rdata,char **rparam,
2629 int *rdata_len,int *rparam_len)
2631 *rparam_len = 4;
2632 *rparam = REALLOC(*rparam,*rparam_len);
2634 *rdata_len = 0;
2636 SSVAL(*rparam,0,NERR_notsupported);
2637 SSVAL(*rparam,2,0); /* converter word */
2639 DEBUG(3,("Unsupported API command\n"));
2641 return(True);
2647 struct
2649 char *name;
2650 int id;
2651 BOOL (*fn)();
2652 int flags;
2653 } api_commands[] = {
2654 {"RNetShareEnum", 0, api_RNetShareEnum,0},
2655 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
2656 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
2657 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
2658 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
2659 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
2660 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
2661 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
2662 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
2663 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
2664 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
2665 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
2666 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
2667 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
2668 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
2669 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
2670 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
2671 {"NetServerEnum", 104, api_RNetServerEnum,0},
2672 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
2673 {"SetUserPassword", 115, api_SetUserPassword,0},
2674 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
2675 {"PrintJobInfo", 147, api_PrintJobInfo,0},
2676 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
2677 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
2678 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
2679 {NULL, -1, api_Unsupported,0}};
2682 /****************************************************************************
2683 handle remote api calls
2684 ****************************************************************************/
2685 static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
2686 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2688 int api_command = SVAL(params,0);
2689 char *rdata = NULL;
2690 char *rparam = NULL;
2691 int rdata_len = 0;
2692 int rparam_len = 0;
2693 BOOL reply=False;
2694 int i;
2696 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2697 api_command,params+2,skip_string(params+2,1),
2698 tdscnt,tpscnt,mdrcnt,mprcnt));
2700 for (i=0;api_commands[i].name;i++)
2701 if (api_commands[i].id == api_command && api_commands[i].fn)
2703 DEBUG(3,("Doing %s\n",api_commands[i].name));
2704 break;
2707 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2708 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2710 reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2711 &rdata,&rparam,&rdata_len,&rparam_len);
2714 if (rdata_len > mdrcnt ||
2715 rparam_len > mprcnt)
2717 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2718 &rdata,&rparam,&rdata_len,&rparam_len);
2722 /* if we get False back then it's actually unsupported */
2723 if (!reply)
2724 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2725 &rdata,&rparam,&rdata_len,&rparam_len);
2729 /* now send the reply */
2730 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2732 if (rdata)
2733 free(rdata);
2734 if (rparam)
2735 free(rparam);
2737 return(-1);
2740 /****************************************************************************
2741 handle named pipe commands
2742 ****************************************************************************/
2743 static int named_pipe(int cnum,int uid, char *outbuf,char *name,
2744 uint16 *setup,char *data,char *params,
2745 int suwcnt,int tdscnt,int tpscnt,
2746 int msrcnt,int mdrcnt,int mprcnt)
2749 if (strequal(name,"LANMAN"))
2750 return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2752 if (strlen(name) < 1)
2753 return(api_fd_reply(cnum,uid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
2756 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2757 name,(int)setup[0],(int)setup[1]));
2759 return(0);
2763 /****************************************************************************
2764 reply to a SMBtrans
2765 ****************************************************************************/
2766 int reply_trans(char *inbuf,char *outbuf)
2768 fstring name;
2770 char *data=NULL,*params=NULL;
2771 uint16 *setup=NULL;
2773 int outsize = 0;
2774 int cnum = SVAL(inbuf,smb_tid);
2775 int uid = SVAL(inbuf,smb_uid);
2777 int tpscnt = SVAL(inbuf,smb_vwv0);
2778 int tdscnt = SVAL(inbuf,smb_vwv1);
2779 int mprcnt = SVAL(inbuf,smb_vwv2);
2780 int mdrcnt = SVAL(inbuf,smb_vwv3);
2781 int msrcnt = CVAL(inbuf,smb_vwv4);
2782 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2783 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2784 int pscnt = SVAL(inbuf,smb_vwv9);
2785 int psoff = SVAL(inbuf,smb_vwv10);
2786 int dscnt = SVAL(inbuf,smb_vwv11);
2787 int dsoff = SVAL(inbuf,smb_vwv12);
2788 int suwcnt = CVAL(inbuf,smb_vwv13);
2790 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2792 if (tdscnt)
2794 data = (char *)malloc(tdscnt);
2795 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2797 if (tpscnt)
2799 params = (char *)malloc(tpscnt);
2800 memcpy(params,smb_base(inbuf)+psoff,pscnt);
2803 if (suwcnt)
2805 int i;
2806 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
2807 for (i=0;i<suwcnt;i++)
2808 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
2812 if (pscnt < tpscnt || dscnt < tdscnt)
2814 /* We need to send an interim response then receive the rest
2815 of the parameter/data bytes */
2816 outsize = set_message(outbuf,0,0,True);
2817 show_msg(outbuf);
2818 send_smb(Client,outbuf);
2821 /* receive the rest of the trans packet */
2822 while (pscnt < tpscnt || dscnt < tdscnt)
2824 int pcnt,poff,dcnt,doff,pdisp,ddisp;
2826 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
2827 CVAL(inbuf, smb_com) != SMBtrans)
2829 DEBUG(2,("Invalid secondary trans2 packet\n"));
2830 if (params) free(params);
2831 if (data) free(data);
2832 if (setup) free(setup);
2833 return(ERROR(ERRSRV,ERRerror));
2836 show_msg(inbuf);
2838 tpscnt = SVAL(inbuf,smb_vwv0);
2839 tdscnt = SVAL(inbuf,smb_vwv1);
2841 pcnt = SVAL(inbuf,smb_vwv2);
2842 poff = SVAL(inbuf,smb_vwv3);
2843 pdisp = SVAL(inbuf,smb_vwv4);
2845 dcnt = SVAL(inbuf,smb_vwv5);
2846 doff = SVAL(inbuf,smb_vwv6);
2847 ddisp = SVAL(inbuf,smb_vwv7);
2849 pscnt += pcnt;
2850 dscnt += dcnt;
2852 if (pcnt)
2853 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
2854 if (dcnt)
2855 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
2859 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
2862 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
2863 outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
2864 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
2867 if (data) free(data);
2868 if (params) free(params);
2869 if (setup) free(setup);
2871 if (close_on_completion)
2872 close_cnum(cnum,uid);
2874 if (one_way)
2875 return(-1);
2877 if (outsize == 0)
2878 return(ERROR(ERRSRV,ERRnosupport));
2880 return(outsize);