Return either STATUS_BUFFER_OVERFLOW or ERRDOS/ERRmoredata depending on
[samba.git] / source3 / smbd / ipc.c
index 46fb6a22ff7590f6726d55a25024dde770d33727..a4d452b2a84cc4c61b36736ea61bb382deddc381 100644 (file)
@@ -60,8 +60,8 @@ extern fstring global_myworkgroup;
 #define QNLEN 12               /* queue name maximum length */
 
 extern int Client;
-extern int oplock_sock;
 extern int smb_read_error;
+extern uint32 global_client_caps;
 
 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
                            int mdrcnt,int mprcnt,
@@ -144,7 +144,7 @@ static void copy_trans_params_and_data(char *outbuf, int align,
                                int param_offset, int data_offset,
                                int param_len, int data_len)
 {
-       char *copy_into = smb_buf(outbuf);
+       char *copy_into = smb_buf(outbuf)+1;
 
        DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
                        param_offset, param_offset + param_len,
@@ -182,20 +182,21 @@ static void send_trans_reply(char *outbuf,
        this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
        this_ldata  = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
 
-#ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
-       /* if you don't want Net Monitor to decode your packets, do this!!! */
-       align = ((this_lparam+1)%4);
-#else
-       align = (this_lparam%4);
-#endif
+       align = ((this_lparam)%4);
 
-       set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
+       set_message(outbuf,10+lsetup,1+align+this_ldata+this_lparam,True);
 
        if (buffer_too_large)
        {
-               /* issue a buffer size warning.  on a DCE/RPC pipe, expect an SMBreadX... */
-               SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
-               SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
+               if (global_client_caps & CAP_STATUS32)
+               {
+                       /* issue a buffer size warning.  on a DCE/RPC pipe, expect an SMBreadX... */
+                       SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+                       SIVAL(outbuf, smb_rcls, 0x80000005); /* STATUS_BUFFER_OVERFLOW */
+               } else {
+                       SCVAL(outbuf, smb_rcls, ERRDOS);
+                       SSVAL(outbuf, smb_err, ERRmoredata);
+               }
        }
 
        copy_trans_params_and_data(outbuf, align,
@@ -206,10 +207,10 @@ static void send_trans_reply(char *outbuf,
        SSVAL(outbuf,smb_vwv0,lparam);
        SSVAL(outbuf,smb_vwv1,ldata);
        SSVAL(outbuf,smb_vwv3,this_lparam);
-       SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
+       SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
        SSVAL(outbuf,smb_vwv5,0);
        SSVAL(outbuf,smb_vwv6,this_ldata);
-       SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
+       SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
        SSVAL(outbuf,smb_vwv8,0);
        SSVAL(outbuf,smb_vwv9,lsetup);
 
@@ -231,7 +232,7 @@ static void send_trans_reply(char *outbuf,
 
                align = (this_lparam%4);
 
-               set_message(outbuf,10,this_ldata+this_lparam+align,False);
+               set_message(outbuf,10,1+this_ldata+this_lparam+align,False);
 
                copy_trans_params_and_data(outbuf, align,
                                           rparam     , rdata,
@@ -239,10 +240,10 @@ static void send_trans_reply(char *outbuf,
                                           this_lparam, this_ldata);
 
                SSVAL(outbuf,smb_vwv3,this_lparam);
-               SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
+               SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
                SSVAL(outbuf,smb_vwv5,tot_param);
                SSVAL(outbuf,smb_vwv6,this_ldata);
-               SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
+               SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
                SSVAL(outbuf,smb_vwv8,tot_data);
                SSVAL(outbuf,smb_vwv9,0);
 
@@ -373,7 +374,7 @@ va_dcl
   }
 #if CHECK_TYPES
   str = va_arg(args,char*);
-  ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
+  SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
 #endif
   stringneeded = -1;
 
@@ -641,14 +642,20 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
     pstring fname;
 
     pstrcpy(fname,lp_driverfile());
-    f=fopen(fname,"r");
+    f=sys_fopen(fname,"r");
     if (!f) {
       DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
       desc->errcode=NERR_notsupported;
       return;
     }
 
-    p=(char *)malloc(8192*sizeof(char));
+    if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
+      DEBUG(0,("fill_printq_info: malloc fail !\n"));
+      desc->errcode=NERR_notsupported;
+      fclose(f);
+      return;
+    }
+
     bzero(p, 8192*sizeof(char));
     q=p;
 
@@ -658,7 +665,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
       p = q;                   /* reset string pointer */
       fgets(p,8191,f);
       p[strlen(p)-1]='\0';
-      if (next_token(&p,tok,":") &&
+      if (next_token(&p,tok,":",sizeof(tok)) &&
         (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
         (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
        ok=1;
@@ -666,9 +673,9 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
     fclose(f);
 
     /* driver file name */
-    if (ok && !next_token(&p,driver,":")) ok = 0;
+    if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0;
     /* data file name */
-    if (ok && !next_token(&p,datafile,":")) ok = 0;
+    if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0;
       /*
        * for the next tokens - which may be empty - I have to check for empty
        * tokens first because the next_token function will skip all empty
@@ -679,7 +686,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
       if (*p == ':') {
          *helpfile = '\0';
          p++;
-      } else if (!next_token(&p,helpfile,":")) ok = 0;
+      } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0;
     }
 
     if (ok) {
@@ -687,11 +694,11 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
       if (*p == ':') {
          *langmon = '\0';
          p++;
-      } else if (!next_token(&p,langmon,":")) ok = 0;
+      } else if (!next_token(&p,langmon,":",sizeof(langmon))) ok = 0;
     }
 
     /* default data type */
-    if (ok && !next_token(&p,datatype,":")) ok = 0;
+    if (ok && !next_token(&p,datatype,":",sizeof(datatype))) ok = 0;
 
     if (ok) {
       PACKI(desc,"W",0x0400);                    /* don't know */
@@ -714,7 +721,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
        /* no need to check return value here - it was already tested in
         * get_printerdrivernumber
         */
-        next_token(&p,tok,",");
+        next_token(&p,tok,",",sizeof(tok));
         PACKS(desc,"z",tok);                        /* driver files to copy */
         DEBUG(3,("file:%s:\n",tok));
       }
@@ -730,7 +737,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
 }
 
 /* This function returns the number of files for a given driver */
-int get_printerdrivernumber(int snum)
+static int get_printerdrivernumber(int snum)
 {
   int i=0,ok=0;
   pstring tok;
@@ -741,13 +748,18 @@ int get_printerdrivernumber(int snum)
   pstrcpy(fname,lp_driverfile());
 
   DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
-  f=fopen(fname,"r");
+  f=sys_fopen(fname,"r");
   if (!f) {
     DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
     return(0);
   }
 
-  p=(char *)malloc(8192*sizeof(char));
+  if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
+    DEBUG(3,("get_printerdrivernumber: malloc fail !\n"));
+    fclose(f);
+    return 0;
+  }
+
   q=p; /* need it to free memory because p change ! */
 
   /* lookup the long printer driver name in the file description */
@@ -755,7 +767,7 @@ int get_printerdrivernumber(int snum)
   {
     p = q;                     /* reset string pointer */
     fgets(p,8191,f);
-    if (next_token(&p,tok,":") &&
+    if (next_token(&p,tok,":",sizeof(tok)) &&
       (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum))))) 
        ok=1;
   }
@@ -771,7 +783,7 @@ int get_printerdrivernumber(int snum)
       return(0);
 
     /* count the number of files */
-    while (next_token(&p,tok,","))
+    while (next_token(&p,tok,",",sizeof(tok)))
        i++;
   }
   free(q);
@@ -789,7 +801,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
   char *QueueName = p;
-  int uLevel,cbBuf;
+  int uLevel;
   int count=0;
   int snum;
   char* str3;
@@ -802,7 +814,6 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
  
   p = skip_string(p,1);
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
   str3 = p + 4;
  
   /* remove any trailing username */
@@ -838,6 +849,26 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
   if (init_package(&desc,1,count)) {
          desc.subcount = count;
          fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
+  } else if(uLevel == 0) {
+       /*
+        * This is a *disgusting* hack.
+        * This is *so* bad that even I'm embarrassed (and I
+        * have no shame). Here's the deal :
+        * Until we get the correct SPOOLSS code into smbd
+        * then when we're running with NT SMB support then
+        * NT makes this call with a level of zero, and then
+        * immediately follows it with an open request to
+        * the \\SRVSVC pipe. If we allow that open to
+        * succeed then NT barfs when it cannot open the
+        * \\SPOOLSS pipe immediately after and continually
+        * whines saying "Printer name is invalid" forever
+        * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
+        * to fail, then NT downgrades to using the downlevel code
+        * and everything works as well as before. I hate
+        * myself for adding this code.... JRA.
+        */
+
+       fail_next_srvsvc_open();
   }
 
   *rdata_len = desc.usedlen;
@@ -889,11 +920,20 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param,
     if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
       queuecnt++;
   if (uLevel > 0) {
-    queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
+    if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
+      DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
+      return False;
+    }
     memset(queue,0,queuecnt*sizeof(print_queue_struct*));
-    status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
+    if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
+      DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
+      return False;
+    }
     memset(status,0,queuecnt*sizeof(print_status_struct));
-    subcntarr = (int*)malloc(queuecnt*sizeof(int));
+    if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
+      DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
+      return False;
+    }
     subcnt = 0;
     n = 0;
     for (i = 0; i < services; i++)
@@ -986,7 +1026,7 @@ static int get_server_info(uint32 servertype,
   pstrcat(fname,"/");
   pstrcat(fname,SERVER_LIST);
 
-  f = fopen(fname,"r");
+  f = sys_fopen(fname,"r");
 
   if (!f) {
     DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
@@ -1021,10 +1061,10 @@ static int get_server_info(uint32 servertype,
     }
     s = &(*servers)[count];
     
-    if (!next_token(&ptr,s->name   , NULL)) continue;
-    if (!next_token(&ptr,stype     , NULL)) continue;
-    if (!next_token(&ptr,s->comment, NULL)) continue;
-    if (!next_token(&ptr,s->domain , NULL)) {
+    if (!next_token(&ptr,s->name   , NULL, sizeof(s->name))) continue;
+    if (!next_token(&ptr,stype     , NULL, sizeof(stype))) continue;
+    if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
+    if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
       /* this allows us to cope with an old nmbd */
       pstrcpy(s->domain,global_myworkgroup); 
     }
@@ -1640,7 +1680,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
    * Older versions of Windows seem to do this.
    */
 
-  if (password_ok(user,pass1,strlen(pass1),NULL) &&
+  if (password_ok(user, pass1,strlen(pass1),NULL) &&
       chgpasswd(user,pass1,pass2,False))
   {
     SSVAL(*rparam,0,NERR_Success);
@@ -1679,11 +1719,7 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
                                int *rdata_len,int *rparam_len)
 {
   fstring user;
-  fstring new_passwd;
-  struct smb_passwd *sampw = NULL;
   char *p = param + 2;
-  int ret = True;
-
   *rparam_len = 2;
   *rparam = REALLOC(*rparam,*rparam_len);
 
@@ -1695,13 +1731,13 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
    * Check the parameter definition is correct.
    */
   if(!strequal(param + 2, "zsT")) {
-    DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
+    DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
     return False;
   }
   p = skip_string(p, 1);
 
   if(!strequal(p, "B516B16")) {
-    DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
+    DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
     return False;
   }
   p = skip_string(p,1);
@@ -1723,24 +1759,8 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *
    */
   (void)Get_Pwnam( user, True);
 
-  if(check_oem_password( user, (unsigned char *)data, &sampw, 
-                         new_passwd, (int)sizeof(new_passwd)) == False) {
-    return True;
-  }
-
-  /* 
-   * At this point we have the new case-sensitive plaintext
-   * password in the fstring new_passwd. If we wanted to synchronise
-   * with UNIX passwords we would call a UNIX password changing 
-   * function here. However it would have to be done as root
-   * as the plaintext of the old users password is not 
-   * available. JRA.
-   */
-
-  if(lp_unix_password_sync())
-    ret = chgpasswd(user,"", new_passwd, True);
-  if(ret && change_oem_password( sampw, new_passwd, False)) {
+  if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
+  {
     SSVAL(*rparam,0,NERR_Success);
   }
 
@@ -1985,7 +2005,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
                                    !become_service(fconn,True))
                                        break;
              
-                               if (sys_rename(fsp->fsp_name,name) == 0) {
+                               if (dos_rename(fsp->fsp_name,name) == 0) {
                                        string_set(&fsp->fsp_name,name);
                                }
                                break;
@@ -2370,7 +2390,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
        Don't depend on vuser being non-null !!. JRA */
     user_struct *vuser = get_valid_user_struct(vuid);
     if(vuser != NULL)
-      DEBUG(3,("  Username of UID %d is %s\n", vuser->uid, vuser->name));
+      DEBUG(3,("  Username of UID %d is %s\n", (int)vuser->uid, vuser->name));
 
     *rparam_len = 6;
     *rparam = REALLOC(*rparam,*rparam_len);
@@ -2675,7 +2695,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int uLevel,cbBuf;
+  int uLevel;
   int count;
   int i;
   int snum;
@@ -2685,7 +2705,6 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
   print_status_struct status;
 
   uLevel = SVAL(p,2);
-  cbBuf = SVAL(p,4);
 
   bzero(&desc,sizeof(desc));
   bzero(&status,sizeof(status));
@@ -2740,7 +2759,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
   char* name = p;
-  int uLevel,cbBuf;
+  int uLevel;
   int count;
   int i, succnt=0;
   int snum;
@@ -2753,7 +2772,6 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
 
   p = skip_string(p,1);
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
 
@@ -2858,7 +2876,7 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
   char* PrinterName = p;
-  int uLevel,cbBuf;
+  int uLevel;
   struct pack_desc desc;
   int snum;
 
@@ -2866,7 +2884,6 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par
 
   p = skip_string(p,1);
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
 
@@ -2916,7 +2933,7 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int uLevel,cbBuf;
+  int uLevel;
   int queuecnt;
   int i, n, succnt=0;
   struct pack_desc desc;
@@ -2925,7 +2942,6 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,
   bzero(&desc,sizeof(desc));
 
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
 
@@ -2974,14 +2990,13 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int uLevel,cbBuf;
+  int uLevel;
   int succnt;
   struct pack_desc desc;
 
   bzero(&desc,sizeof(desc));
 
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
 
@@ -3019,14 +3034,13 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int uLevel,cbBuf;
+  int uLevel;
   int succnt;
   struct pack_desc desc;
 
   bzero(&desc,sizeof(desc));
 
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
 
@@ -3065,14 +3079,13 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int uLevel,cbBuf;
+  int uLevel;
   int succnt;
   struct pack_desc desc;
 
   bzero(&desc,sizeof(desc));
 
   uLevel = SVAL(p,0);
-  cbBuf = SVAL(p,2);
 
   DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
 
@@ -3104,204 +3117,44 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
   return(True);
 }
 
-struct api_cmd
-{
-  char * pipe_clnt_name;
-  char * pipe_srv_name;
-  BOOL (*fn) (pipes_struct *, prs_struct *);
-};
-
-static struct api_cmd api_fd_commands[] =
-{
-    { "lsarpc",   "lsass",   api_ntlsa_rpc },
-    { "samr",     "lsass",   api_samr_rpc },
-    { "srvsvc",   "ntsvcs",  api_srvsvc_rpc },
-    { "wkssvc",   "ntsvcs",  api_wkssvc_rpc },
-    { "NETLOGON", "lsass",   api_netlog_rpc },
-    { "winreg",   "winreg",  api_reg_rpc },
-    { NULL,       NULL,      NULL }
-};
-
-static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
-{
-       BOOL ntlmssp_auth = False;
-       fstring ack_pipe_name;
-       int i = 0;
-
-       DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
-
-       for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
-       {
-               if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
-                   api_fd_commands[i].fn != NULL)
-               {
-                       DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
-                                  api_fd_commands[i].pipe_clnt_name,
-                                  api_fd_commands[i].pipe_srv_name));
-                       fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
-                       break;
-               }
-       }
-
-       if (api_fd_commands[i].fn == NULL) return False;
-
-       /* decode the bind request */
-       smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
-
-       if (pd->offset == 0) return False;
-
-       if (p->hdr.auth_len != 0)
-       {
-               /* decode the authentication verifier */
-               smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
-
-               if (pd->offset == 0) return False;
-
-               /* ignore the version number for now */
-               ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
-       }
-
-       /* name has to be \PIPE\xxxxx */
-       fstrcpy(ack_pipe_name, "\\PIPE\\");
-       fstrcat(ack_pipe_name, p->pipe_srv_name);
-
-       DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
-
-       prs_init(&(p->rdata), 1024, 4, 0, False);
-       prs_init(&(p->rhdr ), 0x10, 4, 0, False);
-       prs_init(&(p->rauth), 1024, 4, 0, False);
-
-    /***/
-       /*** do the bind ack first ***/
-    /***/
-
-       make_rpc_hdr_ba(&p->hdr_ba,
-                                       p->hdr_rb.bba.max_tsize,
-                       p->hdr_rb.bba.max_rsize,
-                       p->hdr_rb.bba.assoc_gid,
-                                       ack_pipe_name,
-                                       0x1, 0x0, 0x0,
-                                       &(p->hdr_rb.transfer));
-
-       smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
-       mem_realloc_data(p->rdata.data, p->rdata.offset);
-
-    /***/
-       /*** now the authentication ***/
-    /***/
-
-       if (ntlmssp_auth)
-       {
-               uint8 data[16];
-               bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
-
-               make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
-                                          0x0a, 0x06, 0,
-                                          "NTLMSSP", 2,
-                                          0x00000000, 0x0000b2b3, 0x000082b1,
-                                          data);
-               smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
-               mem_realloc_data(p->rauth.data, p->rauth.offset);
-       }
-
-    /***/
-       /*** then do the header, now we know the length ***/
-    /***/
-
-       make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
-                                p->hdr.call_id,
-                    p->rdata.offset + p->rauth.offset,
-                    p->rauth.offset);
-
-       smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
-       mem_realloc_data(p->rhdr.data, p->rdata.offset);
-
-    /***/
-       /*** link rpc header, bind acknowledgment and authentication responses ***/
-    /***/
-
-       p->rhdr.data->offset.start = 0;
-       p->rhdr.data->offset.end   = p->rhdr.offset;
-       p->rhdr.data->next         = p->rdata.data;
-
-       if (ntlmssp_auth)
-       {
-               p->rdata.data->offset.start = p->rhdr.offset;
-               p->rdata.data->offset.end   = p->rhdr.offset + p->rdata.offset;
-               p->rdata.data->next         = p->rauth.data;
-
-               p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
-               p->rauth.data->offset.end   = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
-               p->rauth.data->next         = NULL;
-       }
-       else
-       {
-               p->rdata.data->offset.start = p->rhdr.offset;
-               p->rdata.data->offset.end   = p->rhdr.offset + p->rdata.offset;
-               p->rdata.data->next         = NULL;
-       }
-
-       return True;
-}
-
-static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
+static void api_rpc_trans_reply(char *outbuf,
+                               pipes_struct *p,
+                               prs_struct *pd)
 {
-       int i = 0;
+       send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
 
-       for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
+       if (mem_buf_len(p->rhdr.data) <= p->file_offset)
        {
-               if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
-                   api_fd_commands[i].fn != NULL)
-               {
-                       DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
-                       return api_fd_commands[i].fn(p, pd);
-               }
+               /* all of data was sent: no need to wait for SMBreadX calls */
+               mem_free_data(p->rhdr .data);
+               mem_free_data(p->rdata.data);
+               mem_free_data(p->rdata_i.data);
        }
-       return False;
 }
 
