r23792: convert Samba4 to GPLv3
[kai/samba.git] / source4 / torture / rpc / spoolss.c
index 7f56212b74ae1f00258df6fb5933f961409b7d3e..bfedfc9d5c81150a1592f3a780897adc67be741d 100644 (file)
@@ -7,7 +7,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "librpc/gen_ndr/ndr_spoolss.h"
+#include "torture/torture.h"
+#include "torture/rpc/rpc.h"
+#include "librpc/gen_ndr/ndr_spoolss_c.h"
 
 struct test_spoolss_context {
        struct dcerpc_pipe *p;
@@ -62,34 +63,60 @@ struct test_spoolss_context {
        }\
 } while(0)
 
+/* not every compiler supports __typeof__() */
+#if (__GNUC__ >= 3)
+#define _CHECK_FIELD_SIZE(c,r,e,type) do {\
+       if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
+               printf(__location__ ":" #c "." #e "field is not " #type "\n"); \
+               smb_panic(__location__ ":" #c "." #e "field is not " #type ); \
+               ret = False; \
+       }\
+       if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
+               printf(__location__ ":" #r "." #e "field is not " #type "\n"); \
+               smb_panic(__location__ ":" #r "." #e "field is not " #type ); \
+               ret = False; \
+       }\
+} while(0)
+#else
+#define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
+#endif
+
+#if 0 /* unused */
 #define COMPARE_UINT16(c,r,e) do {\
+       _CHECK_FIELD_SIZE(c,r,e,uint16_t); \
        if (c.e != r.e){\
-               printf("%s: " #c "." #e "  0x%08X (%u) doesn't match " #r "." #e " 0x%08X (%u)\n",\
+               printf("%s: " #c "." #e "  0x%04X (%u) doesn't match " #r "." #e " 0x%04X (%u)\n",\
                        __location__, c.e, c.e, r.e, r.e);\
                ret = False;\
        }\
 } while(0)
+#endif
 
 #define COMPARE_UINT32(c,r,e) do {\
+       _CHECK_FIELD_SIZE(c,r,e,uint32_t); \
        if (c.e != r.e){\
-               printf("%s: " #c "." #e "  0x%04X (%u) doesn't match " #r "." #e " 0x%04X (%u)\n",\
+               printf("%s: " #c "." #e "  0x%08X (%u) doesn't match " #r "." #e " 0x%08X (%u)\n",\
                        __location__, c.e, c.e, r.e, r.e);\
                ret = False;\
        }\
 } while(0)
 
+#if 0 /* unused */
 #define COMPARE_UINT64(c,r,e) do {\
+       _CHECK_FIELD_SIZE(c,r,e,uint64_t); \
        if (c.e != r.e){\
-               printf("%s: " #c "." #e "  0x%08X%08X (%llu) doesn't match " #r "." #e " 0x%08X%08X (%llu)\n",\
-                       __location__, (uint32_t)(c.e >> 32), (uint32_t)(c.e & 0xFFFFFFFF), c.e,\
-                       (uint32_t)(r.e >> 32), (uint32_t)(r.e & 0xFFFFFFFF), r.e);\
+               printf("%s: " #c "." #e "  0x%016llX (%llu) doesn't match " #r "." #e " 0x%016llX (%llu)\n",\
+                       __location__, c.e, c.e, r.e, r.e);\
                ret = False;\
        }\
 } while(0)
+#endif
 
 /* TODO: ! */
+#if 0 /* unused */
 #define COMPARE_SEC_DESC(c,r,e)
 #define COMPARE_SPOOLSS_TIME(c,r,e)
+#endif
 #define COMPARE_STRING_ARRAY(c,r,e)
 
 static BOOL test_OpenPrinter_server(struct test_spoolss_context *ctx)
@@ -100,7 +127,6 @@ static BOOL test_OpenPrinter_server(struct test_spoolss_context *ctx)
 
        op.in.printername       = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(ctx->p));
        op.in.datatype          = NULL;
-       op.in.devmode_ctr.size  = 0;
        op.in.devmode_ctr.devmode= NULL;
        op.in.access_mask       = 0;
        op.out.handle           = &ctx->server_handle;
@@ -132,14 +158,11 @@ static BOOL test_EnumPorts(struct test_spoolss_context *ctx)
        for (i=0;i<ARRAY_SIZE(levels);i++) {
                int level = levels[i];
                DATA_BLOB blob;
-               uint32_t buf_size = 0;
 
                r.in.servername = "";
                r.in.level = level;
                r.in.buffer = NULL;
-               buf_size = 0;
-               r.in.buf_size = &buf_size;
-               r.out.buf_size = &buf_size;
+               r.in.offered = 0;
 
                printf("Testing EnumPorts level %u\n", r.in.level);
 
@@ -149,7 +172,10 @@ static BOOL test_EnumPorts(struct test_spoolss_context *ctx)
                        ret = False;
                        continue;
                }
-
+               if (W_ERROR_IS_OK(r.out.result)) {
+                       /* TODO: do some more checks here */
+                       continue;
+               }
                if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
                        printf("EnumPorts unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
                                win_errstr(r.out.result));
