s3-rpc_cli: add winreg_get_core_driver()
authorGünther Deschner <gd@samba.org>
Mon, 31 Oct 2016 16:43:28 +0000 (17:43 +0100)
committerGünther Deschner <gd@samba.org>
Tue, 9 May 2017 14:43:13 +0000 (16:43 +0200)
Guenther

Signed-off-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
source3/rpc_client/cli_winreg_spoolss.c
source3/rpc_client/cli_winreg_spoolss.h

index 5ec97e6a94cace344486f07a59b990d8be4bdee2..1823168685d71b847e97d9b679bb80344445eab2 100644 (file)
@@ -34,6 +34,7 @@
 
 #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
 #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
+#define TOP_LEVEL_PRINT_PACKAGEINSTALLATION_KEY TOP_LEVEL_PRINT_KEY "\\PackageInstallation"
 #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
 #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
 
@@ -3968,3 +3969,165 @@ done:
        TALLOC_FREE(tmp_ctx);
        return result;
 }
+
+WERROR winreg_get_core_driver(TALLOC_CTX *mem_ctx,
+                             struct dcerpc_binding_handle *winreg_handle,
+                             const char *architecture,
+                             const struct GUID *core_driver_guid,
+                             struct spoolss_CorePrinterDriver **_core_printer_driver)
+{
+       uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+       struct policy_handle hive_hnd, key_hnd;
+       struct spoolss_CorePrinterDriver *c;
+       struct spoolss_PrinterEnumValues *enum_values = NULL;
+       struct spoolss_PrinterEnumValues *v;
+       uint32_t num_values = 0;
+       TALLOC_CTX *tmp_ctx;
+       WERROR result;
+       NTSTATUS status;
+       const char *path;
+       const char *guid_str;
+       uint32_t i;
+       const char **enum_names = NULL;
+       enum winreg_Type *enum_types = NULL;
+       DATA_BLOB *enum_data_blobs = NULL;
+
+       ZERO_STRUCT(hive_hnd);
+       ZERO_STRUCT(key_hnd);
+
+       tmp_ctx = talloc_stackframe();
+       if (tmp_ctx == NULL) {
+               return WERR_NOT_ENOUGH_MEMORY;
+       }
+
+       path = talloc_asprintf(tmp_ctx, "%s\\%s\\CorePrinterDrivers",
+                                       TOP_LEVEL_PRINT_PACKAGEINSTALLATION_KEY,
+                                       architecture);
+       if (path == NULL) {
+               result = WERR_NOT_ENOUGH_MEMORY;
+               goto done;
+       }
+
+       guid_str = GUID_string2(tmp_ctx, core_driver_guid);
+       if (guid_str == NULL) {
+               result = WERR_NOT_ENOUGH_MEMORY;
+               goto done;
+       }
+
+       result = winreg_printer_openkey(tmp_ctx,
+                                       winreg_handle,
+                                       path,
+                                       guid_str, /* key */
+                                       false,
+                                       access_mask,
+                                       &hive_hnd,
+                                       &key_hnd);
+
+       if (!W_ERROR_IS_OK(result)) {
+               DEBUG(5, ("winreg_get_core_driver: "
+                         "Could not open core driver key (%s,%s): %s\n",
+                         guid_str, architecture, win_errstr(result)));
+               goto done;
+       }
+
+       status = dcerpc_winreg_enumvals(tmp_ctx,
+                                       winreg_handle,
+                                       &key_hnd,
+                                       &num_values,
+                                       &enum_names,
+                                       &enum_types,
+                                       &enum_data_blobs,
+                                       &result);
+       if (!NT_STATUS_IS_OK(status)){
+               result = ntstatus_to_werror(status);
+       }
+
+       if (!W_ERROR_IS_OK(result)) {
+               DEBUG(0, ("winreg_get_core_driver: "
+                         "Could not enumerate values for (%s,%s): %s\n",
+                         guid_str, architecture, win_errstr(result)));
+               goto done;
+       }
+
+       enum_values = talloc_zero_array(tmp_ctx,
+                                       struct spoolss_PrinterEnumValues,
+                                       num_values);
+       if (enum_values == NULL){
+               result = WERR_NOT_ENOUGH_MEMORY;
+               goto done;
+       }
+
+       for (i = 0; i < num_values; i++){
+               enum_values[i].value_name = enum_names[i];
+               enum_values[i].value_name_len = strlen_m_term(enum_names[i]) * 2;
+               enum_values[i].type = enum_types[i];
+               enum_values[i].data_length = enum_data_blobs[i].length;
+               enum_values[i].data = NULL;
+               if (enum_values[i].data_length != 0){
+                       enum_values[i].data = &enum_data_blobs[i];
+               }
+       }
+
+       c = talloc_zero(tmp_ctx, struct spoolss_CorePrinterDriver);
+       if (c == NULL) {
+               result = WERR_NOT_ENOUGH_MEMORY;
+               goto done;
+       }
+
+       c->core_driver_guid = *core_driver_guid;
+
+       result = WERR_OK;
+
+       for (i = 0; i < num_values; i++) {
+               const char *tmp_str;
+
+               v = &enum_values[i];
+
+               result = winreg_enumval_to_sz(c, v,
+                                             "InfPath",
+                                             &c->szPackageID);
+               CHECK_ERROR(result);
+
+               result = winreg_enumval_to_sz(c, v,
+                                             "DriverDate",
+                                             &tmp_str);
+               if (W_ERROR_IS_OK(result)) {
+                       result = winreg_printer_date_to_NTTIME(tmp_str,
+                                               &c->driver_date);
+               }
+               CHECK_ERROR(result);
+
+               result = winreg_enumval_to_sz(c, v,
+                                             "DriverVersion",
+                                             &tmp_str);
+               if (W_ERROR_IS_OK(result)) {
+                       result = winreg_printer_ver_to_qword(tmp_str,
+                                               &c->driver_version);
+               }
+               CHECK_ERROR(result);
+       }
+
+       if (!W_ERROR_IS_OK(result)) {
+               DEBUG(0, ("winreg_enumval_to_TYPE() failed "
+                         "for %s: %s\n", v->value_name,
+                         win_errstr(result)));
+               goto done;
+       }
+
+       *_core_printer_driver = talloc_steal(mem_ctx, c);
+       result = WERR_OK;
+done:
+       if (winreg_handle != NULL) {
+               WERROR ignore;
+
+               if (is_valid_policy_hnd(&key_hnd)) {
+                       dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &key_hnd, &ignore);
+               }
+               if (is_valid_policy_hnd(&hive_hnd)) {
+                       dcerpc_winreg_CloseKey(winreg_handle, tmp_ctx, &hive_hnd, &ignore);
+               }
+       }
+
+       TALLOC_FREE(tmp_ctx);
+       return result;
+}
index 6542fc94f1c3e0ebac8f8098e10f570b4575ee72..90ff7315e82d148372d82ae0adc2002d52556e41 100644 (file)
@@ -599,5 +599,27 @@ WERROR winreg_get_driver_list(TALLOC_CTX *mem_ctx,
                              uint32_t version,
                              uint32_t *num_drivers,
                              const char ***drivers);
+/**
+ * @brief This function gets a core printer driver
+ *
+ * @param[in]  mem_ctx        A talloc memory context.
+ *
+ * @param[in]  b The dcerpc binding handle
+ *
+ * @param[in]  architecture    The architecture type.
+ *
+ * @param[in]  core_driver_guid The core driver guid.
+ *
+ * @param[out] core_printer_driver The returned core printer driver definiton
+ *
+ * @return              On success WERR_OK, a corresponding DOS error is
+ *                      something went wrong.
+ */
+
+WERROR winreg_get_core_driver(TALLOC_CTX *mem_ctx,
+                             struct dcerpc_binding_handle *winreg_handle,
+                             const char *architecture,
+                             const struct GUID *core_driver_guid,
+                             struct spoolss_CorePrinterDriver **_core_printer_driver);
 
 #endif /* _RPC_CLIENT_CLI_WINREG_SPOOLSS_H_ */