-static BOOL api_dce_rpc_command(char *outbuf,
-                               pipes_struct *p,
-                               prs_struct *pd)
+/****************************************************************************
+ WaitNamedPipeHandleState 
+****************************************************************************/
+static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param)
 {
-       BOOL reply = False;
-       if (pd->data == NULL) return False;
-
-       /* process the rpc header */
-       smb_io_rpc_hdr("", &p->hdr, pd, 0);
+       uint16 priority;
 
-       if (pd->offset == 0) return False;
+       if (!param) return False;
 
-       switch (p->hdr.pkt_type)
-       {
-               case RPC_BIND   :
-               {
-                       reply = api_pipe_bind_req(p, pd);
-                       break;
-               }
-               case RPC_REQUEST:
-               {
-                       reply = api_pipe_request (p, pd);
-                       break;
-               }
-       }
+       priority = param[0] + (param[1] << 8);
+       DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
 
-       if (reply)
+       if (wait_rpc_pipe_hnd_state(p, priority))
        {
                /* now send the reply */
-               send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
+               send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->file_offset);
 
-               if (mem_buf_len(p->rhdr.data) <= p->file_offset)
-               {
-                       /* all of data was sent: no need to wait for SMBreadX calls */
-                       mem_free_data(p->rhdr .data);
-                       mem_free_data(p->rdata.data);
-               }
+               return True;
        }