@@ -157,9 +183,10 @@ static BOOL test_EnumPorts(struct test_spoolss_context *ctx)
                        continue;
                }
 
-               blob = data_blob_talloc(ctx, NULL, buf_size);
+               blob = data_blob_talloc(ctx, NULL, r.out.needed);
                data_blob_clear(&blob);
                r.in.buffer = &blob;
+               r.in.offered = r.out.needed;
 
                status = dcerpc_spoolss_EnumPorts(ctx->p, ctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
@@ -210,6 +237,81 @@ static BOOL test_EnumPorts(struct test_spoolss_context *ctx)
        return True;
 }
 
+static BOOL test_GetPrinterDriverDirectory(struct test_spoolss_context *ctx)
+{
+       NTSTATUS status;
+       struct spoolss_GetPrinterDriverDirectory r;
+       struct {
+               uint16_t level;
+               const char *server;
+       } levels[] = {{
+                       .level  = 1,
+                       .server = NULL
+               },{
+                       .level  = 1,
+                       .server = ""
+               },{
+                       .level  = 78,
+                       .server = ""
+               },{
+                       .level  = 1,
+                       .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(ctx->p))
+               },{
+                       .level  = 1024,
+                       .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(ctx->p))
+               }
+       };
+       int i;
+       BOOL ret = True;
+
+       for (i=0;i<ARRAY_SIZE(levels);i++) {
+               int level = levels[i].level;
+               DATA_BLOB blob;
+
+               r.in.server             = levels[i].server;
+               r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
+               r.in.level              = level;
+               r.in.buffer             = NULL;
+               r.in.offered            = 0;
+
+               printf("Testing GetPrinterDriverDirectory level %u\n", r.in.level);
+
+               status = dcerpc_spoolss_GetPrinterDriverDirectory(ctx->p, ctx, &r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("dcerpc_spoolss_GetPrinterDriverDirectory failed - %s\n", nt_errstr(status));
+                       ret = False;
+                       continue;
+               }
+               if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
+                       printf("GetPrinterDriverDirectory unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
+                               win_errstr(r.out.result));
+                       ret = False;
+                       continue;
+               }
+
+               blob = data_blob_talloc(ctx, NULL, r.out.needed);
+               data_blob_clear(&blob);
+               r.in.buffer = &blob;
+               r.in.offered = r.out.needed;
+
+               status = dcerpc_spoolss_GetPrinterDriverDirectory(ctx->p, ctx, &r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("dcerpc_spoolss_GetPrinterDriverDirectory failed - %s\n", nt_errstr(status));
+                       ret = False;
+                       continue;
+               }
+
+               if (!W_ERROR_IS_OK(r.out.result)) {
+                       printf("GetPrinterDriverDirectory failed - %s\n",
+                               win_errstr(r.out.result));
+                       ret = False;
+                       continue;
+               }
+       }
+
+       return True;
+}
+
 static BOOL test_EnumPrinterDrivers(struct test_spoolss_context *ctx)
 {
        NTSTATUS status;
@@ -221,15 +323,12 @@ static BOOL test_EnumPrinterDrivers(struct test_spoolss_context *ctx)
        for (i=0;i<ARRAY_SIZE(levels);i++) {
                int level = levels[i];
                DATA_BLOB blob;
-               uint32_t buf_size = 0;
 
-               r.in.server = "";
-               r.in.environment = "Windows NT x86";
-               r.in.level = level;
-               r.in.buffer = NULL;
-               buf_size = 0;
-               r.in.buf_size = &buf_size;
-               r.out.buf_size = &buf_size;
+               r.in.server             = "";
+               r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
+               r.in.level              = level;
+               r.in.buffer             = NULL;
+               r.in.offered            = 0;
 
                printf("Testing EnumPrinterDrivers level %u\n", r.in.level);
 
@@ -239,7 +338,10 @@ static BOOL test_EnumPrinterDrivers(struct test_spoolss_context *ctx)
                        ret = False;
                        continue;
                }
-
+               if (W_ERROR_IS_OK(r.out.result)) {
+                       /* TODO: do some more checks here */
+                       continue;
+               }
                if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
                        printf("EnumPrinterDrivers unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
                                win_errstr(r.out.result));
@@ -247,9 +349,10 @@ static BOOL test_EnumPrinterDrivers(struct test_spoolss_context *ctx)
                        continue;
                }
 
-               blob = data_blob_talloc(ctx, NULL, buf_size);
+               blob = data_blob_talloc(ctx, NULL, r.out.needed);
                data_blob_clear(&blob);
                r.in.buffer = &blob;
+               r.in.offered = r.out.needed;
 
                status = dcerpc_spoolss_EnumPrinterDrivers(ctx->p, ctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
@@ -355,14 +458,11 @@ static BOOL test_EnumMonitors(struct test_spoolss_context *ctx)
        for (i=0;i<ARRAY_SIZE(levels);i++) {
                int level = levels[i];
                DATA_BLOB blob;
-               uint32_t buf_size = 0;
 
                r.in.servername = "";
                r.in.level = level;
                r.in.buffer = NULL;
-               buf_size = 0;
-               r.in.buf_size = &buf_size;
-               r.out.buf_size = &buf_size;
+               r.in.offered = 0;
 
                printf("Testing EnumMonitors level %u\n", r.in.level);
 
@@ -372,7 +472,10 @@ static BOOL test_EnumMonitors(struct test_spoolss_context *ctx)
                        ret = False;
                        continue;
                }
-
+               if (W_ERROR_IS_OK(r.out.result)) {
+                       /* TODO: do some more checks here */
+                       continue;
+               }
                if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
                        printf("EnumMonitors unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
                                win_errstr(r.out.result));
@@ -380,9 +483,10 @@ static BOOL test_EnumMonitors(struct test_spoolss_context *ctx)
                        continue;
                }
 
