summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/libsmb/cli_spoolss.c166
-rw-r--r--source3/rpc_parse/parse_spoolss.c38
-rw-r--r--source3/rpcclient/cmd_spoolss.c163
3 files changed, 346 insertions, 21 deletions
diff --git a/source3/libsmb/cli_spoolss.c b/source3/libsmb/cli_spoolss.c
index c11debba33..3aaff10b49 100644
--- a/source3/libsmb/cli_spoolss.c
+++ b/source3/libsmb/cli_spoolss.c
@@ -1210,7 +1210,7 @@ WERROR cli_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
return result;
}
-/** Set a form on a printer - this doesn't seem to work very well.
+/** Set a form on a printer.
*
* @param cli Pointer to client state structure which is open
* on the SPOOLSS pipe.
@@ -1224,7 +1224,8 @@ WERROR cli_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
*/
WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
- POLICY_HND *handle, uint32 level, FORM *form)
+ POLICY_HND *handle, uint32 level, char *form_name,
+ FORM *form)
{
prs_struct qbuf, rbuf;
SPOOL_Q_SETFORM q;
@@ -1241,7 +1242,7 @@ WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/* Initialise input parameters */
- make_spoolss_q_setform(&q, handle, level, form);
+ make_spoolss_q_setform(&q, handle, level, form_name, form);
/* Marshall data and send request */
@@ -1258,6 +1259,77 @@ WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
result = r.status;
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+/** Get a form on a printer.
+ *
+ * @param cli Pointer to client state structure which is open
+ * on the SPOOLSS pipe.
+ * @param mem_ctx Pointer to an initialised talloc context.
+ *
+ * @param handle Policy handle opened with cli_spoolss_open_printer_ex
+ * or cli_spoolss_addprinterex.
+ * @param formname Name of the form to get
+ * @param level Form info level to get - should always be 1.
+ *
+ */
+
+WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 offered, uint32 *needed,
+ POLICY_HND *handle, char *formname, uint32 level,
+ FORM_1 *form)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_GETFORM q;
+ SPOOL_R_GETFORM r;
+ WERROR result = W_ERROR(ERRgeneral);
+ NEW_BUFFER buffer;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ init_buffer(&buffer, offered, mem_ctx);
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_getform(&q, handle, formname, level, &buffer, offered);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_getform("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_GETFORM, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_getform("", &r, &rbuf, 0))
+ goto done;
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ if (needed)
+ *needed = r.needed;
+
+ if (W_ERROR_IS_OK(result))
+ smb_io_form_1("", r.buffer, form, 0);
+
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
@@ -1265,7 +1337,7 @@ WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
return result;
}
-/** Delete a form on a printer - this doesn't seem to work very well.
+/** Delete a form on a printer.
*
* @param cli Pointer to client state structure which is open
* on the SPOOLSS pipe.
@@ -1278,7 +1350,7 @@ WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
*/
WERROR cli_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
- POLICY_HND *handle, char *form)
+ POLICY_HND *handle, char *form_name)
{
prs_struct qbuf, rbuf;
SPOOL_Q_DELETEFORM q;
@@ -1295,7 +1367,7 @@ WERROR cli_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/* Initialise input parameters */
- make_spoolss_q_deleteform(&q, handle, form);
+ make_spoolss_q_deleteform(&q, handle, form_name);
/* Marshall data and send request */
@@ -1319,4 +1391,86 @@ WERROR cli_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
return result;
}
+static void decode_forms_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer,
+ uint32 num_forms, FORM_1 **forms)
+{
+ int i;
+
+ *forms = (FORM_1 *)talloc(mem_ctx, num_forms * sizeof(FORM_1));
+ buffer->prs.data_offset = 0;
+
+ for (i = 0; i < num_forms; i++)
+ smb_io_form_1("", buffer, &((*forms)[i]), 0);
+}
+
+/** Enumerate forms
+ *
+ * @param cli Pointer to client state structure which is open
+ * on the SPOOLSS pipe.
+ * @param mem_ctx Pointer to an initialised talloc context.
+ *
+ * @param offered Buffer size offered in the request.
+ * @param needed Number of bytes needed to complete the request.
+ * may be NULL.
+ * or cli_spoolss_addprinterex.
+ * @param level Form info level to get - should always be 1.
+ * @param handle Open policy handle
+ *
+ */
+
+WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 offered, uint32 *needed,
+ POLICY_HND *handle, int level, uint32 *num_forms,
+ FORM_1 **forms)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_ENUMFORMS q;
+ SPOOL_R_ENUMFORMS r;
+ WERROR result = W_ERROR(ERRgeneral);
+ NEW_BUFFER buffer;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ init_buffer(&buffer, offered, mem_ctx);
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_enumforms(&q, handle, level, &buffer, offered);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_enumforms("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_ENUMFORMS, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_enumforms("", &r, &rbuf, 0))
+ goto done;
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ if (needed)
+ *needed = r.needed;
+
+ if (num_forms)
+ *num_forms = r.numofforms;
+
+ decode_forms_1(mem_ctx, r.buffer, *num_forms, forms);
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
/** @} **/
diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c
index 2ed436fd85..b929369ec9 100644
--- a/source3/rpc_parse/parse_spoolss.c
+++ b/source3/rpc_parse/parse_spoolss.c
@@ -5877,7 +5877,7 @@ BOOL spoolss_io_r_addform(char *desc, SPOOL_R_ADDFORM *r_u, prs_struct *ps, int
BOOL spoolss_io_q_setform(char *desc, SPOOL_Q_SETFORM *q_u, prs_struct *ps, int depth)
{
- uint32 useless_ptr=0;
+ uint32 useless_ptr=1;
prs_debug(ps, depth, desc, "spoolss_io_q_setform");
depth++;
@@ -6695,12 +6695,13 @@ BOOL make_spoolss_q_addform(SPOOL_Q_ADDFORM *q_u, POLICY_HND *handle,
********************************************************************/
BOOL make_spoolss_q_setform(SPOOL_Q_SETFORM *q_u, POLICY_HND *handle,
- int level, FORM *form)
+ int level, char *form_name, FORM *form)
{
memcpy(&q_u->handle, handle, sizeof(POLICY_HND));
q_u->level = level;
q_u->level2 = level;
memcpy(&q_u->form, form, sizeof(FORM));
+ init_unistr2(&q_u->name, form_name, strlen(form_name) + 1);
return True;
}
@@ -6715,3 +6716,36 @@ BOOL make_spoolss_q_deleteform(SPOOL_Q_DELETEFORM *q_u, POLICY_HND *handle, char
init_unistr2(&q_u->name, form, strlen(form) + 1);
return True;
}
+
+/*******************************************************************
+ * init a structure.
+ ********************************************************************/
+
+BOOL make_spoolss_q_getform(SPOOL_Q_GETFORM *q_u, POLICY_HND *handle,
+ char *formname, uint32 level, NEW_BUFFER *buffer,
+ uint32 offered)
+{
+ memcpy(&q_u->handle, handle, sizeof(POLICY_HND));
+ q_u->level = level;
+ init_unistr2(&q_u->formname, formname, strlen(formname) + 1);
+ q_u->buffer=buffer;
+ q_u->offered=offered;
+
+ return True;
+}
+
+/*******************************************************************
+ * init a structure.
+ ********************************************************************/
+
+BOOL make_spoolss_q_enumforms(SPOOL_Q_ENUMFORMS *q_u, POLICY_HND *handle,
+ uint32 level, NEW_BUFFER *buffer,
+ uint32 offered)
+{
+ memcpy(&q_u->handle, handle, sizeof(POLICY_HND));
+ q_u->level = level;
+ q_u->buffer=buffer;
+ q_u->offered=offered;
+
+ return True;
+}
diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c
index 75c0cc0245..8d16ccdf54 100644
--- a/source3/rpcclient/cmd_spoolss.c
+++ b/source3/rpcclient/cmd_spoolss.c
@@ -1268,6 +1268,7 @@ static NTSTATUS cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/* Add the form */
+
werror = cli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
done:
@@ -1304,9 +1305,9 @@ static NTSTATUS cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
strupper(servername);
asprintf(&printername, "%s\\%s", servername, argv[1]);
- werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
- MAXIMUM_ALLOWED_ACCESS,
- servername, cli->user_name, &handle);
+ werror = cli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->user_name, &handle);
if (!W_ERROR_IS_OK(werror))
goto done;
@@ -1318,15 +1319,15 @@ static NTSTATUS cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
form.flags = FORM_PRINTER;
form.size_x = form.size_y = 100;
form.left = 0;
- form.top = 10;
- form.right = 20;
- form.bottom = 30;
+ form.top = 1000;
+ form.right = 2000;
+ form.bottom = 3000;
init_unistr2(&form.name, argv[2], strlen(argv[2]) + 1);
/* Set the form */
- werror = cli_spoolss_setform(cli, mem_ctx, &handle, 1, &form);
+ werror = cli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
done:
if (got_handle)
@@ -1338,15 +1339,17 @@ static NTSTATUS cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
return W_ERROR_IS_OK(werror) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
-/* Set a form */
+/* Get a form */
-static NTSTATUS cmd_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
- int argc, char **argv)
+static NTSTATUS cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, char **argv)
{
POLICY_HND handle;
WERROR werror;
char *servername = NULL, *printername = NULL;
+ FORM_1 form;
BOOL got_handle = False;
+ uint32 needed;
/* Parse the command arguements */
@@ -1361,9 +1364,71 @@ static NTSTATUS cmd_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ct
strupper(servername);
asprintf(&printername, "%s\\%s", servername, argv[1]);
- werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
- MAXIMUM_ALLOWED_ACCESS,
- servername, cli->user_name, &handle);
+ werror = cli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->user_name, &handle);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ got_handle = True;
+
+ /* Set the form */
+
+ werror = cli_spoolss_getform(cli, mem_ctx, 0, &needed,
+ &handle, argv[2], 1, &form);
+
+ if (W_ERROR_V(werror) == ERRinsufficientbuffer)
+ werror = cli_spoolss_getform(cli, mem_ctx, needed, NULL,
+ &handle, argv[2], 1, &form);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ printf("width: %d\n", form.width);
+ printf("length: %d\n", form.length);
+ printf("left: %d\n", form.left);
+ printf("top: %d\n", form.top);
+ printf("right: %d\n", form.right);
+ printf("bottom: %d\n", form.bottom);
+
+ done:
+ if (got_handle)
+ cli_spoolss_close_printer(cli, mem_ctx, &handle);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(printername);
+
+ return W_ERROR_IS_OK(werror) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+/* Delete a form */
+
+static NTSTATUS cmd_spoolss_deleteform(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ char **argv)
+{
+ POLICY_HND handle;
+ WERROR werror;
+ char *servername = NULL, *printername = NULL;
+ BOOL got_handle = False;
+
+ /* Parse the command arguements */
+
+ if (argc != 3) {
+ printf ("Usage: %s <printer> <formname>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Get a printer handle */
+
+ asprintf(&servername, "\\\\%s", cli->desthost);
+ strupper(servername);
+ asprintf(&printername, "%s\\%s", servername, argv[1]);
+
+ werror = cli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->user_name, &handle);
if (!W_ERROR_IS_OK(werror))
goto done;
@@ -1384,6 +1449,76 @@ static NTSTATUS cmd_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ct
return W_ERROR_IS_OK(werror) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
+/* Enumerate forms */
+
+static NTSTATUS cmd_spoolss_enumforms(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ char **argv)
+{
+ POLICY_HND handle;
+ WERROR werror;
+ char *servername = NULL, *printername = NULL;
+ BOOL got_handle = False;
+ uint32 needed, num_forms, level = 1, i;
+ FORM_1 *forms;
+
+ /* Parse the command arguements */
+
+ if (argc != 2) {
+ printf ("Usage: %s <printer>\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ /* Get a printer handle */
+
+ asprintf(&servername, "\\\\%s", cli->desthost);
+ strupper(servername);
+ asprintf(&printername, "%s\\%s", servername, argv[1]);
+
+ werror = cli_spoolss_open_printer_ex(
+ cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS,
+ servername, cli->user_name, &handle);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ got_handle = True;
+
+ /* Enumerate forms */
+
+ werror = cli_spoolss_enumforms(
+ cli, mem_ctx, 0, &needed, &handle, level, &num_forms, &forms);
+
+ if (W_ERROR_V(werror) == ERRinsufficientbuffer)
+ werror = cli_spoolss_enumforms(
+ cli, mem_ctx, needed, NULL, &handle, level,
+ &num_forms, &forms);
+
+ if (!W_ERROR_IS_OK(werror))
+ goto done;
+
+ /* Display output */
+
+ for (i = 0; i < num_forms; i++) {
+ fstring form_name;
+
+ if (forms[i].name.buffer)
+ rpcstr_pull(form_name, forms[i].name.buffer,
+ sizeof(form_name), 0, STR_TERMINATE);
+
+ printf("%s\n", form_name);
+ }
+
+ done:
+ if (got_handle)
+ cli_spoolss_close_printer(cli, mem_ctx, &handle);
+
+ SAFE_FREE(servername);
+ SAFE_FREE(printername);
+
+ return W_ERROR_IS_OK(werror) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
/* List of commands exported by this module */
struct cmd_set spoolss_commands[] = {
@@ -1406,7 +1541,9 @@ struct cmd_set spoolss_commands[] = {
{ "getprintprocdir", cmd_spoolss_getprintprocdir, PIPE_SPOOLSS, "Get print processor directory", "" },
{ "addform", cmd_spoolss_addform, PIPE_SPOOLSS, "Add form", "" },
{ "setform", cmd_spoolss_setform, PIPE_SPOOLSS, "Set form", "" },
+ { "getform", cmd_spoolss_getform, PIPE_SPOOLSS, "Get form", "" },
{ "deleteform", cmd_spoolss_deleteform, PIPE_SPOOLSS, "Delete form", "" },
+ { "enumforms", cmd_spoolss_enumforms, PIPE_SPOOLSS, "Enumerate forms", "" },
{ NULL }
};