-
-       return reply;
+       return False;
 }
 
+
 /****************************************************************************
  SetNamedPipeHandleState 
 ****************************************************************************/
@@ -3312,7 +3165,7 @@ static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
        if (!param) return False;
 
        id = param[0] + (param[1] << 8);
-       DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
+       DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
 
        if (set_rpc_pipe_hnd_state(p, id))
        {
@@ -3365,20 +3218,12 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
        int subcommand;
        pipes_struct *p = NULL;
        prs_struct pd;
-       struct mem_buf data_buf;
 
        DEBUG(5,("api_fd_reply\n"));
 
-       /* fake up a data buffer from the api_fd_reply data parameters */
-       mem_create(&data_buf, data, tdscnt, 0, False);
-       data_buf.offset.start = 0;
-       data_buf.offset.end   = tdscnt;
-
-       /* fake up a parsing structure */
-       pd.data = &data_buf;
-       pd.align = 4;
-       pd.io = True;
-       pd.offset = 0;
+       /* make a static data parsing structure from the api_fd_reply data */
+       prs_init(&pd, 0, 4, 0, True);
+       mem_create(pd.data, data, 0, tdscnt, 0, False);
 
        /* First find out the name of this file. */
        if (suwcnt != 2)
@@ -3398,7 +3243,8 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
                                  subcommand, p->name, pnum));
 
                /* record maximum data length that can be transmitted in an SMBtrans */