-               blob = data_blob_talloc(ctx, NULL, buf_size);
+               blob = data_blob_talloc(ctx, NULL, r.out.needed);
                data_blob_clear(&blob);
                r.in.buffer = &blob;
+               r.in.offered = r.out.needed;
 
                status = dcerpc_spoolss_EnumMonitors(ctx->p, ctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
@@ -444,15 +548,12 @@ static BOOL test_EnumPrintProcessors(struct test_spoolss_context *ctx)
        for (i=0;i<ARRAY_SIZE(levels);i++) {
                int level = levels[i];
                DATA_BLOB blob;
-               uint32_t buf_size = 0;
 
                r.in.servername = "";
                r.in.environment = "Windows NT x86";
                r.in.level = level;
                r.in.buffer = NULL;
-               buf_size = 0;
-               r.in.buf_size = &buf_size;
-               r.out.buf_size = &buf_size;
+               r.in.offered = 0;
 
                printf("Testing EnumPrintProcessors level %u\n", r.in.level);
 
@@ -462,7 +563,10 @@ static BOOL test_EnumPrintProcessors(struct test_spoolss_context *ctx)
                        ret = False;
                        continue;
                }
-
+               if (W_ERROR_IS_OK(r.out.result)) {
+                       /* TODO: do some more checks here */
+                       continue;
+               }
                if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
                        printf("EnumPrintProcessors unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
                                win_errstr(r.out.result));
@@ -470,9 +574,10 @@ static BOOL test_EnumPrintProcessors(struct test_spoolss_context *ctx)
                        continue;
                }
 
-               blob = data_blob_talloc(ctx, NULL, buf_size);
+               blob = data_blob_talloc(ctx, NULL, r.out.needed);
                data_blob_clear(&blob);
                r.in.buffer = &blob;
+               r.in.offered = r.out.needed;
 
                status = dcerpc_spoolss_EnumPrintProcessors(ctx->p, ctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
@@ -533,14 +638,12 @@ static BOOL test_EnumPrinters(struct test_spoolss_context *ctx)
        for (i=0;i<ARRAY_SIZE(levels);i++) {
                int level = levels[i];
                DATA_BLOB blob;
-               uint32_t buf_size = 0;
 
                r.in.flags      = PRINTER_ENUM_LOCAL;
                r.in.server     = "";
                r.in.level      = level;
                r.in.buffer     = NULL;
-               r.in.buf_size   = &buf_size;
-               r.out.buf_size  = &buf_size;
+               r.in.offered    = 0;
 
                printf("\nTesting EnumPrinters level %u\n", r.in.level);
 
@@ -550,7 +653,10 @@ static BOOL test_EnumPrinters(struct test_spoolss_context *ctx)
                        ret = False;
                        continue;
                }
-
+               if (W_ERROR_IS_OK(r.out.result)) {
+                       /* TODO: do some more checks here */
+                       continue;
+               }
                if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
                        printf("EnumPrinters unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n",
                                win_errstr(r.out.result));
@@ -558,9 +664,11 @@ static BOOL test_EnumPrinters(struct test_spoolss_context *ctx)
                        continue;
                }
 
-               blob = data_blob_talloc(ctx, NULL, buf_size);
+               blob = data_blob_talloc(ctx, NULL, r.out.needed);
                data_blob_clear(&blob);
                r.in.buffer = &blob;
+               r.in.offered = r.out.needed;
+
                status = dcerpc_spoolss_EnumPrinters(ctx->p, ctx, &r);
                if (!NT_STATUS_IS_OK(status)) {
                        printf("dcerpc_spoolss_EnumPrinters failed - %s\n", nt_errstr(status));
@@ -669,12 +777,10 @@ static BOOL test_GetPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        BOOL ret = True;
        
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               uint32_t buf_size = 0;
                r.in.handle = handle;
                r.in.level = levels[i];
                r.in.buffer = NULL;
-               r.in.buf_size = &buf_size;
-               r.out.buf_size = &buf_size;
+               r.in.offered = 0;
 
                printf("Testing GetPrinter level %u\n", r.in.level);
 
@@ -686,9 +792,10 @@ static BOOL test_GetPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                }
                
                if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
-                       DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
+                       DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
                        data_blob_clear(&blob);
                        r.in.buffer = &blob;
+                       r.in.offered = r.out.needed;
                        status = dcerpc_spoolss_GetPrinter(p, mem_ctx, &r);
                }
                
@@ -697,7 +804,7 @@ static BOOL test_GetPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                        ret = False;
                        continue;
                }
