home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 July & August / Pcwk78a98.iso / Wtestowe / Clico / UNIX / SAMBA / SOURCE / SAMBA.TAR / samba-1.9.17 / source / ipc.c < prev    next >
C/C++ Source or Header  |  1997-08-19  |  86KB  |  3,116 lines

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