-               p->file_offset = mdrcnt;
+               p->file_offset          = mdrcnt;
+               p->prev_pdu_file_offset = 0;
 
                 DEBUG(10,("api_fd_reply: p:%p file_offset: %d\n",
                            p, p->file_offset));
@@ -3408,7 +3254,17 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
                        case 0x26:
                        {
                                /* dce/rpc command */
-                               reply = api_dce_rpc_command(outbuf, p, &pd);
+                               reply = rpc_command(p, &pd);
+                               if (reply)
+                               {
+                                       api_rpc_trans_reply(outbuf, p, &pd);
+                               }
+                               break;
+                       }
+                       case 0x53:
+                       {
+                               /* Wait Named Pipe Handle state */
+                               reply = api_WNPHS(outbuf, p, params);
                                break;
                        }
                        case 0x01:
@@ -3424,6 +3280,8 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
                DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
        }
 
+       mem_free_data(pd.data);
+
        if (!reply)
        {
                return api_no_reply(outbuf, mdrcnt);
@@ -3522,7 +3380,7 @@ struct
 static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
                     int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
 {
-  int api_command = SVAL(params,0);
+  int api_command;
   struct mem_buf rdata_buf;
   struct mem_buf rparam_buf;
   char *rdata = NULL;
@@ -3532,20 +3390,31 @@ static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data
   BOOL reply=False;
   int i;
 
+  SMB_ASSERT(params != 0);
+
+  api_command = SVAL(params,0);
+
   DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
-          api_command,params+2,skip_string(params+2,1),
+          api_command,
+          params+2,
+          skip_string(params+2,1),
           tdscnt,tpscnt,mdrcnt,mprcnt));
 
   for (i=0;api_commands[i].name;i++)
     if (api_commands[i].id == api_command && api_commands[i].fn)
       {
-       DEBUG(3,("Doing %s\n",api_commands[i].name));
-       break;
+        DEBUG(3,("Doing %s\n",api_commands[i].name));
+        break;
       }
 
   rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
   rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
 