-               
+
                if (!W_ERROR_IS_OK(r.out.result)) {
                        printf("GetPrinter failed - %s\n", 
                               win_errstr(r.out.result));
@@ -736,83 +843,99 @@ static BOOL test_GetForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 {
        NTSTATUS status;
        struct spoolss_GetForm r;
-       uint32_t buf_size;
 
        r.in.handle = handle;
        r.in.form_name = form_name;
        r.in.level = 1;
        r.in.buffer = NULL;
-       buf_size = 0;
-       r.in.buf_size = r.out.buf_size = &buf_size;
+       r.in.offered = 0;
 
        printf("Testing GetForm\n");
 
        status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
-
        if (!NT_STATUS_IS_OK(status)) {
                printf("GetForm failed - %s\n", nt_errstr(status));
                return False;
        }
 
        if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
-               DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
-
+               DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
                data_blob_clear(&blob);
                r.in.buffer = &blob;
-
+               r.in.offered = r.out.needed;
                status = dcerpc_spoolss_GetForm(p, mem_ctx, &r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("GetForm failed - %s\n",
+                               nt_errstr(status));
+                       return False;
+               }
+
+               if (!W_ERROR_IS_OK(r.out.result)) {
+                       printf("GetForm failed - %s\n",
+                               win_errstr(r.out.result));
+                       return False;
+               }
 
                if (!r.out.info) {
-                       printf("No form info returned");
+                       printf("No form info returned\n");
                        return False;
                }
        }
 
+
+       if (!W_ERROR_IS_OK(r.out.result)) {
+               printf("GetForm failed - %s\n",
+                       win_errstr(r.out.result));
+               return False;
+       }
+
        return True;
 }
 
 static BOOL test_EnumForms(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                   struct policy_handle *handle)
+                   struct policy_handle *handle, BOOL print_server)
 {
        NTSTATUS status;
        struct spoolss_EnumForms r;
-       uint32_t buf_size;
+       BOOL ret = True;
 
        r.in.handle = handle;
        r.in.level = 1;
        r.in.buffer = NULL;
-       buf_size = 0;
-       r.in.buf_size = &buf_size;
-       r.out.buf_size = &buf_size;
+       r.in.offered = 0;
 
        printf("Testing EnumForms\n");
 
        status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
-
        if (!NT_STATUS_IS_OK(status)) {
                printf("EnumForms failed - %s\n", nt_errstr(status));
                return False;
        }
 
+       if (print_server && W_ERROR_EQUAL(r.out.result,WERR_BADFID)) {
+               printf("EnumForms on the PrintServer isn't supported by test server (NT4)\n");
+               return True;
+       }
+
        if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
-               DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
                union spoolss_FormInfo *info;
                int j;
-
+               DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
                data_blob_clear(&blob);
                r.in.buffer = &blob;
+               r.in.offered = r.out.needed;
 
                status = dcerpc_spoolss_EnumForms(p, mem_ctx, &r);
 
                if (!r.out.info) {
-                       printf("No forms returned");
+                       printf("No forms returned\n");
                        return False;
                }
 
                info = r.out.info;
 
                for (j = 0; j < r.out.count; j++) {
-                       test_GetForm(p, mem_ctx, handle, info[j].info1.form_name);
+                       if (!print_server) ret &= test_GetForm(p, mem_ctx, handle, info[j].info1.form_name);
                }
        }
 
@@ -855,7 +978,7 @@ static BOOL test_DeleteForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 }
 
 static BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                 struct policy_handle *handle)
+                 struct policy_handle *handle, BOOL print_server)
 {
        struct spoolss_AddForm r;
        struct spoolss_AddFormInfo1 addform;
@@ -883,13 +1006,15 @@ static BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        }
 
        if (!W_ERROR_IS_OK(r.out.result)) {
-               printf("AddForm failed - %s\n", nt_errstr(status));
+               printf("AddForm failed - %s\n", win_errstr(r.out.result));
                goto done;
        }
 
+       if (!print_server) ret &= test_GetForm(p, mem_ctx, handle, form_name);
+
        {
                struct spoolss_SetForm sf;
-               struct spoolss_SetFormInfo1 setform;
+               struct spoolss_AddFormInfo1 setform;
 
                sf.in.handle    = handle;
                sf.in.form_name = form_name;
@@ -918,6 +1043,8 @@ static BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                }
        }
 
+       if (!print_server) ret &= test_GetForm(p, mem_ctx, handle, form_name);
+
  done:
        if (!test_DeleteForm(p, mem_ctx, handle, form_name)) {
                printf("DeleteForm failed\n");
@@ -931,15 +1058,12 @@ static BOOL test_EnumPorts_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
 {
        NTSTATUS status;
        struct spoolss_EnumPorts r;
-       uint32_t buf_size;
 
        r.in.servername = talloc_asprintf(mem_ctx, "\\\\%s", 
                                          dcerpc_server_name(p));
        r.in.level = 2;
        r.in.buffer = NULL;
-       buf_size = 0;
-       r.in.buf_size = &buf_size;
-       r.out.buf_size = &buf_size;
+       r.in.offered = 0;
 
        printf("Testing EnumPorts\n");
 
@@ -951,20 +1075,19 @@ static BOOL test_EnumPorts_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        }
 
        if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
-               DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
-
+               DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
                data_blob_clear(&blob);
                r.in.buffer = &blob;
+               r.in.offered = r.out.needed;
 
                status = dcerpc_spoolss_EnumPorts(p, mem_ctx, &r);
-
                if (!NT_STATUS_IS_OK(status)) {
                        printf("EnumPorts failed - %s\n", nt_errstr(status));
                        return False;
                }
 
                if (!r.out.info) {
-                       printf("No ports returned");
+                       printf("No ports returned\n");
                        return False;
                }
        }
