Proper merge of all the working printing stuff from APPLIANCE_HEAD.
[nivanova/samba-autobuild/.git] / source3 / rpc_parse / parse_spoolss.c
index 841d303840cfb685eafb1c59056d9cf68564ebfe..017540638472b927c92063d30cd27dcf2b167f19 100644 (file)
@@ -48,7 +48,7 @@ static uint32 str_len_uni(UNISTR *source)
 This should be moved in a more generic lib.
 ********************************************************************/  
 
-static BOOL spoolss_io_system_time(char *desc, prs_struct *ps, int depth, SYSTEMTIME *systime)
+BOOL spoolss_io_system_time(char *desc, prs_struct *ps, int depth, SYSTEMTIME *systime)
 {
        if(!prs_uint16("year", ps, depth, &systime->year))
                return False;
@@ -124,7 +124,7 @@ reads or writes an DOC_INFO structure.
 
 static BOOL smb_io_doc_info(char *desc, DOC_INFO *info, prs_struct *ps, int depth)
 {
-       uint32 useless_ptr=1;
+       uint32 useless_ptr=0;
        
        if (info == NULL) return False;
 
@@ -324,53 +324,64 @@ static BOOL smb_io_notify_info_data(char *desc,SPOOL_NOTIFY_INFO_DATA *data, prs
 {
        uint32 useless_ptr=0xADDE0FF0;
 
-       uint32 how_many_words;
-       BOOL isvalue;
-       uint32 x;
-       
        prs_debug(ps, depth, desc, "smb_io_notify_info_data");
        depth++;
 
-       how_many_words=data->size;
-       if (how_many_words==POINTER) {
-               how_many_words=TWO_VALUE;
-       }
-       
-       isvalue=data->enc_type;
-
        if(!prs_align(ps))
                return False;
        if(!prs_uint16("type",           ps, depth, &data->type))
                return False;
        if(!prs_uint16("field",          ps, depth, &data->field))
                return False;
-       /*prs_align(ps);*/
 
-       if(!prs_uint32("how many words", ps, depth, &how_many_words))
+       if(!prs_uint32("how many words", ps, depth, &data->size))
                return False;
        if(!prs_uint32("id",             ps, depth, &data->id))
                return False;
-       if(!prs_uint32("how many words", ps, depth, &how_many_words))
+       if(!prs_uint32("how many words", ps, depth, &data->size))
                return False;
 
+       switch (data->enc_type) {
 
-       /*prs_align(ps);*/
+               /* One and two value data has two uint32 values */
+
+       case ONE_VALUE:
+       case TWO_VALUE:
 
-       if (isvalue==True) {
                if(!prs_uint32("value[0]", ps, depth, &data->notify_data.value[0]))
                        return False;
                if(!prs_uint32("value[1]", ps, depth, &data->notify_data.value[1]))
                        return False;
-               /*prs_align(ps);*/
-       } else {
-               /* it's a string */
-               /* length in ascii including \0 */
-               x=2*(data->notify_data.data.length+1);
-               if(!prs_uint32("string length", ps, depth, &x ))
+               break;
+
+               /* Pointers and strings have a string length and a
+                  pointer.  For a string the length is expressed as
+                  the number of uint16 characters plus a trailing
+                  \0\0. */
+
+       case POINTER:
+
+               if(!prs_uint32("string length", ps, depth, &data->notify_data.data.length ))
+                       return False;
+               if(!prs_uint32("pointer", ps, depth, &useless_ptr))
+                       return False;
+
+               break;
+
+       case STRING:
+
+               if(!prs_uint32("string length", ps, depth, &data->notify_data.data.length))
                        return False;
+
                if(!prs_uint32("pointer", ps, depth, &useless_ptr))
                        return False;
-               /*prs_align(ps);*/
+
+               break;
+
+       default:
+               DEBUG(3, ("invalid enc_type %d for smb_io_notify_info_data\n",
+                         data->enc_type));
+               break;
        }
 
        return True;
@@ -383,22 +394,79 @@ reads or writes an NOTIFY INFO DATA structure.
 BOOL smb_io_notify_info_data_strings(char *desc,SPOOL_NOTIFY_INFO_DATA *data,
                                      prs_struct *ps, int depth)
 {
-       uint32 x;
-       BOOL isvalue;
-       
        prs_debug(ps, depth, desc, "smb_io_notify_info_data_strings");
        depth++;
        
        if(!prs_align(ps))
                return False;
 
-       isvalue=data->enc_type;
+       switch(data->enc_type) {
+
+               /* No data for values */
+
+       case ONE_VALUE:
+       case TWO_VALUE:
+
+               break;
+
+               /* Strings start with a length in uint16s */
+
+       case STRING:
+
+               if (UNMARSHALLING(ps)) {
+                       data->notify_data.data.string = 
+                               (uint16 *)prs_alloc_mem(ps, data->notify_data.data.length);
+
+                       if (!data->notify_data.data.string) 
+                               return False;
+               }
+
+               if (MARSHALLING(ps))
+                       data->notify_data.data.length /= 2;
+
+               if(!prs_uint32("string length", ps, depth, &data->notify_data.data.length))
+                       return False;
+
+               if (!prs_uint16uni(True, "string", ps, depth, data->notify_data.data.string,
+                                  data->notify_data.data.length))
+                       return False;
+
+               if (MARSHALLING(ps))
+                       data->notify_data.data.length *= 2;
+
+               break;
+
+       case POINTER:
+
+               if (UNMARSHALLING(ps)) {
+                       data->notify_data.data.string = 
+                               (uint16 *)prs_alloc_mem(ps, data->notify_data.data.length);
+
+                       if (!data->notify_data.data.string) 
+                               return False;
+               }
+
+               if(!prs_uint8s(True,"buffer",ps,depth,(uint8*)data->notify_data.data.string,data->notify_data.data.length))
+                       return False;
+
+               break;
+
+       default:
+               DEBUG(3, ("invalid enc_type %d for smb_io_notify_info_data_strings\n",
+                         data->enc_type));
+               break;
+       }
 
+#if 0
        if (isvalue==False) {
+
                /* length of string in unicode include \0 */
                x=data->notify_data.data.length+1;
+
+               if (data->field != 16)
                if(!prs_uint32("string length", ps, depth, &x ))
                        return False;
+
                if (MARSHALLING(ps)) {
                        /* These are already in little endian format. Don't byte swap. */
                        if (x == 1) {
@@ -412,6 +480,10 @@ BOOL smb_io_notify_info_data_strings(char *desc,SPOOL_NOTIFY_INFO_DATA *data,
                                if(!prs_uint8s(True,"string",ps,depth, (uint8 *)&data->notify_data.data.length,x*2)) 
                                        return False;
                        } else {
+
+                               if (data->field == 16)
+                                       x /= 2;
+
                                if(!prs_uint16uni(True,"string",ps,depth,data->notify_data.data.string,x))
                                        return False;
                        }
@@ -427,10 +499,11 @@ BOOL smb_io_notify_info_data_strings(char *desc,SPOOL_NOTIFY_INFO_DATA *data,
                                return False;
                }
        }
-#if 0  /* JERRY */
 
-       /* Win2k does not seem to put this parse align here */
+#endif
 
+#if 0  /* JERRY */
+       /* Win2k does not seem to put this parse align here */
        if(!prs_align(ps))
                return False;
 #endif
@@ -959,6 +1032,7 @@ BOOL make_spoolss_printer_info_2(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_2
        return True;
 }
 
+
 /*******************************************************************
  * read a structure.
  * called from spoolss_q_open_printer_ex (srv_spoolss.c)
@@ -1209,8 +1283,11 @@ BOOL spoolss_io_r_getprinterdata(char *desc, SPOOL_R_GETPRINTERDATA *r_u, prs_st
        if (!prs_uint32("size", ps, depth, &r_u->size))
                return False;
        
-       if (UNMARSHALLING(ps))
+       if (UNMARSHALLING(ps) && r_u->size) {
                r_u->data = prs_alloc_mem(ps, r_u->size);
+               if(r_u->data)
+                       return False;
+       }
 
        if (!prs_uint8s(False,"data", ps, depth, r_u->data, r_u->size))
                return False;
@@ -5748,9 +5825,7 @@ BOOL spoolss_io_r_enumprinterdata(char *desc, SPOOL_R_ENUMPRINTERDATA *r_u, prs_
                return False;
 
        if (UNMARSHALLING(ps) && r_u->valuesize) {
-
                r_u->value = (uint16 *)prs_alloc_mem(ps, r_u->valuesize * 2);
-
                if (!r_u->value) {
                        DEBUG(0, ("spoolss_io_r_enumprinterdata: out of memory for printerdata value\n"));
                        return False;
@@ -5773,10 +5848,8 @@ BOOL spoolss_io_r_enumprinterdata(char *desc, SPOOL_R_ENUMPRINTERDATA *r_u, prs_
                return False;
 
        if (UNMARSHALLING(ps) && r_u->datasize) {
-
                r_u->data = (uint8 *)prs_alloc_mem(ps, r_u->datasize);
-
-               if (!r_u->value) {
+               if (!r_u->data) {
                        DEBUG(0, ("spoolss_io_r_enumprinterdata: out of memory for printerdata data\n"));
                        return False;
                }