summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Disseldorp <ddiss@samba.org>2012-01-12 16:27:37 +0100
committerKarolin Seeger <kseeger@samba.org>2012-01-23 21:31:04 +0100
commite6ef4d2451f5c35992281772591b8c740392b5a7 (patch)
treeb6fc574d76c1540a4873566eae60a2b325800108
parentcdd7799ebfa96c16e96ca402eee20d7cd0beae01 (diff)
downloadsamba-e6ef4d2451f5c35992281772591b8c740392b5a7.tar.gz
s3-spoolss: fix printer driver version deletion
Spoolss delete printer driver code currently makes invalid version assumptions based on the architecture requested by the client. Ugly hacks are in place to cover removal of other versions (2 and 3). This change wraps multi version deletion in a simple for loop. (cherry picked from commit 54bc662adb24be9950c827446130b91504965c8c)
-rw-r--r--source3/rpc_server/spoolss/srv_spoolss_nt.c302
1 files changed, 128 insertions, 174 deletions
diff --git a/source3/rpc_server/spoolss/srv_spoolss_nt.c b/source3/rpc_server/spoolss/srv_spoolss_nt.c
index 2403f32d9db..8e4ddc0414f 100644
--- a/source3/rpc_server/spoolss/srv_spoolss_nt.c
+++ b/source3/rpc_server/spoolss/srv_spoolss_nt.c
@@ -2042,6 +2042,12 @@ static const struct print_architecture_table_node archi_table[]= {
{NULL, "", -1 }
};
+static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
+ SPOOLSS_DRIVER_VERSION_NT35,
+ SPOOLSS_DRIVER_VERSION_NT4,
+ SPOOLSS_DRIVER_VERSION_200X,
+ -1};
+
static int get_version_id(const char *arch)
{
int i;
@@ -2064,10 +2070,12 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
{
struct spoolss_DriverInfo8 *info = NULL;
- struct spoolss_DriverInfo8 *info_win2k = NULL;
int version;
WERROR status;
struct dcerpc_binding_handle *b;
+ TALLOC_CTX *tmp_ctx = NULL;
+ int i;
+ bool found;
/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
and not a printer admin, then fail */
@@ -2089,73 +2097,112 @@ WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
if ((version = get_version_id(r->in.architecture)) == -1)
return WERR_INVALID_ENVIRONMENT;
- status = winreg_printer_binding_handle(p->mem_ctx,
+ tmp_ctx = talloc_new(p->mem_ctx);
+ if (!tmp_ctx) {
+ return WERR_NOMEM;
+ }
+
+ status = winreg_printer_binding_handle(tmp_ctx,
get_session_info_system(),
p->msg_ctx,
&b);
if (!W_ERROR_IS_OK(status)) {
- return status;
+ goto done;
}
- status = winreg_get_driver(p->mem_ctx, b,
- r->in.architecture, r->in.driver,
- version, &info);
- if (!W_ERROR_IS_OK(status)) {
- /* try for Win2k driver if "Windows NT x86" */
-
- if ( version == 2 ) {
- version = 3;
-
- status = winreg_get_driver(p->mem_ctx, b,
- r->in.architecture,
- r->in.driver,
- version, &info);
- if (!W_ERROR_IS_OK(status)) {
- status = WERR_UNKNOWN_PRINTER_DRIVER;
- goto done;
- }
+ for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
+ status = winreg_get_driver(tmp_ctx, b,
+ r->in.architecture, r->in.driver,
+ drv_cversion[i], &info);
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(5, ("skipping del of driver with version %d\n",
+ drv_cversion[i]));
+ continue;
}
- /* otherwise it was a failure */
- else {
- status = WERR_UNKNOWN_PRINTER_DRIVER;
+ found = true;
+
+ if (printer_driver_in_use(tmp_ctx, get_session_info_system(),
+ p->msg_ctx, info)) {
+ status = WERR_PRINTER_DRIVER_IN_USE;
goto done;
}
+ status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0, ("failed del of driver with version %d\n",
+ drv_cversion[i]));
+ goto done;
+ }
}
+ if (found == false) {
+ DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
+ status = WERR_UNKNOWN_PRINTER_DRIVER;
+ } else {
+ status = WERR_OK;
+ }
+
+done:
+ talloc_free(tmp_ctx);
+ return status;
+}
- if (printer_driver_in_use(p->mem_ctx,
- get_session_info_system(),
- p->msg_ctx,
- info)) {
+static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
+ struct pipes_struct *p,
+ struct spoolss_DeletePrinterDriverEx *r,
+ struct dcerpc_binding_handle *b,
+ struct spoolss_DriverInfo8 *info)
+{
+ WERROR status;
+ bool delete_files;
+
+ if (printer_driver_in_use(mem_ctx, get_session_info_system(),
+ p->msg_ctx, info)) {
status = WERR_PRINTER_DRIVER_IN_USE;
goto done;
}
- if (version == 2) {
- status = winreg_get_driver(p->mem_ctx, b,
- r->in.architecture,
- r->in.driver, 3, &info_win2k);
- if (W_ERROR_IS_OK(status)) {
- /* if we get to here, we now have 2 driver info structures to remove */
- /* remove the Win2k driver first*/
+ /*
+ * we have a couple of cases to consider.
+ * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
+ * then the delete should fail if **any** files overlap with
+ * other drivers
+ * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
+ * non-overlapping files
+ * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
+ * is set, then do not delete any files
+ * Refer to MSDN docs on DeletePrinterDriverEx() for details.
+ */
- status = winreg_del_driver(p->mem_ctx, b,
- info_win2k, 3);
- talloc_free(info_win2k);
+ delete_files = r->in.delete_flags
+ & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
- /* this should not have failed---if it did, report to client */
- if (!W_ERROR_IS_OK(status)) {
- goto done;
- }
- }
+ /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
+
+ if (delete_files &&
+ (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
+ printer_driver_files_in_use(mem_ctx,
+ get_session_info_system(),
+ b,
+ info)) {
+ status = WERR_PRINTER_DRIVER_IN_USE;
+ goto done;
}
- status = winreg_del_driver(p->mem_ctx, b,
- info, version);
+ status = winreg_del_driver(mem_ctx, b, info, info->version);
+ if (!W_ERROR_IS_OK(status)) {
+ goto done;
+ }
-done:
- talloc_free(info);
+ /*
+ * now delete any associated files if delete_files is
+ * true. Even if this part failes, we return succes
+ * because the driver doesn not exist any more
+ */
+ if (delete_files) {
+ delete_driver_files(get_session_info_system(), info);
+ }
+done:
return status;
}
@@ -2166,12 +2213,12 @@ done:
WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
struct spoolss_DeletePrinterDriverEx *r)
{
- struct spoolss_DriverInfo8 *info = NULL;
- struct spoolss_DriverInfo8 *info_win2k = NULL;
- int version;
- bool delete_files;
+ struct spoolss_DriverInfo8 *info = NULL;
WERROR status;
struct dcerpc_binding_handle *b;
+ TALLOC_CTX *tmp_ctx = NULL;
+ int i;
+ bool found;
/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
and not a printer admin, then fail */
@@ -2188,150 +2235,57 @@ WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
}
/* check that we have a valid driver name first */
- if ((version = get_version_id(r->in.architecture)) == -1) {
+ if (get_version_id(r->in.architecture) == -1) {
/* this is what NT returns */
return WERR_INVALID_ENVIRONMENT;
}
- if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
- version = r->in.version;
+ tmp_ctx = talloc_new(p->mem_ctx);
+ if (!tmp_ctx) {
+ return WERR_NOMEM;
+ }
- status = winreg_printer_binding_handle(p->mem_ctx,
+ status = winreg_printer_binding_handle(tmp_ctx,
get_session_info_system(),
p->msg_ctx,
&b);
if (!W_ERROR_IS_OK(status)) {
- return status;
+ goto done;
}
- status = winreg_get_driver(p->mem_ctx, b,
- r->in.architecture,
- r->in.driver,
- version,
- &info);
- if (!W_ERROR_IS_OK(status)) {
- status = WERR_UNKNOWN_PRINTER_DRIVER;
-
- /*
- * if the client asked for a specific version,
- * or this is something other than Windows NT x86,
- * then we've failed
- */
-
- if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
- goto done;
-
- /* try for Win2k driver if "Windows NT x86" */
+ for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
+ if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
+ && (drv_cversion[i] != r->in.version)) {
+ continue;
+ }
- version = 3;
- status = winreg_get_driver(info, b,
- r->in.architecture,
- r->in.driver,
- version, &info);
+ /* check if a driver with this version exists before delete */
+ status = winreg_get_driver(tmp_ctx, b,
+ r->in.architecture, r->in.driver,
+ drv_cversion[i], &info);
if (!W_ERROR_IS_OK(status)) {
- status = WERR_UNKNOWN_PRINTER_DRIVER;
- goto done;
+ DEBUG(5, ("skipping del of driver with version %d\n",
+ drv_cversion[i]));
+ continue;
}
- }
-
- if (printer_driver_in_use(info,
- get_session_info_system(),
- p->msg_ctx,
- info)) {
- status = WERR_PRINTER_DRIVER_IN_USE;
- goto done;
- }
-
- /*
- * we have a couple of cases to consider.
- * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
- * then the delete should fail if **any** files overlap with
- * other drivers
- * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
- * non-overlapping files
- * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
- * is set, the do not delete any files
- * Refer to MSDN docs on DeletePrinterDriverEx() for details.
- */
-
- delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
-
- /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
-
- if (delete_files &&
- (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
- printer_driver_files_in_use(info,
- get_session_info_system(),
- p->msg_ctx,
- info)) {
- status = WERR_PRINTER_DRIVER_IN_USE;
- goto done;
- }
-
-
- /* also check for W32X86/3 if necessary; maybe we already have? */
-
- if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
- status = winreg_get_driver(info, b,
- r->in.architecture,
- r->in.driver, 3, &info_win2k);
- if (W_ERROR_IS_OK(status)) {
-
- if (delete_files &&
- (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
- printer_driver_files_in_use(info,
- get_session_info_system(),
- p->msg_ctx,
- info_win2k)) {
- /* no idea of the correct error here */
- talloc_free(info_win2k);
- status = WERR_ACCESS_DENIED;
- goto done;
- }
-
- /* if we get to here, we now have 2 driver info structures to remove */
- /* remove the Win2k driver first*/
-
- status = winreg_del_driver(info, b,
- info_win2k,
- 3);
-
- /* this should not have failed---if it did, report to client */
-
- if (!W_ERROR_IS_OK(status)) {
- goto done;
- }
+ found = true;
- /*
- * now delete any associated files if delete_files is
- * true. Even if this part failes, we return succes
- * because the driver doesn not exist any more
- */
- if (delete_files) {
- delete_driver_files(get_session_info_system(),
- info_win2k);
- }
+ status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0, ("failed to delete driver with version %d\n",
+ drv_cversion[i]));
+ goto done;
}
}
-
- status = winreg_del_driver(info, b,
- info,
- version);
- if (!W_ERROR_IS_OK(status)) {
- goto done;
- }
-
- /*
- * now delete any associated files if delete_files is
- * true. Even if this part failes, we return succes
- * because the driver doesn not exist any more
- */
- if (delete_files) {
- delete_driver_files(get_session_info_system(), info);
+ if (found == false) {
+ DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
+ status = WERR_UNKNOWN_PRINTER_DRIVER;
+ } else {
+ status = WERR_OK;
}
done:
- talloc_free(info);
+ talloc_free(tmp_ctx);
return status;
}