@@ -1010,34 +1133,31 @@ static BOOL test_GetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 {
        NTSTATUS status;
        struct spoolss_GetJob r;
-       uint32_t buf_size;
 
        r.in.handle = handle;
        r.in.job_id = job_id;
        r.in.level = 1;
        r.in.buffer = NULL;
-       buf_size = 0;
-       r.in.buf_size = r.out.buf_size = &buf_size;
+       r.in.offered = 0;
 
        printf("Testing GetJob\n");
 
        status = dcerpc_spoolss_GetJob(p, mem_ctx, &r);
-
        if (!NT_STATUS_IS_OK(status)) {
                printf("GetJob failed - %s\n", nt_errstr(status));
                return False;
        }
 
        if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
-               DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
-
+               DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
                data_blob_clear(&blob);
                r.in.buffer = &blob;
+               r.in.offered = r.out.needed;
 
                status = dcerpc_spoolss_GetJob(p, mem_ctx, &r);
 
                if (!r.out.info) {
-                       printf("No job info returned");
+                       printf("No job info returned\n");
                        return False;
                }
        }
@@ -1046,24 +1166,27 @@ static BOOL test_GetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 }
 
 static BOOL test_SetJob(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
-                struct policy_handle *handle, uint32_t job_id, uint32_t command)
+                struct policy_handle *handle, uint32_t job_id, enum spoolss_JobControl command)
 {
        NTSTATUS status;
        struct spoolss_SetJob r;
 
-       r.in.handle = handle;
-       r.in.job_id = job_id;
-       r.in.level = 0;
-       r.in.command = command;
+       r.in.handle     = handle;
+       r.in.job_id     = job_id;
+       r.in.ctr        = NULL;
+       r.in.command    = command;
 
        printf("Testing SetJob\n");
 
        status = dcerpc_spoolss_SetJob(p, mem_ctx, &r);
-
        if (!NT_STATUS_IS_OK(status)) {
                printf("SetJob failed - %s\n", nt_errstr(status));
                return False;
        }
+       if (!W_ERROR_IS_OK(r.out.result)) {
+               printf("SetJob failed - %s\n", win_errstr(r.out.result));
+               return False;
+       }
 
        return True;
 }
@@ -1073,16 +1196,13 @@ static BOOL test_EnumJobs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 {
        NTSTATUS status;
        struct spoolss_EnumJobs r;
-       uint32_t buf_size;
 
        r.in.handle = handle;
        r.in.firstjob = 0;
        r.in.numjobs = 0xffffffff;
        r.in.level = 1;
        r.in.buffer = NULL;
-       buf_size = 0;
-       r.in.buf_size = &buf_size;
-       r.out.buf_size = &buf_size;
+       r.in.offered = 0;
 
        printf("Testing EnumJobs\n");
 
@@ -1094,17 +1214,17 @@ static BOOL test_EnumJobs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        }
 
        if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
-               DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
                union spoolss_JobInfo *info;
                int j;
-
+               DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
                data_blob_clear(&blob);
                r.in.buffer = &blob;
+               r.in.offered = r.out.needed;
 
                status = dcerpc_spoolss_EnumJobs(p, mem_ctx, &r);
 
                if (!r.out.info) {
-                       printf("No jobs returned");
+                       printf("No jobs returned\n");
                        return True;
                }
 