+  if(!rdata || !rparam) {
+    DEBUG(0,("api_reply: malloc fail !\n"));
+    return -1;
+  }
+
   reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
                             &rdata,&rparam,&rdata_len,&rparam_len);
 
@@ -3564,14 +3433,8 @@ static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data
                    &rdata,&rparam,&rdata_len,&rparam_len);
 
       
-  mem_create(&rdata_buf , rdata , rdata_len , 0, False);
-  mem_create(&rparam_buf, rparam, rparam_len, 0, False);
-
-  rdata_buf.offset.start = 0;
-  rdata_buf.offset.end   = rdata_len;
-
-  rparam_buf.offset.start = 0;
-  rparam_buf.offset.end   = rparam_len;
+  mem_create(&rdata_buf , rdata , 0, rdata_len , 0, False);
+  mem_create(&rparam_buf, rparam, 0, rparam_len, 0, False);
 
   /* now send the reply */
   send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
@@ -3597,6 +3460,16 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na
                return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
        }
 
+       if (strequal(name,"WKSSVC") ||
+           strequal(name,"SRVSVC") ||
+           strequal(name,"WINREG") ||
+           strequal(name,"SAMR") ||
+           strequal(name,"LSARPC"))
+       {
+               DEBUG(4,("named pipe command from Win95 (wow!)\n"));
+               return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
+       }
+
        if (strlen(name) < 1)
        {
                return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
@@ -3617,7 +3490,7 @@ static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *na
 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
 {
        fstring name;
-
+        int name_offset = 0;
        char *data=NULL,*params=NULL;
        uint16 *setup=NULL;
        int outsize = 0;
@@ -3643,18 +3516,27 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        }
   
        if (tdscnt)  {
-               data = (char *)malloc(tdscnt);
+               if((data = (char *)malloc(tdscnt)) == NULL) {
+                       DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt));
+                       return(ERROR(ERRDOS,ERRnomem));
+               } 
                memcpy(data,smb_base(inbuf)+dsoff,dscnt);
        }
 
        if (tpscnt) {
-               params = (char *)malloc(tpscnt);
+               if((params = (char *)malloc(tpscnt)) == NULL) {
+                       DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt));
+                       return(ERROR(ERRDOS,ERRnomem));
+               } 
                memcpy(params,smb_base(inbuf)+psoff,pscnt);
        }
 
        if (suwcnt) {
                int i;
-               setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
+               if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
+          DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", suwcnt * sizeof(uint16)));
+                 return(ERROR(ERRDOS,ERRnomem));
+        } 
                for (i=0;i<suwcnt;i++)
                        setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
        }
@@ -3673,7 +3555,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
                BOOL ret;
                int pcnt,poff,dcnt,doff,pdisp,ddisp;
       
-               ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
+               ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
 
                if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret) {
                        if(ret) {
@@ -3718,9 +3600,19 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
                 name,tdscnt,tpscnt,suwcnt));
        
-       if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
+        /*
+         * WinCE wierdness....
+         */
+
+        if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine,
+                                strlen(local_machine)) == 0)) {
+          name_offset = strlen(local_machine)+1;
+        }
+
+       if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
                DEBUG(5,("calling named_pipe\n"));
-               outsize = named_pipe(conn,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
+               outsize = named_pipe(conn,vuid,outbuf,
+                                    name+name_offset+strlen("\\PIPE\\"),setup,data,params,
                                     suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
        } else {
                DEBUG(3,("invalid pipe name\n"));