preparing for release of 3.0-alpha11
[Samba/ekacnet.git] / source / smbd / lanman.c
blob34dcf6c21182e65ba5aaf6aa1dc717d16cc87018
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1998
7 SMB Version handling
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
29 #include "includes.h"
31 #ifdef CHECK_TYPES
32 #undef CHECK_TYPES
33 #endif
34 #define CHECK_TYPES 0
36 extern fstring local_machine;
37 extern pstring global_myname;
38 extern fstring global_myworkgroup;
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)
49 #define ACCESS_READ 0x01
50 #define ACCESS_WRITE 0x02
51 #define ACCESS_CREATE 0x04
53 #define SHPWLEN 8 /* share password length */
55 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
56 int mdrcnt,int mprcnt,
57 char **rdata,char **rparam,
58 int *rdata_len,int *rparam_len);
59 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
60 int mdrcnt,int mprcnt,
61 char **rdata,char **rparam,
62 int *rdata_len,int *rparam_len);
65 static int CopyExpanded(connection_struct *conn,
66 int snum, char** dst, char* src, int* n)
68 pstring buf;
69 int l;
71 if (!src || !dst || !n || !(*dst)) return(0);
73 StrnCpy(buf,src,sizeof(buf)/2);
74 pstring_sub(buf,"%S",lp_servicename(snum));
75 standard_sub_conn(conn,buf);
76 l = push_ascii(*dst,buf,*n-1, STR_TERMINATE);
77 (*dst) += l;
78 (*n) -= l;
79 return l;
82 static int CopyAndAdvance(char** dst, char* src, int* n)
84 int l;
85 if (!src || !dst || !n || !(*dst)) return(0);
86 l = push_ascii(*dst,src,*n-1, STR_TERMINATE);
87 (*dst) += l;
88 (*n) -= l;
89 return l;
92 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
94 pstring buf;
95 if (!s) return(0);
96 StrnCpy(buf,s,sizeof(buf)/2);
97 pstring_sub(buf,"%S",lp_servicename(snum));
98 standard_sub_conn(conn,buf);
99 return strlen(buf) + 1;
102 static char* Expand(connection_struct *conn, int snum, char* s)
104 static pstring buf;
105 if (!s) return(NULL);
106 StrnCpy(buf,s,sizeof(buf)/2);
107 pstring_sub(buf,"%S",lp_servicename(snum));
108 standard_sub_conn(conn,buf);
109 return &buf[0];
112 /*******************************************************************
113 check a API string for validity when we only need to check the prefix
114 ******************************************************************/
115 static BOOL prefix_ok(char *str,char *prefix)
117 return(strncmp(str,prefix,strlen(prefix)) == 0);
120 struct pack_desc {
121 char* format; /* formatstring for structure */
122 char* subformat; /* subformat for structure */
123 char* base; /* baseaddress of buffer */
124 int buflen; /* remaining size for fixed part; on init: length of base */
125 int subcount; /* count of substructures */
126 char* structbuf; /* pointer into buffer for remaining fixed part */
127 int stringlen; /* remaining size for variable part */
128 char* stringbuf; /* pointer into buffer for remaining variable part */
129 int neededlen; /* total needed size */
130 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
131 char* curpos; /* current position; pointer into format or subformat */
132 int errcode;
135 static int get_counter(char** p)
137 int i, n;
138 if (!p || !(*p)) return(1);
139 if (!isdigit((int)**p)) return 1;
140 for (n = 0;;) {
141 i = **p;
142 if (isdigit(i))
143 n = 10 * n + (i - '0');
144 else
145 return n;
146 (*p)++;
150 static int getlen(char* p)
152 int n = 0;
153 if (!p) return(0);
154 while (*p) {
155 switch( *p++ ) {
156 case 'W': /* word (2 byte) */
157 n += 2;
158 break;
159 case 'K': /* status word? (2 byte) */
160 n += 2;
161 break;
162 case 'N': /* count of substructures (word) at end */
163 n += 2;
164 break;
165 case 'D': /* double word (4 byte) */
166 case 'z': /* offset to zero terminated string (4 byte) */
167 case 'l': /* offset to user data (4 byte) */
168 n += 4;
169 break;
170 case 'b': /* offset to data (with counter) (4 byte) */
171 n += 4;
172 get_counter(&p);
173 break;
174 case 'B': /* byte (with optional counter) */
175 n += get_counter(&p);
176 break;
179 return n;
182 static BOOL init_package(struct pack_desc* p, int count, int subcount)
184 int n = p->buflen;
185 int i;
187 if (!p->format || !p->base) return(False);
189 i = count * getlen(p->format);
190 if (p->subformat) i += subcount * getlen(p->subformat);
191 p->structbuf = p->base;
192 p->neededlen = 0;
193 p->usedlen = 0;
194 p->subcount = 0;
195 p->curpos = p->format;
196 if (i > n) {
197 p->neededlen = i;
198 i = n = 0;
199 #if 0
201 * This is the old error code we used. Aparently
202 * WinNT/2k systems return ERRbuftoosmall (2123) and
203 * OS/2 needs this. I'm leaving this here so we can revert
204 * if needed. JRA.
206 p->errcode = ERRmoredata;
207 #else
208 p->errcode = ERRbuftoosmall;
209 #endif
211 else
212 p->errcode = NERR_Success;
213 p->buflen = i;
214 n -= i;
215 p->stringbuf = p->base + i;
216 p->stringlen = n;
217 return(p->errcode == NERR_Success);
220 static int package(struct pack_desc* p, ...)
222 va_list args;
223 int needed=0, stringneeded;
224 char* str=NULL;
225 int is_string=0, stringused;
226 int32 temp;
228 va_start(args,p);
230 if (!*p->curpos) {
231 if (!p->subcount)
232 p->curpos = p->format;
233 else {
234 p->curpos = p->subformat;
235 p->subcount--;
238 #if CHECK_TYPES
239 str = va_arg(args,char*);
240 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
241 #endif
242 stringneeded = -1;
244 if (!p->curpos) {
245 va_end(args);
246 return(0);
249 switch( *p->curpos++ ) {
250 case 'W': /* word (2 byte) */
251 needed = 2;
252 temp = va_arg(args,int);
253 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
254 break;
255 case 'K': /* status word? (2 byte) */
256 needed = 2;
257 temp = va_arg(args,int);
258 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
259 break;
260 case 'N': /* count of substructures (word) at end */
261 needed = 2;
262 p->subcount = va_arg(args,int);
263 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
264 break;
265 case 'D': /* double word (4 byte) */
266 needed = 4;
267 temp = va_arg(args,int);
268 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
269 break;
270 case 'B': /* byte (with optional counter) */
271 needed = get_counter(&p->curpos);
273 char *s = va_arg(args,char*);
274 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
276 break;
277 case 'z': /* offset to zero terminated string (4 byte) */
278 str = va_arg(args,char*);
279 stringneeded = (str ? strlen(str)+1 : 0);
280 is_string = 1;
281 break;
282 case 'l': /* offset to user data (4 byte) */
283 str = va_arg(args,char*);
284 stringneeded = va_arg(args,int);
285 is_string = 0;
286 break;
287 case 'b': /* offset to data (with counter) (4 byte) */
288 str = va_arg(args,char*);
289 stringneeded = get_counter(&p->curpos);
290 is_string = 0;
291 break;
293 va_end(args);
294 if (stringneeded >= 0) {
295 needed = 4;
296 if (p->buflen >= needed) {
297 stringused = stringneeded;
298 if (stringused > p->stringlen) {
299 stringused = (is_string ? p->stringlen : 0);
300 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
302 if (!stringused)
303 SIVAL(p->structbuf,0,0);
304 else {
305 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
306 memcpy(p->stringbuf,str?str:"",stringused);
307 if (is_string) p->stringbuf[stringused-1] = '\0';
308 p->stringbuf += stringused;
309 p->stringlen -= stringused;
310 p->usedlen += stringused;
313 p->neededlen += stringneeded;
315 p->neededlen += needed;
316 if (p->buflen >= needed) {
317 p->structbuf += needed;
318 p->buflen -= needed;
319 p->usedlen += needed;
321 else {
322 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
324 return 1;
327 #if CHECK_TYPES
328 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
329 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
330 #else
331 #define PACK(desc,t,v) package(desc,v)
332 #define PACKl(desc,t,v,l) package(desc,v,l)
333 #endif
335 static void PACKI(struct pack_desc* desc,char *t,int v)
337 PACK(desc,t,v);
340 static void PACKS(struct pack_desc* desc,char *t,char *v)
342 PACK(desc,t,v);
346 /****************************************************************************
347 get a print queue
348 ****************************************************************************/
349 static void PackDriverData(struct pack_desc* desc)
351 char drivdata[4+4+32];
352 SIVAL(drivdata,0,sizeof drivdata); /* cb */
353 SIVAL(drivdata,4,1000); /* lVersion */
354 memset(drivdata+8,0,32); /* szDeviceName */
355 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
356 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
359 static int check_printq_info(struct pack_desc* desc,
360 int uLevel, char *id1, char *id2)
362 desc->subformat = NULL;
363 switch( uLevel ) {
364 case 0:
365 desc->format = "B13";
366 break;
367 case 1:
368 desc->format = "B13BWWWzzzzzWW";
369 break;
370 case 2:
371 desc->format = "B13BWWWzzzzzWN";
372 desc->subformat = "WB21BB16B10zWWzDDz";
373 break;
374 case 3:
375 desc->format = "zWWWWzzzzWWzzl";
376 break;
377 case 4:
378 desc->format = "zWWWWzzzzWNzzl";
379 desc->subformat = "WWzWWDDzz";
380 break;
381 case 5:
382 desc->format = "z";
383 break;
384 case 51:
385 desc->format = "K";
386 break;
387 case 52:
388 desc->format = "WzzzzzzzzN";
389 desc->subformat = "z";
390 break;
391 default: return False;
393 if (strcmp(desc->format,id1) != 0) return False;
394 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
395 return True;
399 #define RAP_JOB_STATUS_QUEUED 0
400 #define RAP_JOB_STATUS_PAUSED 1
401 #define RAP_JOB_STATUS_SPOOLING 2
402 #define RAP_JOB_STATUS_PRINTING 3
403 #define RAP_JOB_STATUS_PRINTED 4
405 #define RAP_QUEUE_STATUS_PAUSED 1
406 #define RAP_QUEUE_STATUS_ERROR 2
408 /* turn a print job status into a on the wire status
410 static int printj_status(int v)
412 switch (v) {
413 case LPQ_QUEUED:
414 return RAP_JOB_STATUS_QUEUED;
415 case LPQ_PAUSED:
416 return RAP_JOB_STATUS_PAUSED;
417 case LPQ_SPOOLING:
418 return RAP_JOB_STATUS_SPOOLING;
419 case LPQ_PRINTING:
420 return RAP_JOB_STATUS_PRINTING;
422 return 0;
425 /* turn a print queue status into a on the wire status
427 static int printq_status(int v)
429 switch (v) {
430 case LPQ_QUEUED:
431 return 0;
432 case LPQ_PAUSED:
433 return RAP_QUEUE_STATUS_PAUSED;
435 return RAP_QUEUE_STATUS_ERROR;
438 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
439 struct pack_desc* desc,
440 print_queue_struct* queue, int n)
442 time_t t = queue->time;
444 /* the client expects localtime */
445 t -= TimeDiff(t);
447 PACKI(desc,"W",queue->job); /* uJobId */
448 if (uLevel == 1) {
449 PACKS(desc,"B21",queue->user); /* szUserName */
450 PACKS(desc,"B",""); /* pad */
451 PACKS(desc,"B16",""); /* szNotifyName */
452 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
453 PACKS(desc,"z",""); /* pszParms */
454 PACKI(desc,"W",n+1); /* uPosition */
455 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
456 PACKS(desc,"z",""); /* pszStatus */
457 PACKI(desc,"D",t); /* ulSubmitted */
458 PACKI(desc,"D",queue->size); /* ulSize */
459 PACKS(desc,"z",queue->file); /* pszComment */
461 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
462 PACKI(desc,"W",queue->priority); /* uPriority */
463 PACKS(desc,"z",queue->user); /* pszUserName */
464 PACKI(desc,"W",n+1); /* uPosition */
465 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
466 PACKI(desc,"D",t); /* ulSubmitted */
467 PACKI(desc,"D",queue->size); /* ulSize */
468 PACKS(desc,"z","Samba"); /* pszComment */
469 PACKS(desc,"z",queue->file); /* pszDocument */
470 if (uLevel == 3) {
471 PACKS(desc,"z",""); /* pszNotifyName */
472 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
473 PACKS(desc,"z",""); /* pszParms */
474 PACKS(desc,"z",""); /* pszStatus */
475 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
476 PACKS(desc,"z","lpd"); /* pszQProcName */
477 PACKS(desc,"z",""); /* pszQProcParms */
478 PACKS(desc,"z","NULL"); /* pszDriverName */
479 PackDriverData(desc); /* pDriverData */
480 PACKS(desc,"z",""); /* pszPrinterName */
481 } else if (uLevel == 4) { /* OS2 */
482 PACKS(desc,"z",""); /* pszSpoolFileName */
483 PACKS(desc,"z",""); /* pszPortName */
484 PACKS(desc,"z",""); /* pszStatus */
485 PACKI(desc,"D",0); /* ulPagesSpooled */
486 PACKI(desc,"D",0); /* ulPagesSent */
487 PACKI(desc,"D",0); /* ulPagesPrinted */
488 PACKI(desc,"D",0); /* ulTimePrinted */
489 PACKI(desc,"D",0); /* ulExtendJobStatus */
490 PACKI(desc,"D",0); /* ulStartPage */
491 PACKI(desc,"D",0); /* ulEndPage */
496 /********************************************************************
497 Return a driver name given an snum.
498 Looks in a tdb first. Returns True if from tdb, False otherwise.
499 ********************************************************************/
501 static BOOL get_driver_name(int snum, pstring drivername)
503 NT_PRINTER_INFO_LEVEL *info = NULL;
504 BOOL in_tdb = False;
506 get_a_printer (&info, 2, lp_servicename(snum));
507 if (info != NULL) {
508 pstrcpy( drivername, info->info_2->drivername);
509 in_tdb = True;
510 free_a_printer(&info, 2);
511 } else {
512 pstrcpy( drivername, lp_printerdriver(snum));
515 return in_tdb;
518 /********************************************************************
519 Respond to the DosPrintQInfo command with a level of 52
520 This is used to get printer driver information for Win9x clients
521 ********************************************************************/
522 static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
523 struct pack_desc* desc,
524 int count, print_queue_struct* queue,
525 print_status_struct* status)
527 int i;
528 BOOL ok = False;
529 pstring tok,driver,datafile,langmon,helpfile,datatype;
530 char *p;
531 char **lines = NULL;
532 pstring gen_line;
533 BOOL in_tdb = False;
534 fstring location;
535 pstring drivername;
538 * Check in the tdb *first* before checking the legacy
539 * files. This allows an NT upload to take precedence over
540 * the existing fileset. JRA.
542 * we need to lookup the driver name prior to making the call
543 * to get_a_printer_driver_9x_compatible() and not rely on the
544 * 'print driver' parameter --jerry
548 if ((get_driver_name(snum,drivername)) &&
549 ((ok = get_a_printer_driver_9x_compatible(gen_line, drivername)) == True))
551 in_tdb = True;
552 p = gen_line;
553 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line));
555 else
557 /* didn't find driver in tdb */
559 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
560 snum, drivername, lp_driverfile(snum)));
562 lines = file_lines_load(lp_driverfile(snum),NULL);
563 if (!lines)
565 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),
566 strerror(errno)));
567 desc->errcode=NERR_notsupported;
568 goto done;
571 /* lookup the long printer driver name in the file description */
572 for (i=0;lines[i] && !ok;i++)
574 p = lines[i];
575 if (next_token(&p,tok,":",sizeof(tok)) &&
576 (strlen(drivername) == strlen(tok)) &&
577 (!strncmp(tok,drivername,strlen(drivername))))
579 ok = True;
584 if (ok)
586 /* driver file name */
587 if (!next_token(&p,driver,":",sizeof(driver)))
588 goto err;
590 /* data file name */
591 if (!next_token(&p,datafile,":",sizeof(datafile)))
592 goto err;
595 * for the next tokens - which may be empty - I have
596 * to check for empty tokens first because the
597 * next_token function will skip all empty token
598 * fields */
600 /* help file */
601 if (*p == ':')
603 *helpfile = '\0';
604 p++;
606 else if (!next_token(&p,helpfile,":",sizeof(helpfile)))
607 goto err;
609 /* language monitor */
610 if (*p == ':')
612 *langmon = '\0';
613 p++;
615 else if (!next_token(&p,langmon,":",sizeof(langmon)))
616 goto err;
618 /* default data type */
619 if (!next_token(&p,datatype,":",sizeof(datatype)))
620 goto err;
622 PACKI(desc,"W",0x0400); /* don't know */
623 PACKS(desc,"z",drivername); /* long printer name */
624 PACKS(desc,"z",driver); /* Driverfile Name */
625 PACKS(desc,"z",datafile); /* Datafile name */
626 PACKS(desc,"z",langmon); /* language monitor */
627 if (in_tdb)
629 fstrcpy(location, "\\\\");
630 fstrcat(location, global_myname);
631 fstrcat(location, "\\print$\\WIN40\\0");
632 PACKS(desc,"z",location); /* share to retrieve files */
634 else
636 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
638 PACKS(desc,"z",datatype); /* default data type */
639 PACKS(desc,"z",helpfile); /* helpfile name */
640 PACKS(desc,"z",driver); /* driver name */
642 DEBUG(3,("printerdriver:%s:\n",drivername));
643 DEBUG(3,("Driver:%s:\n",driver));
644 DEBUG(3,("Data File:%s:\n",datafile));
645 DEBUG(3,("Language Monitor:%s:\n",langmon));
646 if (in_tdb)
647 DEBUG(3,("lp_driverlocation:%s:\n",location));
648 else
649 DEBUG(3,("lp_driverlocation:%s:\n",lp_driverlocation(snum)));
650 DEBUG(3,("Data Type:%s:\n",datatype));
651 DEBUG(3,("Help File:%s:\n",helpfile));
652 PACKI(desc,"N",count); /* number of files to copy */
654 for (i=0;i<count;i++)
656 /* no need to check return value here
657 * - it was already tested in
658 * get_printerdrivernumber */
659 next_token(&p,tok,",",sizeof(tok));
660 PACKS(desc,"z",tok); /* driver files to copy */
661 DEBUG(3,("file:%s:\n",tok));
664 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
665 SERVICE(snum),count));
667 desc->errcode=NERR_Success;
668 goto done;
671 err:
673 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
674 desc->errcode=NERR_notsupported;
676 done:
677 file_lines_free(lines);
681 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
682 struct pack_desc* desc,
683 int count, print_queue_struct* queue,
684 print_status_struct* status)
686 switch (uLevel) {
687 case 1:
688 case 2:
689 PACKS(desc,"B13",SERVICE(snum));
690 break;
691 case 3:
692 case 4:
693 case 5:
694 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
695 break;
696 case 51:
697 PACKI(desc,"K",printq_status(status->status));
698 break;
701 if (uLevel == 1 || uLevel == 2) {
702 PACKS(desc,"B",""); /* alignment */
703 PACKI(desc,"W",5); /* priority */
704 PACKI(desc,"W",0); /* start time */
705 PACKI(desc,"W",0); /* until time */
706 PACKS(desc,"z",""); /* pSepFile */
707 PACKS(desc,"z","lpd"); /* pPrProc */
708 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
709 PACKS(desc,"z",""); /* pParms */
710 if (snum < 0) {
711 PACKS(desc,"z","UNKNOWN PRINTER");
712 PACKI(desc,"W",LPSTAT_ERROR);
714 else if (!status || !status->message[0]) {
715 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
716 PACKI(desc,"W",LPSTAT_OK); /* status */
717 } else {
718 PACKS(desc,"z",status->message);
719 PACKI(desc,"W",printq_status(status->status)); /* status */
721 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
724 if (uLevel == 3 || uLevel == 4) {
725 pstring drivername;
727 PACKI(desc,"W",5); /* uPriority */
728 PACKI(desc,"W",0); /* uStarttime */
729 PACKI(desc,"W",0); /* uUntiltime */
730 PACKI(desc,"W",5); /* pad1 */
731 PACKS(desc,"z",""); /* pszSepFile */
732 PACKS(desc,"z","WinPrint"); /* pszPrProc */
733 PACKS(desc,"z",NULL); /* pszParms */
734 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
735 /* "don't ask" that it's done this way to fix corrupted
736 Win9X/ME printer comments. */
737 if (!status) {
738 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
739 } else {
740 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
742 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
743 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
744 get_driver_name(snum,drivername);
745 PACKS(desc,"z",drivername); /* pszDriverName */
746 PackDriverData(desc); /* pDriverData */
749 if (uLevel == 2 || uLevel == 4) {
750 int i;
751 for (i=0;i<count;i++)
752 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
755 if (uLevel==52) {
756 fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status);
760 /* This function returns the number of files for a given driver */
761 static int get_printerdrivernumber(int snum)
763 int i, result = 0;
764 BOOL ok = False;
765 pstring tok;
766 char *p;
767 char **lines = NULL;
768 pstring gen_line;
769 pstring drivername;
772 * Check in the tdb *first* before checking the legacy
773 * files. This allows an NT upload to take precedence over
774 * the existing fileset. JRA.
776 * we need to lookup the driver name prior to making the call
777 * to get_a_printer_driver_9x_compatible() and not rely on the
778 * 'print driver' parameter --jerry
781 if ((get_driver_name(snum,drivername)) &&
782 (ok = get_a_printer_driver_9x_compatible(gen_line, drivername) == True))
784 p = gen_line;
785 DEBUG(10,("9x compatable driver line for [%s]: [%s]\n", drivername, gen_line));
787 else
789 /* didn't find driver in tdb */
791 DEBUG(10,("snum: %d\nprinterdriver: [%s]\nlp_driverfile: [%s]\n",
792 snum, drivername, lp_driverfile(snum)));
794 lines = file_lines_load(lp_driverfile(snum), NULL);
795 if (!lines)
797 DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
798 goto done;
801 /* lookup the long printer driver name in the file description */
802 for (i=0;lines[i] && !ok;i++)
804 p = lines[i];
805 if (next_token(&p,tok,":",sizeof(tok)) &&
806 (strlen(drivername) == strlen(tok)) &&
807 (!strncmp(tok,drivername,strlen(drivername))))
809 ok = True;
814 if( ok )
816 /* skip 5 fields */
817 i = 5;
818 while (*p && i) {
819 if (*p++ == ':') i--;
821 if (!*p || i) {
822 DEBUG(3,("Can't determine number of printer driver files\n"));
823 goto done;
826 /* count the number of files */
827 while (next_token(&p,tok,",",sizeof(tok)))
828 i++;
830 result = i;
833 done:
835 file_lines_free(lines);
837 return result;
840 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
841 uint16 vuid, char *param,char *data,
842 int mdrcnt,int mprcnt,
843 char **rdata,char **rparam,
844 int *rdata_len,int *rparam_len)
846 char *str1 = param+2;
847 char *str2 = skip_string(str1,1);
848 char *p = skip_string(str2,1);
849 char *QueueName = p;
850 int uLevel;
851 int count=0;
852 int snum;
853 char* str3;
854 struct pack_desc desc;
855 print_queue_struct *queue=NULL;
856 print_status_struct status;
857 char* tmpdata=NULL;
859 memset((char *)&status,'\0',sizeof(status));
860 memset((char *)&desc,'\0',sizeof(desc));
862 p = skip_string(p,1);
863 uLevel = SVAL(p,0);
864 str3 = p + 4;
866 /* remove any trailing username */
867 if ((p = strchr_m(QueueName,'%')))
868 *p = 0;
870 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
872 /* check it's a supported varient */
873 if (!prefix_ok(str1,"zWrLh"))
874 return False;
875 if (!check_printq_info(&desc,uLevel,str2,str3)) {
877 * Patch from Scott Moomaw <scott@bridgewater.edu>
878 * to return the 'invalid info level' error if an
879 * unknown level was requested.
881 *rdata_len = 0;
882 *rparam_len = 6;
883 *rparam = REALLOC(*rparam,*rparam_len);
884 SSVALS(*rparam,0,ERRunknownlevel);
885 SSVAL(*rparam,2,0);
886 SSVAL(*rparam,4,0);
887 return(True);
890 snum = lp_servicenumber(QueueName);
891 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
892 int pnum = lp_servicenumber(PRINTERS_NAME);
893 if (pnum >= 0) {
894 lp_add_printer(QueueName,pnum);
895 snum = lp_servicenumber(QueueName);
899 if (snum < 0 || !VALID_SNUM(snum))
900 return(False);
902 if (uLevel==52) {
903 count = get_printerdrivernumber(snum);
904 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
905 } else {
906 count = print_queue_status(snum, &queue,&status);
909 if (mdrcnt > 0) {
910 *rdata = REALLOC(*rdata,mdrcnt);
911 desc.base = *rdata;
912 desc.buflen = mdrcnt;
913 } else {
915 * Don't return data but need to get correct length
916 * init_package will return wrong size if buflen=0
918 desc.buflen = getlen(desc.format);
919 desc.base = tmpdata = (char *) malloc (desc.buflen);
922 if (init_package(&desc,1,count)) {
923 desc.subcount = count;
924 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
927 *rdata_len = desc.usedlen;
930 * We must set the return code to ERRbuftoosmall
931 * in order to support lanman style printing with Win NT/2k
932 * clients --jerry
934 if (!mdrcnt && lp_disable_spoolss())
935 desc.errcode = ERRbuftoosmall;
937 *rdata_len = desc.usedlen;
938 *rparam_len = 6;
939 *rparam = REALLOC(*rparam,*rparam_len);
940 SSVALS(*rparam,0,desc.errcode);
941 SSVAL(*rparam,2,0);
942 SSVAL(*rparam,4,desc.neededlen);
944 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
946 SAFE_FREE(queue);
947 SAFE_FREE(tmpdata);
949 return(True);
952 /****************************************************************************
953 View list of all print jobs on all queues.
954 ****************************************************************************/
956 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
957 int mdrcnt, int mprcnt,
958 char **rdata, char** rparam,
959 int *rdata_len, int *rparam_len)
961 char *param_format = param+2;
962 char *output_format1 = skip_string(param_format,1);
963 char *p = skip_string(output_format1,1);
964 int uLevel = SVAL(p,0);
965 char *output_format2 = p + 4;
966 int services = lp_numservices();
967 int i, n;
968 struct pack_desc desc;
969 print_queue_struct **queue = NULL;
970 print_status_struct *status = NULL;
971 int* subcntarr = NULL;
972 int queuecnt, subcnt=0, succnt=0;
974 memset((char *)&desc,'\0',sizeof(desc));
976 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
978 if (!prefix_ok(param_format,"WrLeh")) return False;
979 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
981 * Patch from Scott Moomaw <scott@bridgewater.edu>
982 * to return the 'invalid info level' error if an
983 * unknown level was requested.
985 *rdata_len = 0;
986 *rparam_len = 6;
987 *rparam = REALLOC(*rparam,*rparam_len);
988 SSVALS(*rparam,0,ERRunknownlevel);
989 SSVAL(*rparam,2,0);
990 SSVAL(*rparam,4,0);
991 return(True);
994 queuecnt = 0;
995 for (i = 0; i < services; i++)
996 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
997 queuecnt++;
998 if (uLevel > 0) {
999 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
1000 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1001 return False;
1003 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1004 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
1005 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1006 return False;
1008 memset(status,0,queuecnt*sizeof(print_status_struct));
1009 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
1010 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1011 return False;
1013 subcnt = 0;
1014 n = 0;
1015 for (i = 0; i < services; i++)
1016 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1017 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1018 subcnt += subcntarr[n];
1019 n++;
1022 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
1023 desc.base = *rdata;
1024 desc.buflen = mdrcnt;
1026 if (init_package(&desc,queuecnt,subcnt)) {
1027 n = 0;
1028 succnt = 0;
1029 for (i = 0; i < services; i++)
1030 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1031 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1032 n++;
1033 if (desc.errcode == NERR_Success) succnt = n;
1037 SAFE_FREE(subcntarr);
1039 *rdata_len = desc.usedlen;
1040 *rparam_len = 8;
1041 *rparam = REALLOC(*rparam,*rparam_len);
1042 SSVALS(*rparam,0,desc.errcode);
1043 SSVAL(*rparam,2,0);
1044 SSVAL(*rparam,4,succnt);
1045 SSVAL(*rparam,6,queuecnt);
1047 for (i = 0; i < queuecnt; i++) {
1048 if (queue) SAFE_FREE(queue[i]);
1051 SAFE_FREE(queue);
1052 SAFE_FREE(status);
1054 return True;
1057 /****************************************************************************
1058 get info level for a server list query
1059 ****************************************************************************/
1060 static BOOL check_server_info(int uLevel, char* id)
1062 switch( uLevel ) {
1063 case 0:
1064 if (strcmp(id,"B16") != 0) return False;
1065 break;
1066 case 1:
1067 if (strcmp(id,"B16BBDz") != 0) return False;
1068 break;
1069 default:
1070 return False;
1072 return True;
1075 struct srv_info_struct
1077 fstring name;
1078 uint32 type;
1079 fstring comment;
1080 fstring domain;
1081 BOOL server_added;
1085 /*******************************************************************
1086 get server info lists from the files saved by nmbd. Return the
1087 number of entries
1088 ******************************************************************/
1089 static int get_server_info(uint32 servertype,
1090 struct srv_info_struct **servers,
1091 char *domain)
1093 int count=0;
1094 int alloced=0;
1095 char **lines;
1096 BOOL local_list_only;
1097 int i;
1099 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
1100 if (!lines) {
1101 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1102 return(0);
1105 /* request for everything is code for request all servers */
1106 if (servertype == SV_TYPE_ALL)
1107 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1109 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1111 DEBUG(4,("Servertype search: %8x\n",servertype));
1113 for (i=0;lines[i];i++) {
1114 fstring stype;
1115 struct srv_info_struct *s;
1116 char *ptr = lines[i];
1117 BOOL ok = True;
1119 if (!*ptr) continue;
1121 if (count == alloced) {
1122 struct srv_info_struct *ts;
1124 alloced += 10;
1125 ts = (struct srv_info_struct *)
1126 Realloc(*servers,sizeof(**servers)*alloced);
1127 if (!ts) {
1128 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1129 return(0);
1131 else *servers = ts;
1132 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1134 s = &(*servers)[count];
1136 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1137 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1138 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1139 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1140 /* this allows us to cope with an old nmbd */
1141 pstrcpy(s->domain,global_myworkgroup);
1144 if (sscanf(stype,"%X",&s->type) != 1) {
1145 DEBUG(4,("r:host file "));
1146 ok = False;
1149 /* Filter the servers/domains we return based on what was asked for. */
1151 /* Check to see if we are being asked for a local list only. */
1152 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1153 DEBUG(4,("r: local list only"));
1154 ok = False;
1157 /* doesn't match up: don't want it */
1158 if (!(servertype & s->type)) {
1159 DEBUG(4,("r:serv type "));
1160 ok = False;
1163 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1164 (s->type & SV_TYPE_DOMAIN_ENUM))
1166 DEBUG(4,("s: dom mismatch "));
1167 ok = False;
1170 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1172 ok = False;
1175 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1176 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1178 if (ok)
1180 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1181 s->name, s->type, s->comment, s->domain));
1183 s->server_added = True;
1184 count++;
1186 else
1188 DEBUG(4,("%20s %8x %25s %15s\n",
1189 s->name, s->type, s->comment, s->domain));
1193 file_lines_free(lines);
1194 return(count);
1198 /*******************************************************************
1199 fill in a server info structure
1200 ******************************************************************/
1201 static int fill_srv_info(struct srv_info_struct *service,
1202 int uLevel, char **buf, int *buflen,
1203 char **stringbuf, int *stringspace, char *baseaddr)
1205 int struct_len;
1206 char* p;
1207 char* p2;
1208 int l2;
1209 int len;
1211 switch (uLevel) {
1212 case 0: struct_len = 16; break;
1213 case 1: struct_len = 26; break;
1214 default: return -1;
1217 if (!buf)
1219 len = 0;
1220 switch (uLevel)
1222 case 1:
1223 len = strlen(service->comment)+1;
1224 break;
1227 if (buflen) *buflen = struct_len;
1228 if (stringspace) *stringspace = len;
1229 return struct_len + len;
1232 len = struct_len;
1233 p = *buf;
1234 if (*buflen < struct_len) return -1;
1235 if (stringbuf)
1237 p2 = *stringbuf;
1238 l2 = *stringspace;
1240 else
1242 p2 = p + struct_len;
1243 l2 = *buflen - struct_len;
1245 if (!baseaddr) baseaddr = p;
1247 switch (uLevel)
1249 case 0:
1250 push_ascii(p,service->name, 15, STR_TERMINATE);
1251 break;
1253 case 1:
1254 push_ascii(p,service->name,15, STR_TERMINATE);
1255 SIVAL(p,18,service->type);
1256 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1257 len += CopyAndAdvance(&p2,service->comment,&l2);
1258 break;
1261 if (stringbuf)
1263 *buf = p + struct_len;
1264 *buflen -= struct_len;
1265 *stringbuf = p2;
1266 *stringspace = l2;
1268 else
1270 *buf = p2;
1271 *buflen -= len;
1273 return len;
1277 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1279 return(strcmp(s1->name,s2->name));
1282 /****************************************************************************
1283 view list of servers available (or possibly domains). The info is
1284 extracted from lists saved by nmbd on the local host
1285 ****************************************************************************/
1286 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1287 int mdrcnt, int mprcnt, char **rdata,
1288 char **rparam, int *rdata_len, int *rparam_len)
1290 char *str1 = param+2;
1291 char *str2 = skip_string(str1,1);
1292 char *p = skip_string(str2,1);
1293 int uLevel = SVAL(p,0);
1294 int buf_len = SVAL(p,2);
1295 uint32 servertype = IVAL(p,4);
1296 char *p2;
1297 int data_len, fixed_len, string_len;
1298 int f_len = 0, s_len = 0;
1299 struct srv_info_struct *servers=NULL;
1300 int counted=0,total=0;
1301 int i,missed;
1302 fstring domain;
1303 BOOL domain_request;
1304 BOOL local_request;
1306 /* If someone sets all the bits they don't really mean to set
1307 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1308 known servers. */
1310 if (servertype == SV_TYPE_ALL)
1311 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1313 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1314 any other bit (they may just set this bit on it's own) they
1315 want all the locally seen servers. However this bit can be
1316 set on its own so set the requested servers to be
1317 ALL - DOMAIN_ENUM. */
1319 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1320 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1322 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1323 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1325 p += 8;
1327 if (!prefix_ok(str1,"WrLehD")) return False;
1328 if (!check_server_info(uLevel,str2)) return False;
1330 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1331 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1332 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1334 if (strcmp(str1, "WrLehDz") == 0) {
1335 pull_ascii_fstring(domain, p);
1336 } else {
1337 fstrcpy(domain, global_myworkgroup);
1340 if (lp_browse_list())
1341 total = get_server_info(servertype,&servers,domain);
1343 data_len = fixed_len = string_len = 0;
1344 missed = 0;
1346 if (total > 0)
1347 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1350 char *lastname=NULL;
1352 for (i=0;i<total;i++)
1354 struct srv_info_struct *s = &servers[i];
1355 if (lastname && strequal(lastname,s->name)) continue;
1356 lastname = s->name;
1357 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1358 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1359 s->name, s->type, s->comment, s->domain));
1361 if (data_len <= buf_len) {
1362 counted++;
1363 fixed_len += f_len;
1364 string_len += s_len;
1365 } else {
1366 missed++;
1371 *rdata_len = fixed_len + string_len;
1372 *rdata = REALLOC(*rdata,*rdata_len);
1373 memset(*rdata,'\0',*rdata_len);
1375 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1376 p = *rdata;
1377 f_len = fixed_len;
1378 s_len = string_len;
1381 char *lastname=NULL;
1382 int count2 = counted;
1383 for (i = 0; i < total && count2;i++)
1385 struct srv_info_struct *s = &servers[i];
1386 if (lastname && strequal(lastname,s->name)) continue;
1387 lastname = s->name;
1388 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1389 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1390 s->name, s->type, s->comment, s->domain));
1391 count2--;
1395 *rparam_len = 8;
1396 *rparam = REALLOC(*rparam,*rparam_len);
1397 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1398 SSVAL(*rparam,2,0);
1399 SSVAL(*rparam,4,counted);
1400 SSVAL(*rparam,6,counted+missed);
1402 SAFE_FREE(servers);
1404 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1405 domain,uLevel,counted,counted+missed));
1407 return(True);
1410 /****************************************************************************
1411 command 0x34 - suspected of being a "Lookup Names" stub api
1412 ****************************************************************************/
1413 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1414 int mdrcnt, int mprcnt, char **rdata,
1415 char **rparam, int *rdata_len, int *rparam_len)
1417 char *str1 = param+2;
1418 char *str2 = skip_string(str1,1);
1419 char *p = skip_string(str2,1);
1420 int uLevel = SVAL(p,0);
1421 int buf_len = SVAL(p,2);
1422 int counted=0;
1423 int missed=0;
1425 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1426 str1, str2, p, uLevel, buf_len));
1428 if (!prefix_ok(str1,"zWrLeh")) return False;
1430 *rdata_len = 0;
1432 *rparam_len = 8;
1433 *rparam = REALLOC(*rparam,*rparam_len);
1435 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1436 SSVAL(*rparam,2,0);
1437 SSVAL(*rparam,4,counted);
1438 SSVAL(*rparam,6,counted+missed);
1440 return(True);
1443 /****************************************************************************
1444 get info about a share
1445 ****************************************************************************/
1446 static BOOL check_share_info(int uLevel, char* id)
1448 switch( uLevel ) {
1449 case 0:
1450 if (strcmp(id,"B13") != 0) return False;
1451 break;
1452 case 1:
1453 if (strcmp(id,"B13BWz") != 0) return False;
1454 break;
1455 case 2:
1456 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1457 break;
1458 case 91:
1459 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1460 break;
1461 default: return False;
1463 return True;
1466 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1467 char** buf, int* buflen,
1468 char** stringbuf, int* stringspace, char* baseaddr)
1470 int struct_len;
1471 char* p;
1472 char* p2;
1473 int l2;
1474 int len;
1476 switch( uLevel ) {
1477 case 0: struct_len = 13; break;
1478 case 1: struct_len = 20; break;
1479 case 2: struct_len = 40; break;
1480 case 91: struct_len = 68; break;
1481 default: return -1;
1485 if (!buf)
1487 len = 0;
1488 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1489 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1490 if (buflen) *buflen = struct_len;
1491 if (stringspace) *stringspace = len;
1492 return struct_len + len;
1495 len = struct_len;
1496 p = *buf;
1497 if ((*buflen) < struct_len) return -1;
1498 if (stringbuf)
1500 p2 = *stringbuf;
1501 l2 = *stringspace;
1503 else
1505 p2 = p + struct_len;
1506 l2 = (*buflen) - struct_len;
1508 if (!baseaddr) baseaddr = p;
1510 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1512 if (uLevel > 0)
1514 int type;
1515 CVAL(p,13) = 0;
1516 type = STYPE_DISKTREE;
1517 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1518 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1519 SSVAL(p,14,type); /* device type */
1520 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1521 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1524 if (uLevel > 1)
1526 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1527 SSVALS(p,22,-1); /* max uses */
1528 SSVAL(p,24,1); /* current uses */
1529 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1530 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1531 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1534 if (uLevel > 2)
1536 memset(p+40,0,SHPWLEN+2);
1537 SSVAL(p,50,0);
1538 SIVAL(p,52,0);
1539 SSVAL(p,56,0);
1540 SSVAL(p,58,0);
1541 SIVAL(p,60,0);
1542 SSVAL(p,64,0);
1543 SSVAL(p,66,0);
1546 if (stringbuf)
1548 (*buf) = p + struct_len;
1549 (*buflen) -= struct_len;
1550 (*stringbuf) = p2;
1551 (*stringspace) = l2;
1553 else
1555 (*buf) = p2;
1556 (*buflen) -= len;
1558 return len;
1561 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1562 int mdrcnt,int mprcnt,
1563 char **rdata,char **rparam,
1564 int *rdata_len,int *rparam_len)
1566 char *str1 = param+2;
1567 char *str2 = skip_string(str1,1);
1568 char *netname = skip_string(str2,1);
1569 char *p = skip_string(netname,1);
1570 int uLevel = SVAL(p,0);
1571 int snum = find_service(netname);
1573 if (snum < 0) return False;
1575 /* check it's a supported varient */
1576 if (!prefix_ok(str1,"zWrLh")) return False;
1577 if (!check_share_info(uLevel,str2)) return False;
1579 *rdata = REALLOC(*rdata,mdrcnt);
1580 p = *rdata;
1581 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1582 if (*rdata_len < 0) return False;
1584 *rparam_len = 6;
1585 *rparam = REALLOC(*rparam,*rparam_len);
1586 SSVAL(*rparam,0,NERR_Success);
1587 SSVAL(*rparam,2,0); /* converter word */
1588 SSVAL(*rparam,4,*rdata_len);
1590 return(True);
1593 /****************************************************************************
1594 view list of shares available
1595 ****************************************************************************/
1596 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1597 int mdrcnt,int mprcnt,
1598 char **rdata,char **rparam,
1599 int *rdata_len,int *rparam_len)
1601 char *str1 = param+2;
1602 char *str2 = skip_string(str1,1);
1603 char *p = skip_string(str2,1);
1604 int uLevel = SVAL(p,0);
1605 int buf_len = SVAL(p,2);
1606 char *p2;
1607 int count=lp_numservices();
1608 int total=0,counted=0;
1609 BOOL missed = False;
1610 int i;
1611 int data_len, fixed_len, string_len;
1612 int f_len = 0, s_len = 0;
1614 if (!prefix_ok(str1,"WrLeh")) return False;
1615 if (!check_share_info(uLevel,str2)) return False;
1617 data_len = fixed_len = string_len = 0;
1618 for (i=0;i<count;i++)
1619 if (lp_browseable(i) && lp_snum_ok(i))
1621 total++;
1622 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1623 if (data_len <= buf_len)
1625 counted++;
1626 fixed_len += f_len;
1627 string_len += s_len;
1629 else
1630 missed = True;
1632 *rdata_len = fixed_len + string_len;
1633 *rdata = REALLOC(*rdata,*rdata_len);
1634 memset(*rdata,0,*rdata_len);
1636 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1637 p = *rdata;
1638 f_len = fixed_len;
1639 s_len = string_len;
1640 for (i = 0; i < count;i++)
1641 if (lp_browseable(i) && lp_snum_ok(i))
1642 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1643 break;
1645 *rparam_len = 8;
1646 *rparam = REALLOC(*rparam,*rparam_len);
1647 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1648 SSVAL(*rparam,2,0);
1649 SSVAL(*rparam,4,counted);
1650 SSVAL(*rparam,6,total);
1652 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1653 counted,total,uLevel,
1654 buf_len,*rdata_len,mdrcnt));
1655 return(True);
1658 /****************************************************************************
1659 Add a share
1660 ****************************************************************************/
1661 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1662 int mdrcnt,int mprcnt,
1663 char **rdata,char **rparam,
1664 int *rdata_len,int *rparam_len)
1666 char *str1 = param+2;
1667 char *str2 = skip_string(str1,1);
1668 char *p = skip_string(str2,1);
1669 int uLevel = SVAL(p,0);
1670 fstring sharename;
1671 fstring comment;
1672 pstring pathname;
1673 char *command, *cmdname;
1674 uint offset;
1675 int snum;
1676 int res = ERRunsup;
1678 /* check it's a supported varient */
1679 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1680 if (!check_share_info(uLevel,str2)) return False;
1681 if (uLevel != 2) return False;
1683 pull_ascii_fstring(sharename,data);
1684 snum = find_service(sharename);
1685 if (snum >= 0) { /* already exists */
1686 res = ERRfilexists;
1687 goto error_exit;
1690 /* only support disk share adds */
1691 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1693 offset = IVAL(data, 16);
1694 if (offset >= mdrcnt) {
1695 res = ERRinvalidparam;
1696 goto error_exit;
1698 pull_ascii_fstring(comment, offset? (data+offset) : "");
1700 offset = IVAL(data, 26);
1701 if (offset >= mdrcnt) {
1702 res = ERRinvalidparam;
1703 goto error_exit;
1705 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1707 string_replace(sharename, '"', ' ');
1708 string_replace(pathname, '"', ' ');
1709 string_replace(comment, '"', ' ');
1711 cmdname = lp_add_share_cmd();
1713 if (!cmdname || *cmdname == '\0') return False;
1715 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1716 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1718 if (command) {
1719 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1720 if ((res = smbrun(command, NULL)) != 0) {
1721 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1722 SAFE_FREE(command);
1723 res = ERRnoaccess;
1724 goto error_exit;
1725 } else {
1726 SAFE_FREE(command);
1727 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False);
1729 } else return False;
1731 *rparam_len = 6;
1732 *rparam = REALLOC(*rparam,*rparam_len);
1733 SSVAL(*rparam,0,NERR_Success);
1734 SSVAL(*rparam,2,0); /* converter word */
1735 SSVAL(*rparam,4,*rdata_len);
1736 *rdata_len = 0;
1738 return True;
1740 error_exit:
1741 *rparam_len = 4;
1742 *rparam = REALLOC(*rparam,*rparam_len);
1743 *rdata_len = 0;
1744 SSVAL(*rparam,0,res);
1745 SSVAL(*rparam,2,0);
1746 return True;
1750 /****************************************************************************
1751 view list of groups available
1752 ****************************************************************************/
1753 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1754 int mdrcnt,int mprcnt,
1755 char **rdata,char **rparam,
1756 int *rdata_len,int *rparam_len)
1758 char *str1 = param+2;
1759 char *str2 = skip_string(str1,1);
1760 char *p = skip_string(str2,1);
1761 int uLevel = SVAL(p,0);
1762 char *p2;
1763 int count=0;
1765 if (!prefix_ok(str1,"WrLeh")) return False;
1767 /* check it's a supported variant */
1768 switch( uLevel )
1770 case 0:
1771 p2 = "B21";
1772 break;
1773 default:
1774 return False;
1777 if (strcmp(p2,str2) != 0) return False;
1779 *rdata_len = mdrcnt + 1024;
1780 *rdata = REALLOC(*rdata,*rdata_len);
1782 SSVAL(*rparam,0,NERR_Success);
1783 SSVAL(*rparam,2,0); /* converter word */
1785 p = *rdata;
1787 /* XXXX we need a real SAM database some day */
1788 pstrcpy(p,"Users"); p += 21; count++;
1789 pstrcpy(p,"Domain Users"); p += 21; count++;
1790 pstrcpy(p,"Guests"); p += 21; count++;
1791 pstrcpy(p,"Domain Guests"); p += 21; count++;
1793 *rdata_len = PTR_DIFF(p,*rdata);
1795 *rparam_len = 8;
1796 *rparam = REALLOC(*rparam,*rparam_len);
1798 SSVAL(*rparam,4,count); /* is this right?? */
1799 SSVAL(*rparam,6,count); /* is this right?? */
1801 DEBUG(3,("api_RNetGroupEnum gave %d entries\n", count));
1803 return(True);
1806 /****************************************************************************
1807 view list of groups available
1808 ****************************************************************************/
1809 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1810 int mdrcnt,int mprcnt,
1811 char **rdata,char **rparam,
1812 int *rdata_len,int *rparam_len)
1814 char *str1 = param+2;
1815 char *str2 = skip_string(str1,1);
1816 char *p = skip_string(str2,1);
1817 int uLevel = SVAL(p,0);
1818 char *p2;
1819 int count=0;
1821 if (!prefix_ok(str1,"WrLeh")) return False;
1823 /* check it's a supported variant */
1824 switch( uLevel )
1826 case 0:
1827 p2 = "B21";
1828 break;
1829 default:
1830 return False;
1833 if (strcmp(p2,str2) != 0) return False;
1835 *rdata_len = mdrcnt + 1024;
1836 *rdata = REALLOC(*rdata,*rdata_len);
1838 SSVAL(*rparam,0,NERR_Success);
1839 SSVAL(*rparam,2,0); /* converter word */
1841 p = *rdata;
1843 /* XXXX we need a real SAM database some day */
1844 pstrcpy(p,"Users"); p += 21; count++;
1845 pstrcpy(p,"Domain Users"); p += 21; count++;
1846 pstrcpy(p,"Guests"); p += 21; count++;
1847 pstrcpy(p,"Domain Guests"); p += 21; count++;
1849 *rdata_len = PTR_DIFF(p,*rdata);
1851 *rparam_len = 8;
1852 *rparam = REALLOC(*rparam,*rparam_len);
1854 SSVAL(*rparam,4,count); /* is this right?? */
1855 SSVAL(*rparam,6,count); /* is this right?? */
1857 DEBUG(3,("api_RNetUserEnum gave %d entries\n", count));
1859 return(True);
1864 /****************************************************************************
1865 get the time of day info
1866 ****************************************************************************/
1867 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1868 int mdrcnt,int mprcnt,
1869 char **rdata,char **rparam,
1870 int *rdata_len,int *rparam_len)
1872 char *p;
1873 *rparam_len = 4;
1874 *rparam = REALLOC(*rparam,*rparam_len);
1876 *rdata_len = 21;
1877 *rdata = REALLOC(*rdata,*rdata_len);
1879 SSVAL(*rparam,0,NERR_Success);
1880 SSVAL(*rparam,2,0); /* converter word */
1882 p = *rdata;
1885 struct tm *t;
1886 time_t unixdate = time(NULL);
1888 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1889 by NT in a "net time" operation,
1890 it seems to ignore the one below */
1892 /* the client expects to get localtime, not GMT, in this bit
1893 (I think, this needs testing) */
1894 t = LocalTime(&unixdate);
1896 SIVAL(p,4,0); /* msecs ? */
1897 CVAL(p,8) = t->tm_hour;
1898 CVAL(p,9) = t->tm_min;
1899 CVAL(p,10) = t->tm_sec;
1900 CVAL(p,11) = 0; /* hundredths of seconds */
1901 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1902 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1903 CVAL(p,16) = t->tm_mday;
1904 CVAL(p,17) = t->tm_mon + 1;
1905 SSVAL(p,18,1900+t->tm_year);
1906 CVAL(p,20) = t->tm_wday;
1910 return(True);
1913 /****************************************************************************
1914 Set the user password.
1915 *****************************************************************************/
1917 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1918 int mdrcnt,int mprcnt,
1919 char **rdata,char **rparam,
1920 int *rdata_len,int *rparam_len)
1922 char *p = skip_string(param+2,2);
1923 fstring user;
1924 fstring pass1,pass2;
1926 struct passwd *passwd;
1928 pull_ascii_fstring(user,p);
1930 p = skip_string(p,1);
1932 memset(pass1,'\0',sizeof(pass1));
1933 memset(pass2,'\0',sizeof(pass2));
1934 memcpy(pass1,p,16);
1935 memcpy(pass2,p+16,16);
1937 *rparam_len = 4;
1938 *rparam = REALLOC(*rparam,*rparam_len);
1940 *rdata_len = 0;
1942 SSVAL(*rparam,0,NERR_badpass);
1943 SSVAL(*rparam,2,0); /* converter word */
1945 DEBUG(3,("Set password for <%s>\n",user));
1948 * Pass the user through the NT -> unix user mapping
1949 * function.
1952 (void)map_username(user);
1955 * Do any UNIX username case mangling.
1957 passwd = Get_Pwnam_Modify( user );
1960 * Attempt to verify the old password against smbpasswd entries
1961 * Win98 clients send old and new password in plaintext for this call.
1965 fstring saved_pass2;
1966 SAM_ACCOUNT *sampass=NULL;
1969 * Save the new password as change_oem_password overwrites it
1970 * with zeros.
1973 fstrcpy(saved_pass2, pass2);
1975 if (check_plaintext_password(user,pass1,strlen(pass1),&sampass) &&
1976 change_oem_password(sampass,pass2))
1978 SSVAL(*rparam,0,NERR_Success);
1981 * If unix password sync was requested, attempt to change
1982 * the /etc/passwd database also. Return failure if this cannot
1983 * be done.
1986 if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
1987 SSVAL(*rparam,0,NERR_badpass);
1989 pdb_free_sam(&sampass);
1994 * If the above failed, attempt the plaintext password change.
1995 * This tests against the /etc/passwd database only.
1998 if(SVAL(*rparam,0) != NERR_Success)
2000 if NT_STATUS_IS_OK(pass_check(passwd, user, pass1,
2001 strlen(pass1), NULL, False))
2003 if (chgpasswd(user,pass1,pass2,False)) {
2004 SSVAL(*rparam,0,NERR_Success);
2010 * If the plaintext change failed, attempt
2011 * the old encrypted method. NT will generate this
2012 * after trying the samr method. Note that this
2013 * method is done as a last resort as this
2014 * password change method loses the NT password hash
2015 * and cannot change the UNIX password as no plaintext
2016 * is received.
2019 if(SVAL(*rparam,0) != NERR_Success)
2021 SAM_ACCOUNT *hnd = NULL;
2023 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) &&
2024 change_lanman_password(hnd,(unsigned char *)pass1,(unsigned char *)pass2))
2026 SSVAL(*rparam,0,NERR_Success);
2028 pdb_free_sam(&hnd);
2032 memset((char *)pass1,'\0',sizeof(fstring));
2033 memset((char *)pass2,'\0',sizeof(fstring));
2035 return(True);
2038 /****************************************************************************
2039 Set the user password (SamOEM version - gets plaintext).
2040 ****************************************************************************/
2042 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2043 int mdrcnt,int mprcnt,
2044 char **rdata,char **rparam,
2045 int *rdata_len,int *rparam_len)
2047 fstring user;
2048 char *p = param + 2;
2049 *rparam_len = 2;
2050 *rparam = REALLOC(*rparam,*rparam_len);
2052 *rdata_len = 0;
2054 SSVAL(*rparam,0,NERR_badpass);
2057 * Check the parameter definition is correct.
2059 if(!strequal(param + 2, "zsT")) {
2060 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2061 return False;
2063 p = skip_string(p, 1);
2065 if(!strequal(p, "B516B16")) {
2066 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2067 return False;
2069 p = skip_string(p,1);
2071 p += pull_ascii_fstring(user,p);
2073 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2076 * Pass the user through the NT -> unix user mapping
2077 * function.
2080 (void)map_username(user);
2083 * Do any UNIX username case mangling.
2085 (void)Get_Pwnam_Modify( user );
2087 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
2089 SSVAL(*rparam,0,NERR_Success);
2092 return(True);
2095 /****************************************************************************
2096 delete a print job
2097 Form: <W> <>
2098 ****************************************************************************/
2099 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2100 int mdrcnt,int mprcnt,
2101 char **rdata,char **rparam,
2102 int *rdata_len,int *rparam_len)
2104 int function = SVAL(param,0);
2105 char *str1 = param+2;
2106 char *str2 = skip_string(str1,1);
2107 char *p = skip_string(str2,1);
2108 int jobid, errcode;
2109 extern struct current_user current_user;
2110 WERROR werr = WERR_OK;
2112 jobid = SVAL(p,0);
2114 /* check it's a supported varient */
2115 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2116 return(False);
2118 *rparam_len = 4;
2119 *rparam = REALLOC(*rparam,*rparam_len);
2120 *rdata_len = 0;
2122 if (!print_job_exists(jobid)) {
2123 errcode = NERR_JobNotFound;
2124 goto out;
2127 errcode = NERR_notsupported;
2129 switch (function) {
2130 case 81: /* delete */
2131 if (print_job_delete(&current_user, jobid, &werr))
2132 errcode = NERR_Success;
2133 break;
2134 case 82: /* pause */
2135 if (print_job_pause(&current_user, jobid, &werr))
2136 errcode = NERR_Success;
2137 break;
2138 case 83: /* resume */
2139 if (print_job_resume(&current_user, jobid, &werr))
2140 errcode = NERR_Success;
2141 break;
2144 if (!W_ERROR_IS_OK(werr))
2145 errcode = W_ERROR_V(werr);
2147 out:
2148 SSVAL(*rparam,0,errcode);
2149 SSVAL(*rparam,2,0); /* converter word */
2151 return(True);
2154 /****************************************************************************
2155 Purge a print queue - or pause or resume it.
2156 ****************************************************************************/
2157 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2158 int mdrcnt,int mprcnt,
2159 char **rdata,char **rparam,
2160 int *rdata_len,int *rparam_len)
2162 int function = SVAL(param,0);
2163 char *str1 = param+2;
2164 char *str2 = skip_string(str1,1);
2165 char *QueueName = skip_string(str2,1);
2166 int errcode = NERR_notsupported;
2167 int snum;
2168 WERROR werr = WERR_OK;
2169 extern struct current_user current_user;
2171 /* check it's a supported varient */
2172 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2173 return(False);
2175 *rparam_len = 4;
2176 *rparam = REALLOC(*rparam,*rparam_len);
2177 *rdata_len = 0;
2179 snum = print_queue_snum(QueueName);
2181 if (snum == -1) {
2182 errcode = NERR_JobNotFound;
2183 goto out;
2186 switch (function) {
2187 case 74: /* Pause queue */
2188 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2189 break;
2190 case 75: /* Resume queue */
2191 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2192 break;
2193 case 103: /* Purge */
2194 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2195 break;
2198 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2200 out:
2201 SSVAL(*rparam,0,errcode);
2202 SSVAL(*rparam,2,0); /* converter word */
2204 return(True);
2208 /****************************************************************************
2209 set the property of a print job (undocumented?)
2210 ? function = 0xb -> set name of print job
2211 ? function = 0x6 -> move print job up/down
2212 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2213 or <WWsTP> <WB21BB16B10zWWzDDz>
2214 ****************************************************************************/
2215 static int check_printjob_info(struct pack_desc* desc,
2216 int uLevel, char* id)
2218 desc->subformat = NULL;
2219 switch( uLevel ) {
2220 case 0: desc->format = "W"; break;
2221 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2222 case 2: desc->format = "WWzWWDDzz"; break;
2223 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2224 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2225 default: return False;
2227 if (strcmp(desc->format,id) != 0) return False;
2228 return True;
2231 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2232 int mdrcnt,int mprcnt,
2233 char **rdata,char **rparam,
2234 int *rdata_len,int *rparam_len)
2236 struct pack_desc desc;
2237 char *str1 = param+2;
2238 char *str2 = skip_string(str1,1);
2239 char *p = skip_string(str2,1);
2240 int jobid;
2241 int uLevel = SVAL(p,2);
2242 int function = SVAL(p,4);
2243 int place, errcode;
2245 jobid = SVAL(p,0);
2246 *rparam_len = 4;
2247 *rparam = REALLOC(*rparam,*rparam_len);
2249 *rdata_len = 0;
2251 /* check it's a supported varient */
2252 if ((strcmp(str1,"WWsTP")) ||
2253 (!check_printjob_info(&desc,uLevel,str2)))
2254 return(False);
2256 if (!print_job_exists(jobid)) {
2257 errcode=NERR_JobNotFound;
2258 goto out;
2261 errcode = NERR_notsupported;
2263 switch (function) {
2264 case 0x6:
2265 /* change job place in the queue,
2266 data gives the new place */
2267 place = SVAL(data,0);
2268 if (print_job_set_place(jobid, place)) {
2269 errcode=NERR_Success;
2271 break;
2273 case 0xb:
2274 /* change print job name, data gives the name */
2275 if (print_job_set_name(jobid, data)) {
2276 errcode=NERR_Success;
2278 break;
2280 default:
2281 return False;
2284 out:
2285 SSVALS(*rparam,0,errcode);
2286 SSVAL(*rparam,2,0); /* converter word */
2288 return(True);
2292 /****************************************************************************
2293 get info about the server
2294 ****************************************************************************/
2295 static BOOL api_RNetServerGetInfo(connection_struct *conn,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 uLevel = SVAL(p,0);
2304 char *p2;
2305 int struct_len;
2307 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2309 /* check it's a supported varient */
2310 if (!prefix_ok(str1,"WrLh")) return False;
2311 switch( uLevel ) {
2312 case 0:
2313 if (strcmp(str2,"B16") != 0) return False;
2314 struct_len = 16;
2315 break;
2316 case 1:
2317 if (strcmp(str2,"B16BBDz") != 0) return False;
2318 struct_len = 26;
2319 break;
2320 case 2:
2321 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2322 != 0) return False;
2323 struct_len = 134;
2324 break;
2325 case 3:
2326 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2327 != 0) return False;
2328 struct_len = 144;
2329 break;
2330 case 20:
2331 if (strcmp(str2,"DN") != 0) return False;
2332 struct_len = 6;
2333 break;
2334 case 50:
2335 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2336 struct_len = 42;
2337 break;
2338 default: return False;
2341 *rdata_len = mdrcnt;
2342 *rdata = REALLOC(*rdata,*rdata_len);
2344 p = *rdata;
2345 p2 = p + struct_len;
2346 if (uLevel != 20) {
2347 srvstr_push(NULL, p,local_machine,16,
2348 STR_ASCII|STR_UPPER|STR_TERMINATE);
2350 p += 16;
2351 if (uLevel > 0)
2353 struct srv_info_struct *servers=NULL;
2354 int i,count;
2355 pstring comment;
2356 uint32 servertype= lp_default_server_announce();
2358 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2360 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2361 for (i=0;i<count;i++)
2362 if (strequal(servers[i].name,local_machine))
2364 servertype = servers[i].type;
2365 pstrcpy(comment,servers[i].comment);
2368 SAFE_FREE(servers);
2370 SCVAL(p,0,lp_major_announce_version());
2371 SCVAL(p,1,lp_minor_announce_version());
2372 SIVAL(p,2,servertype);
2374 if (mdrcnt == struct_len) {
2375 SIVAL(p,6,0);
2376 } else {
2377 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2378 standard_sub_conn(conn,comment);
2379 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2380 p2 = skip_string(p2,1);
2383 if (uLevel > 1)
2385 return False; /* not yet implemented */
2388 *rdata_len = PTR_DIFF(p2,*rdata);
2390 *rparam_len = 6;
2391 *rparam = REALLOC(*rparam,*rparam_len);
2392 SSVAL(*rparam,0,NERR_Success);
2393 SSVAL(*rparam,2,0); /* converter word */
2394 SSVAL(*rparam,4,*rdata_len);
2396 return(True);
2400 /****************************************************************************
2401 get info about the server
2402 ****************************************************************************/
2403 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2404 int mdrcnt,int mprcnt,
2405 char **rdata,char **rparam,
2406 int *rdata_len,int *rparam_len)
2408 char *str1 = param+2;
2409 char *str2 = skip_string(str1,1);
2410 char *p = skip_string(str2,1);
2411 char *p2;
2412 extern userdom_struct current_user_info;
2413 int level = SVAL(p,0);
2415 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2417 *rparam_len = 6;
2418 *rparam = REALLOC(*rparam,*rparam_len);
2420 /* check it's a supported varient */
2421 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2422 return(False);
2424 *rdata_len = mdrcnt + 1024;
2425 *rdata = REALLOC(*rdata,*rdata_len);
2427 SSVAL(*rparam,0,NERR_Success);
2428 SSVAL(*rparam,2,0); /* converter word */
2430 p = *rdata;
2431 p2 = p + 22;
2434 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2435 pstrcpy(p2,local_machine);
2436 strupper(p2);
2437 p2 = skip_string(p2,1);
2438 p += 4;
2440 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2441 pstrcpy(p2,current_user_info.smb_name);
2442 p2 = skip_string(p2,1);
2443 p += 4;
2445 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2446 pstrcpy(p2,global_myworkgroup);
2447 strupper(p2);
2448 p2 = skip_string(p2,1);
2449 p += 4;
2451 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2452 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2453 p += 2;
2455 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2456 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2457 p2 = skip_string(p2,1);
2458 p += 4;
2460 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2461 pstrcpy(p2,"");
2462 p2 = skip_string(p2,1);
2463 p += 4;
2465 *rdata_len = PTR_DIFF(p2,*rdata);
2467 SSVAL(*rparam,4,*rdata_len);
2469 return(True);
2472 /****************************************************************************
2473 get info about a user
2475 struct user_info_11 {
2476 char usri11_name[21]; 0-20
2477 char usri11_pad; 21
2478 char *usri11_comment; 22-25
2479 char *usri11_usr_comment; 26-29
2480 unsigned short usri11_priv; 30-31
2481 unsigned long usri11_auth_flags; 32-35
2482 long usri11_password_age; 36-39
2483 char *usri11_homedir; 40-43
2484 char *usri11_parms; 44-47
2485 long usri11_last_logon; 48-51
2486 long usri11_last_logoff; 52-55
2487 unsigned short usri11_bad_pw_count; 56-57
2488 unsigned short usri11_num_logons; 58-59
2489 char *usri11_logon_server; 60-63
2490 unsigned short usri11_country_code; 64-65
2491 char *usri11_workstations; 66-69
2492 unsigned long usri11_max_storage; 70-73
2493 unsigned short usri11_units_per_week; 74-75
2494 unsigned char *usri11_logon_hours; 76-79
2495 unsigned short usri11_code_page; 80-81
2498 where:
2500 usri11_name specifies the user name for which information is retireved
2502 usri11_pad aligns the next data structure element to a word boundary
2504 usri11_comment is a null terminated ASCII comment
2506 usri11_user_comment is a null terminated ASCII comment about the user
2508 usri11_priv specifies the level of the privilege assigned to the user.
2509 The possible values are:
2511 Name Value Description
2512 USER_PRIV_GUEST 0 Guest privilege
2513 USER_PRIV_USER 1 User privilege
2514 USER_PRV_ADMIN 2 Administrator privilege
2516 usri11_auth_flags specifies the account operator privileges. The
2517 possible values are:
2519 Name Value Description
2520 AF_OP_PRINT 0 Print operator
2523 Leach, Naik [Page 28]
2527 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2530 AF_OP_COMM 1 Communications operator
2531 AF_OP_SERVER 2 Server operator
2532 AF_OP_ACCOUNTS 3 Accounts operator
2535 usri11_password_age specifies how many seconds have elapsed since the
2536 password was last changed.
2538 usri11_home_dir points to a null terminated ASCII string that contains
2539 the path name of the user's home directory.
2541 usri11_parms points to a null terminated ASCII string that is set
2542 aside for use by applications.
2544 usri11_last_logon specifies the time when the user last logged on.
2545 This value is stored as the number of seconds elapsed since
2546 00:00:00, January 1, 1970.
2548 usri11_last_logoff specifies the time when the user last logged off.
2549 This value is stored as the number of seconds elapsed since
2550 00:00:00, January 1, 1970. A value of 0 means the last logoff
2551 time is unknown.
2553 usri11_bad_pw_count specifies the number of incorrect passwords
2554 entered since the last successful logon.
2556 usri11_log1_num_logons specifies the number of times this user has
2557 logged on. A value of -1 means the number of logons is unknown.
2559 usri11_logon_server points to a null terminated ASCII string that
2560 contains the name of the server to which logon requests are sent.
2561 A null string indicates logon requests should be sent to the
2562 domain controller.
2564 usri11_country_code specifies the country code for the user's language
2565 of choice.
2567 usri11_workstations points to a null terminated ASCII string that
2568 contains the names of workstations the user may log on from.
2569 There may be up to 8 workstations, with the names separated by
2570 commas. A null strings indicates there are no restrictions.
2572 usri11_max_storage specifies the maximum amount of disk space the user
2573 can occupy. A value of 0xffffffff indicates there are no
2574 restrictions.
2576 usri11_units_per_week specifies the equal number of time units into
2577 which a week is divided. This value must be equal to 168.
2579 usri11_logon_hours points to a 21 byte (168 bits) string that
2580 specifies the time during which the user can log on. Each bit
2581 represents one unique hour in a week. The first bit (bit 0, word
2582 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2586 Leach, Naik [Page 29]
2590 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2593 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2594 are no restrictions.
2596 usri11_code_page specifies the code page for the user's language of
2597 choice
2599 All of the pointers in this data structure need to be treated
2600 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2601 to be ignored. The converter word returned in the parameters section
2602 needs to be subtracted from the lower 16 bits to calculate an offset
2603 into the return buffer where this ASCII string resides.
2605 There is no auxiliary data in the response.
2607 ****************************************************************************/
2609 #define usri11_name 0
2610 #define usri11_pad 21
2611 #define usri11_comment 22
2612 #define usri11_usr_comment 26
2613 #define usri11_full_name 30
2614 #define usri11_priv 34
2615 #define usri11_auth_flags 36
2616 #define usri11_password_age 40
2617 #define usri11_homedir 44
2618 #define usri11_parms 48
2619 #define usri11_last_logon 52
2620 #define usri11_last_logoff 56
2621 #define usri11_bad_pw_count 60
2622 #define usri11_num_logons 62
2623 #define usri11_logon_server 64
2624 #define usri11_country_code 68
2625 #define usri11_workstations 70
2626 #define usri11_max_storage 74
2627 #define usri11_units_per_week 78
2628 #define usri11_logon_hours 80
2629 #define usri11_code_page 84
2630 #define usri11_end 86
2632 #define USER_PRIV_GUEST 0
2633 #define USER_PRIV_USER 1
2634 #define USER_PRIV_ADMIN 2
2636 #define AF_OP_PRINT 0
2637 #define AF_OP_COMM 1
2638 #define AF_OP_SERVER 2
2639 #define AF_OP_ACCOUNTS 3
2642 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2643 int mdrcnt,int mprcnt,
2644 char **rdata,char **rparam,
2645 int *rdata_len,int *rparam_len)
2647 char *str1 = param+2;
2648 char *str2 = skip_string(str1,1);
2649 char *UserName = skip_string(str2,1);
2650 char *p = skip_string(UserName,1);
2651 int uLevel = SVAL(p,0);
2652 char *p2;
2654 /* get NIS home of a previously validated user - simeon */
2655 /* With share level security vuid will always be zero.
2656 Don't depend on vuser being non-null !!. JRA */
2657 user_struct *vuser = get_valid_user_struct(vuid);
2658 if(vuser != NULL)
2659 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2660 vuser->user.unix_name));
2662 *rparam_len = 6;
2663 *rparam = REALLOC(*rparam,*rparam_len);
2665 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2667 /* check it's a supported variant */
2668 if (strcmp(str1,"zWrLh") != 0) return False;
2669 switch( uLevel )
2671 case 0: p2 = "B21"; break;
2672 case 1: p2 = "B21BB16DWzzWz"; break;
2673 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2674 case 10: p2 = "B21Bzzz"; break;
2675 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2676 default: return False;
2679 if (strcmp(p2,str2) != 0) return False;
2681 *rdata_len = mdrcnt + 1024;
2682 *rdata = REALLOC(*rdata,*rdata_len);
2684 SSVAL(*rparam,0,NERR_Success);
2685 SSVAL(*rparam,2,0); /* converter word */
2687 p = *rdata;
2688 p2 = p + usri11_end;
2690 memset(p,0,21);
2691 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2693 if (uLevel > 0)
2695 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2696 *p2 = 0;
2698 if (uLevel >= 10)
2700 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2701 pstrcpy(p2,"Comment");
2702 p2 = skip_string(p2,1);
2704 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2705 pstrcpy(p2,"UserComment");
2706 p2 = skip_string(p2,1);
2708 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2709 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2710 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2711 p2 = skip_string(p2,1);
2714 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2716 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2717 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2718 SIVALS(p,usri11_password_age,-1); /* password age */
2719 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2720 pstrcpy(p2, lp_logon_home());
2721 standard_sub_conn(conn, p2);
2722 p2 = skip_string(p2,1);
2723 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2724 pstrcpy(p2,"");
2725 p2 = skip_string(p2,1);
2726 SIVAL(p,usri11_last_logon,0); /* last logon */
2727 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2728 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2729 SSVALS(p,usri11_num_logons,-1); /* num logons */
2730 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2731 pstrcpy(p2,"\\\\*");
2732 p2 = skip_string(p2,1);
2733 SSVAL(p,usri11_country_code,0); /* country code */
2735 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2736 pstrcpy(p2,"");
2737 p2 = skip_string(p2,1);
2739 SIVALS(p,usri11_max_storage,-1); /* max storage */
2740 SSVAL(p,usri11_units_per_week,168); /* units per week */
2741 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2743 /* a simple way to get logon hours at all times. */
2744 memset(p2,0xff,21);
2745 SCVAL(p2,21,0); /* fix zero termination */
2746 p2 = skip_string(p2,1);
2748 SSVAL(p,usri11_code_page,0); /* code page */
2750 if (uLevel == 1 || uLevel == 2)
2752 memset(p+22,' ',16); /* password */
2753 SIVALS(p,38,-1); /* password age */
2754 SSVAL(p,42,
2755 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2756 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2757 pstrcpy(p2,lp_logon_home());
2758 standard_sub_conn(conn, p2);
2759 p2 = skip_string(p2,1);
2760 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2761 *p2++ = 0;
2762 SSVAL(p,52,0); /* flags */
2763 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2764 pstrcpy(p2,lp_logon_script());
2765 standard_sub_conn( conn, p2 );
2766 p2 = skip_string(p2,1);
2767 if (uLevel == 2)
2769 SIVAL(p,60,0); /* auth_flags */
2770 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2771 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2772 p2 = skip_string(p2,1);
2773 SIVAL(p,68,0); /* urs_comment */
2774 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2775 pstrcpy(p2,"");
2776 p2 = skip_string(p2,1);
2777 SIVAL(p,76,0); /* workstations */
2778 SIVAL(p,80,0); /* last_logon */
2779 SIVAL(p,84,0); /* last_logoff */
2780 SIVALS(p,88,-1); /* acct_expires */
2781 SIVALS(p,92,-1); /* max_storage */
2782 SSVAL(p,96,168); /* units_per_week */
2783 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2784 memset(p2,-1,21);
2785 p2 += 21;
2786 SSVALS(p,102,-1); /* bad_pw_count */
2787 SSVALS(p,104,-1); /* num_logons */
2788 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2789 pstrcpy(p2,"\\\\%L");
2790 standard_sub_conn(conn, p2);
2791 p2 = skip_string(p2,1);
2792 SSVAL(p,110,49); /* country_code */
2793 SSVAL(p,112,860); /* code page */
2797 *rdata_len = PTR_DIFF(p2,*rdata);
2799 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2801 return(True);
2804 /*******************************************************************
2805 get groups that a user is a member of
2806 ******************************************************************/
2807 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2808 int mdrcnt,int mprcnt,
2809 char **rdata,char **rparam,
2810 int *rdata_len,int *rparam_len)
2812 char *str1 = param+2;
2813 char *str2 = skip_string(str1,1);
2814 char *UserName = skip_string(str2,1);
2815 char *p = skip_string(UserName,1);
2816 int uLevel = SVAL(p,0);
2817 char *p2;
2818 int count=0;
2820 *rparam_len = 8;
2821 *rparam = REALLOC(*rparam,*rparam_len);
2823 /* check it's a supported varient */
2824 if (strcmp(str1,"zWrLeh") != 0) return False;
2825 switch( uLevel ) {
2826 case 0: p2 = "B21"; break;
2827 default: return False;
2829 if (strcmp(p2,str2) != 0) return False;
2831 *rdata_len = mdrcnt + 1024;
2832 *rdata = REALLOC(*rdata,*rdata_len);
2834 SSVAL(*rparam,0,NERR_Success);
2835 SSVAL(*rparam,2,0); /* converter word */
2837 p = *rdata;
2839 /* XXXX we need a real SAM database some day */
2840 pstrcpy(p,"Users"); p += 21; count++;
2841 pstrcpy(p,"Domain Users"); p += 21; count++;
2842 pstrcpy(p,"Guests"); p += 21; count++;
2843 pstrcpy(p,"Domain Guests"); p += 21; count++;
2845 *rdata_len = PTR_DIFF(p,*rdata);
2847 SSVAL(*rparam,4,count); /* is this right?? */
2848 SSVAL(*rparam,6,count); /* is this right?? */
2850 return(True);
2854 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2855 int mdrcnt,int mprcnt,
2856 char **rdata,char **rparam,
2857 int *rdata_len,int *rparam_len)
2859 char *str1 = param+2;
2860 char *str2 = skip_string(str1,1);
2861 char *p = skip_string(str2,1);
2862 int uLevel;
2863 struct pack_desc desc;
2864 char* name;
2866 uLevel = SVAL(p,0);
2867 name = p + 2;
2869 memset((char *)&desc,'\0',sizeof(desc));
2871 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2873 /* check it's a supported varient */
2874 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2875 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2876 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2877 desc.base = *rdata;
2878 desc.buflen = mdrcnt;
2879 desc.subformat = NULL;
2880 desc.format = str2;
2882 if (init_package(&desc,1,0))
2884 PACKI(&desc,"W",0); /* code */
2885 PACKS(&desc,"B21",name); /* eff. name */
2886 PACKS(&desc,"B",""); /* pad */
2887 PACKI(&desc,"W",
2888 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2889 PACKI(&desc,"D",0); /* auth flags XXX */
2890 PACKI(&desc,"W",0); /* num logons */
2891 PACKI(&desc,"W",0); /* bad pw count */
2892 PACKI(&desc,"D",0); /* last logon */
2893 PACKI(&desc,"D",-1); /* last logoff */
2894 PACKI(&desc,"D",-1); /* logoff time */
2895 PACKI(&desc,"D",-1); /* kickoff time */
2896 PACKI(&desc,"D",0); /* password age */
2897 PACKI(&desc,"D",0); /* password can change */
2898 PACKI(&desc,"D",-1); /* password must change */
2900 fstring mypath;
2901 fstrcpy(mypath,"\\\\");
2902 fstrcat(mypath,local_machine);
2903 strupper(mypath);
2904 PACKS(&desc,"z",mypath); /* computer */
2906 PACKS(&desc,"z",global_myworkgroup);/* domain */
2908 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2909 /* made sure all macros are fully substituted and available */
2911 pstring logon_script;
2912 pstrcpy(logon_script,lp_logon_script());
2913 standard_sub_conn( conn, logon_script );
2914 PACKS(&desc,"z", logon_script); /* script path */
2916 /* End of JHT mods */
2918 PACKI(&desc,"D",0x00000000); /* reserved */
2921 *rdata_len = desc.usedlen;
2922 *rparam_len = 6;
2923 *rparam = REALLOC(*rparam,*rparam_len);
2924 SSVALS(*rparam,0,desc.errcode);
2925 SSVAL(*rparam,2,0);
2926 SSVAL(*rparam,4,desc.neededlen);
2928 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2929 return(True);
2933 /****************************************************************************
2934 api_WAccessGetUserPerms
2935 ****************************************************************************/
2936 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2937 int mdrcnt,int mprcnt,
2938 char **rdata,char **rparam,
2939 int *rdata_len,int *rparam_len)
2941 char *str1 = param+2;
2942 char *str2 = skip_string(str1,1);
2943 char *user = skip_string(str2,1);
2944 char *resource = skip_string(user,1);
2946 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2948 /* check it's a supported varient */
2949 if (strcmp(str1,"zzh") != 0) return False;
2950 if (strcmp(str2,"") != 0) return False;
2952 *rparam_len = 6;
2953 *rparam = REALLOC(*rparam,*rparam_len);
2954 SSVALS(*rparam,0,0); /* errorcode */
2955 SSVAL(*rparam,2,0); /* converter word */
2956 SSVAL(*rparam,4,0x7f); /* permission flags */
2958 return(True);
2961 /****************************************************************************
2962 api_WPrintJobEnumerate
2963 ****************************************************************************/
2964 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2965 int mdrcnt,int mprcnt,
2966 char **rdata,char **rparam,
2967 int *rdata_len,int *rparam_len)
2969 char *str1 = param+2;
2970 char *str2 = skip_string(str1,1);
2971 char *p = skip_string(str2,1);
2972 int uLevel;
2973 int count;
2974 int i;
2975 int snum;
2976 int job;
2977 struct pack_desc desc;
2978 print_queue_struct *queue=NULL;
2979 print_status_struct status;
2980 char *tmpdata=NULL;
2982 uLevel = SVAL(p,2);
2984 memset((char *)&desc,'\0',sizeof(desc));
2985 memset((char *)&status,'\0',sizeof(status));
2987 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2989 /* check it's a supported varient */
2990 if (strcmp(str1,"WWrLh") != 0) return False;
2991 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2993 job = SVAL(p,0);
2994 snum = print_job_snum(job);
2996 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2998 count = print_queue_status(snum,&queue,&status);
2999 for (i = 0; i < count; i++) {
3000 if (queue[i].job == job) break;
3003 if (mdrcnt > 0) {
3004 *rdata = REALLOC(*rdata,mdrcnt);
3005 desc.base = *rdata;
3006 desc.buflen = mdrcnt;
3007 } else {
3009 * Don't return data but need to get correct length
3010 * init_package will return wrong size if buflen=0
3012 desc.buflen = getlen(desc.format);
3013 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3016 if (init_package(&desc,1,0)) {
3017 if (i < count) {
3018 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3019 *rdata_len = desc.usedlen;
3021 else {
3022 desc.errcode = NERR_JobNotFound;
3023 *rdata_len = 0;
3027 *rparam_len = 6;
3028 *rparam = REALLOC(*rparam,*rparam_len);
3029 SSVALS(*rparam,0,desc.errcode);
3030 SSVAL(*rparam,2,0);
3031 SSVAL(*rparam,4,desc.neededlen);
3033 SAFE_FREE(queue);
3034 SAFE_FREE(tmpdata);
3036 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3037 return(True);
3040 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3041 int mdrcnt,int mprcnt,
3042 char **rdata,char **rparam,
3043 int *rdata_len,int *rparam_len)
3045 char *str1 = param+2;
3046 char *str2 = skip_string(str1,1);
3047 char *p = skip_string(str2,1);
3048 char* name = p;
3049 int uLevel;
3050 int count;
3051 int i, succnt=0;
3052 int snum;
3053 struct pack_desc desc;
3054 print_queue_struct *queue=NULL;
3055 print_status_struct status;
3057 memset((char *)&desc,'\0',sizeof(desc));
3058 memset((char *)&status,'\0',sizeof(status));
3060 p = skip_string(p,1);
3061 uLevel = SVAL(p,0);
3063 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3065 /* check it's a supported varient */
3066 if (strcmp(str1,"zWrLeh") != 0) return False;
3067 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
3068 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3070 snum = lp_servicenumber(name);
3071 if (snum < 0 && pcap_printername_ok(name,NULL)) {
3072 int pnum = lp_servicenumber(PRINTERS_NAME);
3073 if (pnum >= 0) {
3074 lp_add_printer(name,pnum);
3075 snum = lp_servicenumber(name);
3079 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3081 count = print_queue_status(snum,&queue,&status);
3082 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3083 desc.base = *rdata;
3084 desc.buflen = mdrcnt;
3086 if (init_package(&desc,count,0)) {
3087 succnt = 0;
3088 for (i = 0; i < count; i++) {
3089 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3090 if (desc.errcode == NERR_Success) succnt = i+1;
3094 *rdata_len = desc.usedlen;
3096 *rparam_len = 8;
3097 *rparam = REALLOC(*rparam,*rparam_len);
3098 SSVALS(*rparam,0,desc.errcode);
3099 SSVAL(*rparam,2,0);
3100 SSVAL(*rparam,4,succnt);
3101 SSVAL(*rparam,6,count);
3103 SAFE_FREE(queue);
3105 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3106 return(True);
3109 static int check_printdest_info(struct pack_desc* desc,
3110 int uLevel, char* id)
3112 desc->subformat = NULL;
3113 switch( uLevel ) {
3114 case 0: desc->format = "B9"; break;
3115 case 1: desc->format = "B9B21WWzW"; break;
3116 case 2: desc->format = "z"; break;
3117 case 3: desc->format = "zzzWWzzzWW"; break;
3118 default: return False;
3120 if (strcmp(desc->format,id) != 0) return False;
3121 return True;
3124 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3125 struct pack_desc* desc)
3127 char buf[100];
3128 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3129 buf[sizeof(buf)-1] = 0;
3130 strupper(buf);
3131 if (uLevel <= 1) {
3132 PACKS(desc,"B9",buf); /* szName */
3133 if (uLevel == 1) {
3134 PACKS(desc,"B21",""); /* szUserName */
3135 PACKI(desc,"W",0); /* uJobId */
3136 PACKI(desc,"W",0); /* fsStatus */
3137 PACKS(desc,"z",""); /* pszStatus */
3138 PACKI(desc,"W",0); /* time */
3141 if (uLevel == 2 || uLevel == 3) {
3142 PACKS(desc,"z",buf); /* pszPrinterName */
3143 if (uLevel == 3) {
3144 PACKS(desc,"z",""); /* pszUserName */
3145 PACKS(desc,"z",""); /* pszLogAddr */
3146 PACKI(desc,"W",0); /* uJobId */
3147 PACKI(desc,"W",0); /* fsStatus */
3148 PACKS(desc,"z",""); /* pszStatus */
3149 PACKS(desc,"z",""); /* pszComment */
3150 PACKS(desc,"z","NULL"); /* pszDrivers */
3151 PACKI(desc,"W",0); /* time */
3152 PACKI(desc,"W",0); /* pad1 */
3157 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3158 int mdrcnt,int mprcnt,
3159 char **rdata,char **rparam,
3160 int *rdata_len,int *rparam_len)
3162 char *str1 = param+2;
3163 char *str2 = skip_string(str1,1);
3164 char *p = skip_string(str2,1);
3165 char* PrinterName = p;
3166 int uLevel;
3167 struct pack_desc desc;
3168 int snum;
3169 char *tmpdata=NULL;
3171 memset((char *)&desc,'\0',sizeof(desc));
3173 p = skip_string(p,1);
3174 uLevel = SVAL(p,0);
3176 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3178 /* check it's a supported varient */
3179 if (strcmp(str1,"zWrLh") != 0) return False;
3180 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3182 snum = lp_servicenumber(PrinterName);
3183 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3184 int pnum = lp_servicenumber(PRINTERS_NAME);
3185 if (pnum >= 0) {
3186 lp_add_printer(PrinterName,pnum);
3187 snum = lp_servicenumber(PrinterName);
3191 if (snum < 0) {
3192 *rdata_len = 0;
3193 desc.errcode = NERR_DestNotFound;
3194 desc.neededlen = 0;
3196 else {
3197 if (mdrcnt > 0) {
3198 *rdata = REALLOC(*rdata,mdrcnt);
3199 desc.base = *rdata;
3200 desc.buflen = mdrcnt;
3201 } else {
3203 * Don't return data but need to get correct length
3204 * init_package will return wrong size if buflen=0
3206 desc.buflen = getlen(desc.format);
3207 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3209 if (init_package(&desc,1,0)) {
3210 fill_printdest_info(conn,snum,uLevel,&desc);
3212 *rdata_len = desc.usedlen;
3215 *rparam_len = 6;
3216 *rparam = REALLOC(*rparam,*rparam_len);
3217 SSVALS(*rparam,0,desc.errcode);
3218 SSVAL(*rparam,2,0);
3219 SSVAL(*rparam,4,desc.neededlen);
3221 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3222 SAFE_FREE(tmpdata);
3223 return(True);
3226 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3227 int mdrcnt,int mprcnt,
3228 char **rdata,char **rparam,
3229 int *rdata_len,int *rparam_len)
3231 char *str1 = param+2;
3232 char *str2 = skip_string(str1,1);
3233 char *p = skip_string(str2,1);
3234 int uLevel;
3235 int queuecnt;
3236 int i, n, succnt=0;
3237 struct pack_desc desc;
3238 int services = lp_numservices();
3240 memset((char *)&desc,'\0',sizeof(desc));
3242 uLevel = SVAL(p,0);
3244 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3246 /* check it's a supported varient */
3247 if (strcmp(str1,"WrLeh") != 0) return False;
3248 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3250 queuecnt = 0;
3251 for (i = 0; i < services; i++)
3252 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3253 queuecnt++;
3255 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3256 desc.base = *rdata;
3257 desc.buflen = mdrcnt;
3258 if (init_package(&desc,queuecnt,0)) {
3259 succnt = 0;
3260 n = 0;
3261 for (i = 0; i < services; i++) {
3262 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3263 fill_printdest_info(conn,i,uLevel,&desc);
3264 n++;
3265 if (desc.errcode == NERR_Success) succnt = n;
3270 *rdata_len = desc.usedlen;
3272 *rparam_len = 8;
3273 *rparam = REALLOC(*rparam,*rparam_len);
3274 SSVALS(*rparam,0,desc.errcode);
3275 SSVAL(*rparam,2,0);
3276 SSVAL(*rparam,4,succnt);
3277 SSVAL(*rparam,6,queuecnt);
3279 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3280 return(True);
3283 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3284 int mdrcnt,int mprcnt,
3285 char **rdata,char **rparam,
3286 int *rdata_len,int *rparam_len)
3288 char *str1 = param+2;
3289 char *str2 = skip_string(str1,1);
3290 char *p = skip_string(str2,1);
3291 int uLevel;
3292 int succnt;
3293 struct pack_desc desc;
3295 memset((char *)&desc,'\0',sizeof(desc));
3297 uLevel = SVAL(p,0);
3299 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3301 /* check it's a supported varient */
3302 if (strcmp(str1,"WrLeh") != 0) return False;
3303 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3305 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3306 desc.base = *rdata;
3307 desc.buflen = mdrcnt;
3308 if (init_package(&desc,1,0)) {
3309 PACKS(&desc,"B41","NULL");
3312 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3314 *rdata_len = desc.usedlen;
3316 *rparam_len = 8;
3317 *rparam = REALLOC(*rparam,*rparam_len);
3318 SSVALS(*rparam,0,desc.errcode);
3319 SSVAL(*rparam,2,0);
3320 SSVAL(*rparam,4,succnt);
3321 SSVAL(*rparam,6,1);
3323 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3324 return(True);
3327 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3328 int mdrcnt,int mprcnt,
3329 char **rdata,char **rparam,
3330 int *rdata_len,int *rparam_len)
3332 char *str1 = param+2;
3333 char *str2 = skip_string(str1,1);
3334 char *p = skip_string(str2,1);
3335 int uLevel;
3336 int succnt;
3337 struct pack_desc desc;
3339 memset((char *)&desc,'\0',sizeof(desc));
3341 uLevel = SVAL(p,0);
3343 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3345 /* check it's a supported varient */
3346 if (strcmp(str1,"WrLeh") != 0) return False;
3347 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3349 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3350 desc.base = *rdata;
3351 desc.buflen = mdrcnt;
3352 desc.format = str2;
3353 if (init_package(&desc,1,0)) {
3354 PACKS(&desc,"B13","lpd");
3357 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3359 *rdata_len = desc.usedlen;
3361 *rparam_len = 8;
3362 *rparam = REALLOC(*rparam,*rparam_len);
3363 SSVALS(*rparam,0,desc.errcode);
3364 SSVAL(*rparam,2,0);
3365 SSVAL(*rparam,4,succnt);
3366 SSVAL(*rparam,6,1);
3368 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3369 return(True);
3372 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3373 int mdrcnt,int mprcnt,
3374 char **rdata,char **rparam,
3375 int *rdata_len,int *rparam_len)
3377 char *str1 = param+2;
3378 char *str2 = skip_string(str1,1);
3379 char *p = skip_string(str2,1);
3380 int uLevel;
3381 int succnt;
3382 struct pack_desc desc;
3384 memset((char *)&desc,'\0',sizeof(desc));
3386 uLevel = SVAL(p,0);
3388 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3390 /* check it's a supported varient */
3391 if (strcmp(str1,"WrLeh") != 0) return False;
3392 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3394 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3395 memset((char *)&desc,'\0',sizeof(desc));
3396 desc.base = *rdata;
3397 desc.buflen = mdrcnt;
3398 desc.format = str2;
3399 if (init_package(&desc,1,0)) {
3400 PACKS(&desc,"B13","lp0");
3403 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3405 *rdata_len = desc.usedlen;
3407 *rparam_len = 8;
3408 *rparam = REALLOC(*rparam,*rparam_len);
3409 SSVALS(*rparam,0,desc.errcode);
3410 SSVAL(*rparam,2,0);
3411 SSVAL(*rparam,4,succnt);
3412 SSVAL(*rparam,6,1);
3414 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3415 return(True);
3418 struct session_info {
3419 char machine[31];
3420 char username[24];
3421 char clitype[24];
3422 int opens;
3423 int time;
3426 struct sessions_info {
3427 int count;
3428 struct session_info *session_list;
3431 static int gather_sessioninfo(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
3433 struct sessions_info *sinfo = state;
3434 struct session_info *curinfo = NULL;
3435 struct sessionid *sessid = (struct sessionid *) dbuf.dptr;
3437 sinfo->count += 1;
3438 sinfo->session_list = REALLOC(sinfo->session_list, sinfo->count * sizeof(struct session_info));
3440 curinfo = &(sinfo->session_list[sinfo->count - 1]);
3442 safe_strcpy(curinfo->machine, sessid->remote_machine,
3443 sizeof(curinfo->machine));
3444 safe_strcpy(curinfo->username, uidtoname(sessid->uid),
3445 sizeof(curinfo->username));
3446 DEBUG(7,("gather_sessioninfo session from %s@%s\n",
3447 curinfo->username, curinfo->machine));
3448 return 0;
3451 /****************************************************************************
3452 List open sessions
3453 ****************************************************************************/
3454 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3455 int mdrcnt,int mprcnt,
3456 char **rdata,char **rparam,
3457 int *rdata_len,int *rparam_len)
3460 char *str1 = param+2;
3461 char *str2 = skip_string(str1,1);
3462 char *p = skip_string(str2,1);
3463 int uLevel;
3464 struct pack_desc desc;
3465 struct sessions_info sinfo;
3466 int i;
3468 memset((char *)&desc,'\0',sizeof(desc));
3470 uLevel = SVAL(p,0);
3472 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3473 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3474 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3476 /* check it's a supported varient */
3477 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3478 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3480 sinfo.count = 0;
3481 sinfo.session_list = NULL;
3483 if (!session_traverse(gather_sessioninfo, &sinfo)) {
3484 DEBUG(4,("RNetSessionEnum session_traverse failed\n"));
3485 return False;
3488 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3489 memset((char *)&desc,'\0',sizeof(desc));
3490 desc.base = *rdata;
3491 desc.buflen = mdrcnt;
3492 desc.format = str2;
3493 if (!init_package(&desc,sinfo.count,0)) {
3494 return False;
3497 for(i=0; i<sinfo.count; i++) {
3498 PACKS(&desc, "z", sinfo.session_list[i].machine);
3499 PACKS(&desc, "z", sinfo.session_list[i].username);
3500 PACKI(&desc, "W", 1); /* num conns */
3501 PACKI(&desc, "W", 0); /* num opens */
3502 PACKI(&desc, "W", 1); /* num users */
3503 PACKI(&desc, "D", 0); /* session time */
3504 PACKI(&desc, "D", 0); /* idle time */
3505 PACKI(&desc, "D", 0); /* flags */
3506 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3509 *rdata_len = desc.usedlen;
3511 *rparam_len = 8;
3512 *rparam = REALLOC(*rparam,*rparam_len);
3513 SSVALS(*rparam,0,desc.errcode);
3514 SSVAL(*rparam,2,0); /* converter */
3515 SSVAL(*rparam,4,sinfo.count); /* count */
3517 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3518 return True;
3522 /****************************************************************************
3523 The buffer was too small
3524 ****************************************************************************/
3526 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3527 int mdrcnt,int mprcnt,
3528 char **rdata,char **rparam,
3529 int *rdata_len,int *rparam_len)
3531 *rparam_len = MIN(*rparam_len,mprcnt);
3532 *rparam = REALLOC(*rparam,*rparam_len);
3534 *rdata_len = 0;
3536 SSVAL(*rparam,0,NERR_BufTooSmall);
3538 DEBUG(3,("Supplied buffer too small in API command\n"));
3540 return(True);
3544 /****************************************************************************
3545 The request is not supported
3546 ****************************************************************************/
3548 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3549 int mdrcnt,int mprcnt,
3550 char **rdata,char **rparam,
3551 int *rdata_len,int *rparam_len)
3553 *rparam_len = 4;
3554 *rparam = REALLOC(*rparam,*rparam_len);
3556 *rdata_len = 0;
3558 SSVAL(*rparam,0,NERR_notsupported);
3559 SSVAL(*rparam,2,0); /* converter word */
3561 DEBUG(3,("Unsupported API command\n"));
3563 return(True);
3569 struct
3571 char *name;
3572 int id;
3573 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3574 int,int,char **,char **,int *,int *);
3575 int flags;
3576 } api_commands[] = {
3577 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum,0},
3578 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo,0},
3579 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd,0},
3580 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum,0},
3581 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo,0},
3582 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum,0},
3583 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers,0},
3584 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum,0},
3585 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo,0},
3586 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups,0},
3587 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo,0},
3588 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum,0},
3589 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo,0},
3590 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl,0},
3591 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl,0},
3592 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate,0},
3593 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo,0},
3594 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel,0},
3595 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel,0},
3596 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel,0},
3597 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum,0},
3598 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo,0},
3599 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD,0},
3600 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl,0},
3601 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum,0},
3602 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms,0},
3603 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword,0},
3604 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon,0},
3605 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo,0},
3606 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum,0},
3607 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum,0},
3608 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum,0},
3609 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword,0},
3610 {NULL, -1, api_Unsupported,0}};
3613 /****************************************************************************
3614 Handle remote api calls
3615 ****************************************************************************/
3617 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3618 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3620 int api_command;
3621 char *rdata = NULL;
3622 char *rparam = NULL;
3623 int rdata_len = 0;
3624 int rparam_len = 0;
3625 BOOL reply=False;
3626 int i;
3628 if (!params) {
3629 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3630 return 0;
3633 api_command = SVAL(params,0);
3635 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3636 api_command,
3637 params+2,
3638 skip_string(params+2,1),
3639 tdscnt,tpscnt,mdrcnt,mprcnt));
3641 for (i=0;api_commands[i].name;i++) {
3642 if (api_commands[i].id == api_command && api_commands[i].fn) {
3643 DEBUG(3,("Doing %s\n",api_commands[i].name));
3644 break;
3648 rdata = (char *)malloc(1024);
3649 if (rdata)
3650 memset(rdata,'\0',1024);
3652 rparam = (char *)malloc(1024);
3653 if (rparam)
3654 memset(rparam,'\0',1024);
3656 if(!rdata || !rparam) {
3657 DEBUG(0,("api_reply: malloc fail !\n"));
3658 return -1;
3661 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3662 &rdata,&rparam,&rdata_len,&rparam_len);
3665 if (rdata_len > mdrcnt ||
3666 rparam_len > mprcnt) {
3667 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3668 &rdata,&rparam,&rdata_len,&rparam_len);
3671 /* if we get False back then it's actually unsupported */
3672 if (!reply)
3673 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3674 &rdata,&rparam,&rdata_len,&rparam_len);
3676 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
3678 SAFE_FREE(rdata);
3679 SAFE_FREE(rparam);
3681 return -1;