@@ -1112,7 +1232,8 @@ static BOOL test_EnumJobs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
                for (j = 0; j < r.out.count; j++) {
                        test_GetJob(p, mem_ctx, handle, info[j].info1.job_id);
-                       test_SetJob(p, mem_ctx, handle, info[j].info1.job_id, 1);
+                       test_SetJob(p, mem_ctx, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
+                       test_SetJob(p, mem_ctx, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
                }
 
        } else if (!W_ERROR_IS_OK(r.out.result)) {
@@ -1123,32 +1244,190 @@ static BOOL test_EnumJobs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        return True;
 }
 
+static BOOL test_DoPrintTest(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                  struct policy_handle *handle)
+{
+       BOOL ret = True;
+       NTSTATUS status;
+       struct spoolss_StartDocPrinter s;
+       struct spoolss_DocumentInfo1 info1;
+       struct spoolss_StartPagePrinter sp;
+       struct spoolss_WritePrinter w;
+       struct spoolss_EndPagePrinter ep;
+       struct spoolss_EndDocPrinter e;
+       int i;
+       uint32_t job_id;
+
+       printf("Testing StartDocPrinter\n");
+
+       s.in.handle             = handle;
+       s.in.level              = 1;
+       s.in.info.info1         = &info1;
+       info1.document_name     = "TorturePrintJob";
+       info1.output_file       = NULL;
+       info1.datatype          = "RAW";
+
+       status = dcerpc_spoolss_StartDocPrinter(p, mem_ctx, &s);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("dcerpc_spoolss_StartDocPrinter failed - %s\n", nt_errstr(status));
+               return False;
+       }
+       if (!W_ERROR_IS_OK(s.out.result)) {
+               printf("StartDocPrinter failed - %s\n", win_errstr(s.out.result));
+               return False;
+       }
+
+       job_id = s.out.job_id;
+
+       for (i=1; i < 4; i++) {
+               printf("Testing StartPagePrinter: Page[%d]\n", i);
+
+               sp.in.handle            = handle;
+
+               status = dcerpc_spoolss_StartPagePrinter(p, mem_ctx, &sp);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("dcerpc_spoolss_StartPagePrinter failed - %s\n", nt_errstr(status));
+                       return False;
+               }
+               if (!W_ERROR_IS_OK(sp.out.result)) {
+                       printf("StartPagePrinter failed - %s\n", win_errstr(sp.out.result));
+                       return False;
+               }
+
+               printf("Testing WritePrinter: Page[%d]\n", i);
+
+               w.in.handle             = handle;
+               w.in.data               = data_blob_string_const(talloc_asprintf(mem_ctx,"TortureTestPage: %d\nData\n",i));
+
+               status = dcerpc_spoolss_WritePrinter(p, mem_ctx, &w);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("dcerpc_spoolss_WritePrinter failed - %s\n", nt_errstr(status));
+                       return False;
+               }
+               if (!W_ERROR_IS_OK(w.out.result)) {
+                       printf("WritePrinter failed - %s\n", win_errstr(w.out.result));
+                       return False;
+               }
+
+               printf("Testing EndPagePrinter: Page[%d]\n", i);
+
+               ep.in.handle            = handle;
+
+               status = dcerpc_spoolss_EndPagePrinter(p, mem_ctx, &ep);
+               if (!NT_STATUS_IS_OK(status)) {
+                       printf("dcerpc_spoolss_EndPagePrinter failed - %s\n", nt_errstr(status));
+                       return False;
+               }
+               if (!W_ERROR_IS_OK(ep.out.result)) {
+                       printf("EndPagePrinter failed - %s\n", win_errstr(ep.out.result));
+                       return False;
+               }
+       }
+
+       printf("Testing EndDocPrinter\n");
+
+       e.in.handle = handle;
+
+       status = dcerpc_spoolss_EndDocPrinter(p, mem_ctx, &e);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("dcerpc_spoolss_EndDocPrinter failed - %s\n", nt_errstr(status));
+               return False;
+       }
+       if (!W_ERROR_IS_OK(e.out.result)) {
+               printf("EndDocPrinter failed - %s\n", win_errstr(e.out.result));
+               return False;
+       }
+
+       ret &= test_EnumJobs(p, mem_ctx, handle);
+
+       ret &= test_SetJob(p, mem_ctx, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
+
+       return ret;
+}
+
+static BOOL test_PausePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                  struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct spoolss_SetPrinter r;
+
+       r.in.handle             = handle;
+       r.in.level              = 0;
+       r.in.info.info1         = NULL;
+       r.in.devmode_ctr.devmode= NULL;
+       r.in.secdesc_ctr.sd     = NULL;
+       r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
+
+       printf("Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
+
+       status = dcerpc_spoolss_SetPrinter(p, mem_ctx, &r);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("SetPrinter failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+       if (!W_ERROR_IS_OK(r.out.result)) {
+               printf("SetPrinter failed - %s\n", win_errstr(r.out.result));
+               return False;
+       }
+
+       return True;
+}
+
+static BOOL test_ResumePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
+                  struct policy_handle *handle)
+{
+       NTSTATUS status;
+       struct spoolss_SetPrinter r;
+
+       r.in.handle             = handle;
+       r.in.level              = 0;
+       r.in.info.info1         = NULL;
+       r.in.devmode_ctr.devmode= NULL;
+       r.in.secdesc_ctr.sd     = NULL;
+       r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
+
+       printf("Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
+
+       status = dcerpc_spoolss_SetPrinter(p, mem_ctx, &r);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("SetPrinter failed - %s\n", nt_errstr(status));
+               return False;
+       }
+
+       if (!W_ERROR_IS_OK(r.out.result)) {
+               printf("SetPrinter failed - %s\n", win_errstr(r.out.result));
+               return False;
+       }
+
+       return True;
+}
+
 static BOOL test_GetPrinterData(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                                struct policy_handle *handle, 
                                const char *value_name)
 {
        NTSTATUS status;
        struct spoolss_GetPrinterData r;
-       uint32_t buf_size;
 
        r.in.handle = handle;
        r.in.value_name = value_name;
-       buf_size = 0;
-       r.in.buf_size = r.out.buf_size = &buf_size;
+       r.in.offered = 0;
 
        printf("Testing GetPrinterData\n");
 
        status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
-
        if (!NT_STATUS_IS_OK(status)) {
                printf("GetPrinterData failed - %s\n", nt_errstr(status));
                return False;
        }
 
        if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
+               r.in.offered = r.out.needed;
 
                status = dcerpc_spoolss_GetPrinterData(p, mem_ctx, &r);
-
                if (!NT_STATUS_IS_OK(status)) {
                        printf("GetPrinterData failed - %s\n", 
                               nt_errstr(status));
@@ -1172,13 +1451,11 @@ static BOOL test_GetPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 {
        NTSTATUS status;
        struct spoolss_GetPrinterDataEx r;
-       uint32_t buf_size;
 
        r.in.handle = handle;
        r.in.key_name = key_name;
        r.in.value_name = value_name;
-       buf_size = 0;
-       r.in.buf_size = r.out.buf_size = &buf_size;
+       r.in.offered = 0;
 
        printf("Testing GetPrinterDataEx\n");
 
@@ -1194,9 +1471,9 @@ static BOOL test_GetPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        }
 
        if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
+               r.in.offered = r.out.needed;
 
                status = dcerpc_spoolss_GetPrinterDataEx(p, mem_ctx, &r);
-
                if (!NT_STATUS_IS_OK(status)) {
                        printf("GetPrinterDataEx failed - %s\n", 
                               nt_errstr(status));
@@ -1269,18 +1546,17 @@ static BOOL test_EnumPrinterDataEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
        r.in.handle = handle;
        r.in.key_name = "PrinterDriverData";
-       r.in.buf_size = 0;
+       r.in.offered = 0;
 
        printf("Testing EnumPrinterDataEx\n");
 
        status = dcerpc_spoolss_EnumPrinterDataEx(p, mem_ctx, &r);
-
        if (!NT_STATUS_IS_OK(status)) {
                printf("EnumPrinterDataEx failed - %s\n", nt_errstr(status));
                return False;
        }
 
-       r.in.buf_size = r.out.buf_size;
+       r.in.offered = r.out.needed;
 
        status = dcerpc_spoolss_EnumPrinterDataEx(p, mem_ctx, &r);
 
@@ -1374,8 +1650,7 @@ static BOOL test_SecondaryClosePrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ct
                return False;
        }
 
-       status = dcerpc_bind_auth_none(p2, DCERPC_SPOOLSS_UUID, 
-                                      DCERPC_SPOOLSS_VERSION);
+       status = dcerpc_bind_auth_none(p2, &dcerpc_table_spoolss);
        if (!NT_STATUS_IS_OK(status)) {
                printf("Failed to create bind on secondary connection\n");
                talloc_free(p2);
@@ -1409,7 +1684,6 @@ static BOOL test_OpenPrinter_badname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
        op.in.printername       = name;
        op.in.datatype          = NULL;
-       op.in.devmode_ctr.size  = 0;
        op.in.devmode_ctr.devmode= NULL;
        op.in.access_mask       = 0;
        op.out.handle           = &handle;
@@ -1432,7 +1706,6 @@ static BOOL test_OpenPrinter_badname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
        opEx.in.printername             = name;
        opEx.in.datatype                = NULL;
-       opEx.in.devmode_ctr.size        = 0;
        opEx.in.devmode_ctr.devmode     = NULL;
        opEx.in.access_mask             = 0;
        opEx.in.level                   = 1;
@@ -1490,7 +1763,6 @@ static BOOL test_OpenPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 
        r.in.printername        = talloc_asprintf(mem_ctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
        r.in.datatype           = NULL;
-       r.in.devmode_ctr.size   = 0;
        r.in.devmode_ctr.devmode= NULL;
        r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
        r.out.handle            = &handle;
@@ -1540,7 +1812,6 @@ static BOOL call_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
        }
 
        r.in.datatype           = NULL;
-       r.in.devmode_ctr.size   = 0;
        r.in.devmode_ctr.devmode= NULL;
        r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
        r.in.level              = 1;
@@ -1586,11 +1857,11 @@ static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                ret = False;
        }
 
-       if (!test_EnumForms(p, mem_ctx, &handle)) {
+       if (!test_EnumForms(p, mem_ctx, &handle, False)) {
                ret = False;
        }
 
-       if (!test_AddForm(p, mem_ctx, &handle)) {
+       if (!test_AddForm(p, mem_ctx, &handle, False)) {
                ret = False;
        }
 
@@ -1602,7 +1873,15 @@ static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
                ret = False;
        }
 
-       if (!test_EnumJobs(p, mem_ctx, &handle)) {
+       if (!test_PausePrinter(p, mem_ctx, &handle)) {
+               ret = False;
+       }
+
+       if (!test_DoPrintTest(p, mem_ctx, &handle)) {
+               ret = False;
+       }
+
+       if (!test_ResumePrinter(p, mem_ctx, &handle)) {
                ret = False;
        }
 
@@ -1630,7 +1909,6 @@ static BOOL test_EnumPrinters_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        BOOL ret = True;
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               uint32_t buf_size = 0;
                union spoolss_PrinterInfo *info;
                int j;
 
@@ -1638,8 +1916,7 @@ static BOOL test_EnumPrinters_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
                r.in.server     = "";
                r.in.level      = levels[i];
                r.in.buffer     = NULL;
-               r.in.buf_size   = &buf_size;
-               r.out.buf_size  = &buf_size;
+               r.in.offered    = 0;
 
                printf("\nTesting EnumPrinters level %u\n", r.in.level);
 
@@ -1651,9 +1928,10 @@ static BOOL test_EnumPrinters_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
                }
 
                if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
-                       DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, buf_size);
+                       DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
                        data_blob_clear(&blob);
                        r.in.buffer = &blob;
+                       r.in.offered = r.out.needed;
                        status = dcerpc_spoolss_EnumPrinters(p, mem_ctx, &r);
                }
 
@@ -1670,7 +1948,7 @@ static BOOL test_EnumPrinters_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
                }
 
                if (!r.out.info) {
-                       printf("No printers returned");
+                       printf("No printers returned\n");
                        continue;
                }
 
@@ -1702,27 +1980,25 @@ static BOOL test_GetPrinterDriver2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
 {
        NTSTATUS status;
        struct spoolss_GetPrinterDriver2 r;
-       uint32_t buf_size;
 
        r.in.handle = handle;
        r.in.architecture = "W32X86";
        r.in.level = 1;
-       buf_size = 0;
        r.in.buffer = NULL;
-       r.in.buf_size = r.out.buf_size = &buf_size;
+       r.in.offered = 0;
        r.in.client_major_version = 0;
        r.in.client_minor_version = 0;
 
        printf("Testing GetPrinterDriver2\n");
 
        status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
-
        if (!NT_STATUS_IS_OK(status)) {
                printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
                return False;
        }
 
        if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
+               r.in.offered = r.out.needed;
                status = dcerpc_spoolss_GetPrinterDriver2(p, mem_ctx, &r);
        }
                
@@ -1751,15 +2027,12 @@ static BOOL test_EnumPrinterDrivers_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_c
        BOOL ret = True;
 
        for (i=0;i<ARRAY_SIZE(levels);i++) {
-               uint32_t buf_size;
 
                r.in.server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
                r.in.environment = "Windows NT x86";
                r.in.level = levels[i];
                r.in.buffer = NULL;
-               buf_size = 0;
-               r.in.buf_size = &buf_size;
-               r.out.buf_size = &buf_size;
+               r.in.offered = 0;
 
                printf("\nTesting EnumPrinterDrivers level %u\n", r.in.level);
 
@@ -1773,14 +2046,13 @@ static BOOL test_EnumPrinterDrivers_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_c
                }
 
                if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
-                       DATA_BLOB blob = data_blob_talloc(
-                               mem_ctx, NULL, buf_size);
-
+                       DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, r.out.needed);
                        data_blob_clear(&blob);
                        r.in.buffer = &blob;
+                       r.in.offered = r.out.needed;
                        status = dcerpc_spoolss_EnumPrinterDrivers(p, mem_ctx, &r);
                }
-               
+
                if (!NT_STATUS_IS_OK(status)) {
                        printf("EnumPrinterDrivers failed - %s\n", 
                               nt_errstr(status));
@@ -1796,7 +2068,7 @@ static BOOL test_EnumPrinterDrivers_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_c
                }
 
                if (!r.out.info) {
-                       printf("No printer drivers returned");
+                       printf("No printer drivers returned\n");
                        break;
                }
        }
@@ -1804,7 +2076,7 @@ static BOOL test_EnumPrinterDrivers_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_c
        return ret;
 }
 
-BOOL torture_rpc_spoolss(void)
+BOOL torture_rpc_spoolss(struct torture_context *torture)
 {
         NTSTATUS status;
         struct dcerpc_pipe *p;
@@ -1814,11 +2086,7 @@ BOOL torture_rpc_spoolss(void)
 
        mem_ctx = talloc_init("torture_rpc_spoolss");
 
-       status = torture_rpc_connection(mem_ctx, 
-                                       &p, 
-                                       DCERPC_SPOOLSS_NAME,
-                                       DCERPC_SPOOLSS_UUID,
-                                       DCERPC_SPOOLSS_VERSION);
+       status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_spoolss);
        if (!NT_STATUS_IS_OK(status)) {
                talloc_free(mem_ctx);
                return False;
@@ -1829,12 +2097,28 @@ BOOL torture_rpc_spoolss(void)
 
        ret &= test_OpenPrinter_server(ctx);
 
+       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "W3SvcInstalled");
+       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "BeepEnabled");
+       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "EventLog");
+       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "NetPopup");
+       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "NetPopupToComputer");
+       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "MajorVersion");
+       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "MinorVersion");
+       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "DefaultSpoolDirectory");
        ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "Architecture");
+       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "DsPresent");
+       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "OSVersion");
+       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "OSVersionEx");
+       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "DNSMachineName");
 
-       ret &= test_GetPrinterData(ctx->p, ctx, &ctx->server_handle, "DefaultSpoolDirectory");
+       ret &= test_EnumForms(ctx->p, ctx, &ctx->server_handle, True);
+
+       ret &= test_AddForm(ctx->p, ctx, &ctx->server_handle, True);
 
        ret &= test_EnumPorts(ctx);
 
+       ret &= test_GetPrinterDriverDirectory(ctx);
+
        ret &= test_EnumPrinterDrivers(ctx);
 
        ret &= test_EnumMonitors(ctx);