2 Unix SMB/CIFS implementation.
4 Copyright (C) Guenther Deschner 2016
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "librpc/gen_ndr/ndr_spoolss.h"
22 #include "rpc_client/init_spoolss.h"
23 #include "libgpo/gpo_ini.h"
24 #include "printer_driver.h"
26 #define ADD_TO_ARRAY(mem_ctx, type, elem, array, num) \
28 *(array) = talloc_realloc(mem_ctx, (*(array)), type, (*(num))+1); \
29 SMB_ASSERT((*(array)) != NULL); \
30 (*(array))[*(num)] = (elem); \
35 /* GetPrinterDriverDirectory -> drivers and dependent files */
36 #define PRINTER_INF_DIRID_66000
38 /* GetPrintProcessorDirectory -> print processors */
39 #define PRINTER_INF_DIRID_66001
41 /* GetColorDirectory -> color profiles */
42 #define PRINTER_INF_DIRID_66003
44 static const char *get_string_unquote(const char *s)
58 if (s[0] == '"' && s[len-1] == '"') {
59 ok = trim_string(discard_const(s), "\"", "\"");
69 * '%STRING%' indicates STRING is localized in the [Strings] section
72 static const char *get_string_token(struct gp_inifile_context *ctx,
80 if (s != NULL && s[0] != '%' && s[strlen(s)-1] != '%') {
84 ok = trim_string(discard_const(s), "%", "%");
89 key = talloc_asprintf(ctx, "Strings:%s", s);
94 status = gp_inifile_getstring(ctx, key, &s2);
96 if (!NT_STATUS_IS_OK(status)) {
97 /* what can you do... */
104 static NTSTATUS gp_inifile_getstring_ext(struct gp_inifile_context *ctx,
111 status = gp_inifile_getstring(ctx, key, &s);
112 if (!NT_STATUS_IS_OK(status)) {
116 s = get_string_unquote(s);
118 return NT_STATUS_INTERNAL_ERROR;
121 if (s[0] == '%' && s[strlen(s)-1] == '%') {
122 s = get_string_token(ctx, s);
125 s = get_string_unquote(s);
127 return NT_STATUS_INTERNAL_ERROR;
135 static NTSTATUS find_manufacturer_name(struct gp_inifile_context *ctx,
137 const char *section_name,
138 const char **manufacturer_name)
142 const char **keys = NULL;
143 const char **values = NULL;
147 status = gp_inifile_enum_section(ctx, section_name, &num_keys, &keys, &values);
148 if (!NT_STATUS_IS_OK(status)) {
153 return NT_STATUS_INVALID_PARAMETER;
156 s = talloc_strdup(mem_ctx, keys[0]);
158 return NT_STATUS_NO_MEMORY;
163 return NT_STATUS_NO_MEMORY;
168 s = get_string_unquote(p);
170 return NT_STATUS_INTERNAL_ERROR;
173 s = get_string_token(ctx, s);
175 s = get_string_unquote(s);
177 return NT_STATUS_INTERNAL_ERROR;
181 *manufacturer_name = talloc_strdup(mem_ctx, s);
182 if (*manufacturer_name == NULL) {
183 return NT_STATUS_NO_MEMORY;
193 static NTSTATUS find_manufacturer_url(struct gp_inifile_context *ctx,
195 const char *section_name,
196 const char *manufacturer_name,
197 const char **manufacturer_url)
201 const char **keys = NULL;
202 const char **values = NULL;
206 status = gp_inifile_enum_section(ctx, section_name, &num_keys, &keys, &values);
208 if (!NT_STATUS_IS_OK(status)) {
213 return NT_STATUS_INVALID_PARAMETER;
216 p = strchr(keys[0], ':');
218 return NT_STATUS_NO_MEMORY;
223 s = get_string_unquote(p);
225 return NT_STATUS_INTERNAL_ERROR;
228 s = get_string_token(ctx, s);
230 s = get_string_unquote(s);
232 return NT_STATUS_INTERNAL_ERROR;
235 if (strequal(s, manufacturer_name)) {
236 s = get_string_unquote(values[0]);
238 return NT_STATUS_INTERNAL_ERROR;
243 *manufacturer_url = talloc_strdup(mem_ctx, s);
244 if (*manufacturer_url == NULL) {
245 return NT_STATUS_NO_MEMORY;
255 static NTSTATUS add_string_to_spoolss_array(TALLOC_CTX *mem_ctx,
257 struct spoolss_StringArray **r)
260 struct spoolss_StringArray *a = *r;
265 a = talloc_zero(mem_ctx, struct spoolss_StringArray);
267 return NT_STATUS_NO_MEMORY;
271 if (a->string == NULL) {
272 a->string = talloc_zero_array(a, const char *, count);
273 if (a->string == NULL) {
274 return NT_STATUS_NO_MEMORY;
278 for (i = 0; a->string[i] != NULL; i++) { ;; }
281 ok = add_string_to_array(mem_ctx, s, &a->string, &count);
283 return NT_STATUS_NO_MEMORY;
286 a->string = talloc_realloc(mem_ctx, a->string, const char *, count + 1);
287 if (a->string == NULL) {
288 return NT_STATUS_NO_MEMORY;
290 a->string[count] = NULL;
297 static NTSTATUS add_dependent_driver_file(TALLOC_CTX *mem_ctx,
299 struct spoolss_StringArray **r)
304 return NT_STATUS_INVALID_PARAMETER;
307 if (file[0] == '@') {
311 p = strchr(file, ',');
316 return add_string_to_spoolss_array(mem_ctx, file, r);
320 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-manufacturer-section
323 * "Kyocera"=Kyocera,NTx86.5.1,NTx86.6.0,NTamd64.5.1,NTamd64.6.0
326 static NTSTATUS enum_devices_in_toc(struct gp_inifile_context *ctx,
328 size_t *pnum_devices,
329 const char ***pdevices,
330 const char ***pdevice_values)
333 size_t num_manufacturers = 0;
334 const char **manufacturers = NULL;
335 const char **values = NULL;
340 status = gp_inifile_enum_section(ctx, "Manufacturer", &num_manufacturers, &manufacturers, &values);
341 if (!NT_STATUS_IS_OK(status)) {
345 for (i = 0; i < num_manufacturers; i++) {
347 const char *models_section_name;
352 DEBUG(11,("processing manufacturer: %s\n", manufacturers[i]));
354 status = gp_inifile_getstring(ctx, manufacturers[i], &s);
355 if (!NT_STATUS_IS_OK(status)) {
359 decorations = str_list_make_v3(mem_ctx, s, ",");
360 if (decorations == NULL) {
361 return NT_STATUS_NO_MEMORY;
364 models_section_name = decorations[0];
366 for (j = 1; decorations[j] != NULL; j++) {
369 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-models-section
372 const char *decorated_models_section_name;
373 size_t num_devices = 0;
374 const char **devices = NULL;
375 const char **device_values = NULL;
379 decorated_models_section_name = talloc_asprintf(mem_ctx, "%s.%s",
382 if (decorated_models_section_name == NULL) {
383 return NT_STATUS_NO_MEMORY;
386 DEBUG(11,("processing decorated models_section_name: %s\n",
387 decorated_models_section_name));
389 status = gp_inifile_enum_section(ctx, decorated_models_section_name,
390 &num_devices, &devices,
392 for (d = 0; d < num_devices; d++) {
394 DEBUG(11,("processing device: %s\n",
397 s = talloc_strdup(mem_ctx, devices[d]);
399 return NT_STATUS_NO_MEMORY;
404 return NT_STATUS_DRIVER_INTERNAL_ERROR;
410 s = get_string_unquote(p);
412 ok = add_string_to_array(mem_ctx, s, pdevices, pnum_devices);
414 return NT_STATUS_NO_MEMORY;
416 ok = add_string_to_array(mem_ctx, device_values[d], pdevice_values, &c);
418 return NT_STATUS_NO_MEMORY;
427 static NTSTATUS find_device_in_toc(struct gp_inifile_context *ctx,
429 const char *device_description,
433 size_t num_devices = 0;
434 const char **devices = NULL;
435 const char **device_values = NULL;
438 if (device_description == NULL) {
439 return NT_STATUS_INVALID_PARAMETER;
442 status = enum_devices_in_toc(ctx, mem_ctx,
446 if (!NT_STATUS_IS_OK(status)) {
450 for (d = 0; d < num_devices; d++) {
452 if (strequal(device_description, devices[d])) {
454 DEBUG(10,("found device_description: %s\n",
455 device_description));
457 *value = talloc_strdup(mem_ctx, device_values[d]);
458 if (*value == NULL) {
459 return NT_STATUS_NO_MEMORY;
461 DEBUGADD(10,("and returned: %s\n", *value));
467 return NT_STATUS_DRIVER_INTERNAL_ERROR;
471 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-copyfiles-directive
474 static NTSTATUS process_driver_section_copyfiles(struct gp_inifile_context *ctx,
476 const char *driver_section,
477 struct spoolss_AddDriverInfo8 *r)
482 const char **keys = NULL;
483 const char **values = NULL;
488 key = talloc_asprintf(mem_ctx, "%s:%s", driver_section, "CopyFiles");
490 return NT_STATUS_NO_MEMORY;
493 DEBUG(10,("Checking for CopyFiles entry in %s\n", driver_section));
495 status = gp_inifile_getstring(ctx, key, &s);
496 if (!NT_STATUS_IS_OK(status)) {
500 DEBUG(10,("these are the files to copy: %s\n", s));
502 while (next_token_talloc(mem_ctx, &s, &str, ",")) {
504 DEBUG(10,("trying section: %s\n", str));
507 DEBUG(10,("adding dependent driver file: %s\n", str));
508 status = add_dependent_driver_file(mem_ctx, str, &r->dependent_files);
509 if (!NT_STATUS_IS_OK(status)) {
515 status = gp_inifile_enum_section(ctx, str, &num_keys, &keys, &values);
516 if (NT_STATUS_IS_OK(status)) {
517 for (i = 0; i < num_keys; i++) {
518 p = strchr(keys[i], ':');
520 return NT_STATUS_INVALID_PARAMETER;
525 DEBUG(10,("adding dependent driver file: %s\n", p));
527 status = add_dependent_driver_file(mem_ctx, p, &r->dependent_files);
528 if (!NT_STATUS_IS_OK(status)) {
540 #define process_driver_section_val(_ctx, _mem_ctx, _section, _r, _key, _element) \
543 const char *__key, *_s; \
544 __key = talloc_asprintf(_mem_ctx, "%s:%s", _section, _key); \
545 NT_STATUS_HAVE_NO_MEMORY(__key); \
546 _status = gp_inifile_getstring(_ctx, __key, &_s); \
547 if (NT_STATUS_IS_OK(_status)) { \
548 (_r)->_element = talloc_strdup(mem_ctx, _s); \
549 NT_STATUS_HAVE_NO_MEMORY((_r)->_element); \
553 static NTSTATUS process_driver_section_colorprofiles(struct gp_inifile_context *ctx,
556 struct spoolss_AddDriverInfo8 *r)
561 key = talloc_asprintf(mem_ctx, "%s:%s", section, "ColorProfiles");
563 return NT_STATUS_NO_MEMORY;
566 status = gp_inifile_getstring_ext(ctx, key, &s);
567 if (NT_STATUS_IS_OK(status)) {
569 status = add_string_to_spoolss_array(mem_ctx, s, &r->color_profiles);
570 if (!NT_STATUS_IS_OK(status)) {
578 static NTSTATUS process_driver_section_printprocessor(struct gp_inifile_context *ctx,
581 struct spoolss_AddDriverInfo8 *r)
587 key = talloc_asprintf(mem_ctx, "%s:%s", section, "PrintProcessor");
589 return NT_STATUS_NO_MEMORY;
592 status = gp_inifile_getstring_ext(ctx, key, &s);
593 if (NT_STATUS_IS_OK(status)) {
594 s = get_string_unquote(s);
598 return NT_STATUS_INVALID_PARAMETER;
601 r->print_processor = talloc_strdup(mem_ctx, s);
602 if (r->print_processor == NULL) {
603 return NT_STATUS_NO_MEMORY;
610 static NTSTATUS process_driver_section_data_section(struct gp_inifile_context *ctx,
613 struct spoolss_AddDriverInfo8 *r)
619 key = talloc_asprintf(mem_ctx, "%s:%s", section, "DataSection");
621 return NT_STATUS_NO_MEMORY;
624 status = gp_inifile_getstring(ctx, key, &s);
625 if (NT_STATUS_IS_OK(status)) {
626 process_driver_section_val(ctx, mem_ctx, s, r,
627 "DriverFile", driver_path);
628 process_driver_section_val(ctx, mem_ctx, s, r,
629 "HelpFile", help_file);
630 process_driver_section_val(ctx, mem_ctx, s, r,
631 "DataFile", data_file);
632 process_driver_section_val(ctx, mem_ctx, s, r,
633 "ConfigFile", config_file);
640 static NTSTATUS process_one_core_driver_section(struct gp_inifile_context *core_ctx,
642 const char *driver_section,
643 struct spoolss_AddDriverInfo8 *r)
647 const char **keys = NULL;
648 const char **values = NULL;
651 DEBUG(10,("CoreDriverSection is: %s\n", driver_section));
653 status = gp_inifile_enum_section(core_ctx, driver_section, &num_keys, &keys, &values);
654 if (!NT_STATUS_IS_OK(status)) {
658 for (i = 0; i < num_keys; i++) {
660 status = process_driver_section_copyfiles(core_ctx, mem_ctx, driver_section, r);
661 if (!NT_STATUS_IS_OK(status)) {
665 process_driver_section_val(core_ctx, mem_ctx, driver_section, r,
666 "DriverFile", driver_path);
667 process_driver_section_val(core_ctx, mem_ctx, driver_section, r,
668 "HelpFile", help_file);
669 process_driver_section_val(core_ctx, mem_ctx, driver_section, r,
670 "ConfigFile", config_file);
672 status = process_driver_section_colorprofiles(core_ctx, mem_ctx, driver_section, r);
673 if (!NT_STATUS_IS_OK(status)) {
685 * CoreDriverSections="{D20EA372-DD35-4950-9ED8-A6335AFE79F0},UNIDRV_BIDI.OEM,UNIDRV_BIDI_DATA","{D20EA372-DD35-4950-9ED8-A6335AFE79F2},PCLXL.OEM","{D20EA372-DD35-4950-9ED8-A6335AFE79F3},sRGBPROFILE.OEM"
687 static NTSTATUS process_core_driver_sections(struct gp_inifile_context *core_ctx,
690 struct spoolss_AddDriverInfo8 *r)
697 list = str_list_make_v3(mem_ctx, value, ",");
699 return NT_STATUS_NO_MEMORY;
702 for (i = 0; list[i] != NULL; i++) {
706 /* FIXME: do we have to validate the core driver guid ? */
708 p = strchr(list[i], ',');
714 DEBUG(10,("CoreDriverSections we have to process: %s\n", p));
716 array = str_list_make_v3(mem_ctx, p, ",");
718 return NT_STATUS_NO_MEMORY;
721 for (a = 0; array[a] != NULL; a++) {
723 if (core_ctx == NULL) {
724 DEBUG(0,("Need to process CoreDriverSections but "
725 "have no Core Driver Context!\n"));
726 return NT_STATUS_DRIVER_INTERNAL_ERROR;
729 status = process_one_core_driver_section(core_ctx, mem_ctx, array[a], r);
730 if (!NT_STATUS_IS_OK(status)) {
740 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-ddinstall-section
742 static NTSTATUS find_driver_files(struct gp_inifile_context *ctx,
743 struct gp_inifile_context *core_ctx,
745 const char *driver_name,
746 struct spoolss_AddDriverInfo8 *r)
752 char *install_section_name;
756 status = find_device_in_toc(ctx, mem_ctx, driver_name, &value);
757 if (!NT_STATUS_IS_OK(status)) {
761 r->driver_name = talloc_strdup(mem_ctx, driver_name);
762 if (r->driver_name == NULL) {
763 return NT_STATUS_NO_MEMORY;
766 ok = next_token_talloc(mem_ctx, &value, &install_section_name, ",");
768 return NT_STATUS_INVALID_PARAMETER;
771 DEBUG(10,("driver_name: %s, value: %s, install_section_name: %s\n",
772 driver_name, value, install_section_name));
774 /* Hardware Id is optional */
775 ok = next_token_talloc(mem_ctx, &value, &hw_id, ",");
777 r->hardware_id = hw_id;
780 status = process_driver_section_copyfiles(ctx, mem_ctx, install_section_name, r);
781 if (!NT_STATUS_IS_OK(status)) {
785 process_driver_section_val(ctx, mem_ctx, install_section_name, r,
786 "DriverFile", driver_path);
787 process_driver_section_val(ctx, mem_ctx, install_section_name, r,
788 "HelpFile", help_file);
789 process_driver_section_val(ctx, mem_ctx, install_section_name, r,
790 "DataFile", data_file);
791 process_driver_section_val(ctx, mem_ctx, install_section_name, r,
792 "ConfigFile", config_file);
794 status = process_driver_section_printprocessor(ctx, mem_ctx, install_section_name, r);
795 if (!NT_STATUS_IS_OK(status)) {
799 status = process_driver_section_data_section(ctx, mem_ctx, install_section_name, r);
800 if (!NT_STATUS_IS_OK(status)) {
804 key = talloc_asprintf(mem_ctx, "%s:%s", install_section_name, "CoreDriverSections");
806 return NT_STATUS_NO_MEMORY;
809 status = gp_inifile_getstring(ctx, key, &s);
810 if (NT_STATUS_IS_OK(status)) {
812 DEBUG(10,("found CoreDriverSections: %s\n", s));
814 status = process_core_driver_sections(core_ctx, mem_ctx, s, r);
815 if (!NT_STATUS_IS_OK(status)) {
824 struct gp_inifile_context *ctx;
825 struct gp_inifile_context *core_ctx;
828 static NTSTATUS init_inf_context(TALLOC_CTX *mem_ctx,
829 const char *inf_filename,
830 const char *core_filename,
831 struct inf_context **_inf_ctx)
834 struct gp_inifile_context *ctx;
835 struct gp_inifile_context *core_ctx = NULL;
836 struct inf_context *inf_ctx;
838 inf_ctx = talloc_zero(mem_ctx, struct inf_context);
839 if (inf_ctx == NULL) {
840 return NT_STATUS_NO_MEMORY;
843 status = gp_inifile_init_context_direct(mem_ctx,
846 if (!NT_STATUS_IS_OK(status)) {
847 DEBUG(10,("init_inf_context: failed to load %s\n", inf_filename));
851 if (ctx->generated_filename != NULL) {
852 unlink(ctx->generated_filename);
855 if (core_filename != NULL) {
856 status = gp_inifile_init_context_direct(mem_ctx,
859 if (!NT_STATUS_IS_OK(status)) {
860 DEBUG(10,("init_inf_context: failed to load %s\n", core_filename));
864 if (core_ctx->generated_filename != NULL) {
865 unlink(core_ctx->generated_filename);
870 inf_ctx->core_ctx = core_ctx;
877 static NTSTATUS process_driver_driverver(struct gp_inifile_context *ctx,
878 struct spoolss_AddDriverInfo8 *r)
886 status = gp_inifile_getstring(ctx, "Version:DriverVer", &s);
887 if (!NT_STATUS_IS_OK(status)) {
891 str = talloc_strdup(ctx, s);
893 return NT_STATUS_NO_MEMORY;
896 p = strchr(str, ',');
902 ok = spoolss_timestr_to_NTTIME(str, &r->driver_date);
904 return NT_STATUS_INVALID_PARAMETER;
907 ok = spoolss_driver_version_to_qword(p, &r->driver_version);
909 return NT_STATUS_INVALID_PARAMETER;
916 * Parse a SourceDisksNames section,
917 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-sourcedisksnames-section?f=255&MSPPError=-2147217396
919 static NTSTATUS process_source_disk_name(struct gp_inifile_context *ctx,
921 const char *short_environment,
922 const char **source_disk_name)
928 const char **keys = NULL;
929 const char **values = NULL;
932 key = talloc_asprintf(mem_ctx, "SourceDisksNames.%s", short_environment);
934 return NT_STATUS_NO_MEMORY;
937 status = gp_inifile_enum_section(ctx, key, &num_keys, &keys, &values);
938 if (!NT_STATUS_IS_OK(status)) {
942 if (keys == NULL && values == NULL) {
943 key = "SourceDisksNames";
945 status = gp_inifile_enum_section(ctx, key, &num_keys, &keys, &values);
946 if (!NT_STATUS_IS_OK(status)) {
951 for (i = 0; i < num_keys; i++) {
954 * 1 = %Disk1%,,,"Amd64"
955 * diskid = disk-description[,[tag-or-cab-file],[unused],[path],[flags][,tag-file]]
957 char *disk_description, *tag_or_cab_file, *unused, *path;
959 ok = next_token_no_ltrim_talloc(mem_ctx, &values[i], &disk_description, ",");
964 ok = next_token_no_ltrim_talloc(mem_ctx, &values[i], &tag_or_cab_file, ",");
969 ok = next_token_no_ltrim_talloc(mem_ctx, &values[i], &unused, ",");
974 ok = next_token_no_ltrim_talloc(mem_ctx, &values[i], &path, ",");
979 *source_disk_name = path;
984 return NT_STATUS_NOT_FOUND;
987 static NTSTATUS setup_driver_by_name(TALLOC_CTX *mem_ctx,
988 struct inf_context *inf_ctx,
989 const char *filename,
990 const char *environment,
991 const char *driver_name,
992 struct spoolss_AddDriverInfo8 *r,
993 const char **source_disk_name)
996 struct gp_inifile_context *ctx = inf_ctx->ctx;
997 struct gp_inifile_context *core_ctx = inf_ctx->core_ctx;
1000 const char *short_environment;
1003 short_environment = spoolss_get_short_filesys_environment(environment);
1004 if (short_environment == NULL) {
1005 return NT_STATUS_INVALID_PARAMETER;
1008 status = find_driver_files(ctx, core_ctx, mem_ctx, driver_name, r);
1009 if (!NT_STATUS_IS_OK(status)) {
1013 status = process_source_disk_name(ctx, mem_ctx,
1016 if (!NT_STATUS_IS_OK(status)) {
1020 r->inf_path = talloc_strdup(mem_ctx, filename);
1021 if (r->inf_path == NULL) {
1022 return NT_STATUS_NO_MEMORY;
1025 r->architecture = talloc_strdup(mem_ctx, environment);
1026 if (r->architecture == NULL) {
1027 return NT_STATUS_NO_MEMORY;
1030 if (r->print_processor == NULL) {
1031 r->print_processor = talloc_strdup(mem_ctx, "winprint");
1032 if (r->print_processor == NULL) {
1033 return NT_STATUS_NO_MEMORY;
1037 status = gp_inifile_getstring_ext(ctx, "Version:Class", &s);
1038 if (NT_STATUS_IS_OK(status)) {
1039 if (strequal(s, "Printer")) {
1040 r->printer_driver_attributes |= PRINTER_DRIVER_CLASS;
1044 status = gp_inifile_getstring(ctx, "Version:Signature", &s);
1045 if (!NT_STATUS_IS_OK(status)) {
1048 if (!strequal(s, "\"$Windows NT$\"")) {
1049 return NT_STATUS_INVALID_SIGNATURE;
1052 r->version = SPOOLSS_DRIVER_VERSION_200X;
1053 status = gp_inifile_getstring(ctx, "Version:ClassVer", &s);
1054 if (NT_STATUS_IS_OK(status)) {
1055 int cmp = strncasecmp_m(s, "4.0", 3);
1057 r->version = SPOOLSS_DRIVER_VERSION_2012;
1059 if (strequal(s, "3.0")) {
1060 r->version = SPOOLSS_DRIVER_VERSION_200X;
1064 status = gp_inifile_getstring_ext(ctx, "Version:Provider", &s);
1065 if (NT_STATUS_IS_OK(status)) {
1067 r->provider = talloc_strdup(mem_ctx, s);
1068 if (r->provider == NULL) {
1069 return NT_STATUS_NO_MEMORY;
1074 status = process_driver_driverver(ctx, r);
1075 if (!NT_STATUS_IS_OK(status)) {
1079 r->printer_driver_attributes &= ~PRINTER_DRIVER_SANDBOX_ENABLED;
1081 status = gp_inifile_getstring(ctx, "Version:DriverIsolation", &s);
1082 if (NT_STATUS_IS_OK(status)) {
1083 int cmp = strncasecmp_m(s, "2", 1);
1085 r->printer_driver_attributes |= PRINTER_DRIVER_SANDBOX_ENABLED;
1087 cmp = strncasecmp_m(s, "0", 1);
1089 r->printer_driver_attributes &= ~PRINTER_DRIVER_SANDBOX_ENABLED;
1093 status = find_manufacturer_name(ctx, mem_ctx, "Manufacturer", &r->manufacturer_name);
1094 if (!NT_STATUS_IS_OK(status)) {
1098 status = find_manufacturer_url(ctx, mem_ctx, "OEM URLS", r->manufacturer_name, &r->manufacturer_url);
1099 if (!NT_STATUS_IS_OK(status)) {
1103 status = gp_inifile_getbool(ctx, "PrinterPackageInstallation:PackageAware", &ok);
1104 if (NT_STATUS_IS_OK(status)) {
1106 r->printer_driver_attributes |= PRINTER_DRIVER_PACKAGE_AWARE;
1110 key = talloc_asprintf(mem_ctx, "%s.%s:%s",
1111 "PrinterPackageInstallation", short_environment, "PackageAware");
1113 return NT_STATUS_NO_MEMORY;
1116 status = gp_inifile_getbool(ctx, key, &ok);
1117 if (NT_STATUS_IS_OK(status)) {
1119 r->printer_driver_attributes |= PRINTER_DRIVER_PACKAGE_AWARE;
1123 key = talloc_asprintf(mem_ctx, "%s.%s:%s",
1124 "PrinterPackageInstallation", short_environment, "CoreDriverDependencies");
1126 return NT_STATUS_NO_MEMORY;
1129 status = gp_inifile_getstring(ctx, key, &s);
1130 if (NT_STATUS_IS_OK(status)) {
1132 r->core_driver_dependencies = talloc_zero(mem_ctx, struct spoolss_StringArray);
1133 if (r->core_driver_dependencies == NULL) {
1134 return NT_STATUS_NO_MEMORY;
1137 list = str_list_make_v3(r->core_driver_dependencies, s, ",");
1139 return NT_STATUS_NO_MEMORY;
1141 r->core_driver_dependencies->string = const_str_list(list);
1144 key = talloc_asprintf(mem_ctx, "%s.%s:%s",
1145 "PrinterPackageInstallation", short_environment, "InboxVersionRequired");
1147 return NT_STATUS_NO_MEMORY;
1150 status = gp_inifile_getstring(ctx, key, &s);
1151 if (NT_STATUS_IS_OK(status)) {
1152 if (strequal(s, "UseDriverVer")) {
1153 r->min_inbox_driver_ver_date = r->driver_date;
1154 r->min_inbox_driver_ver_version = r->driver_version;
1158 return NT_STATUS_OK;
1161 /****************************************************************
1162 parse the a printer inf file
1163 ****************************************************************/
1165 NTSTATUS driver_inf_parse(TALLOC_CTX *mem_ctx,
1166 const char *core_driver_inf,
1167 const char *filename,
1168 const char *environment,
1169 const char *driver_name,
1170 struct spoolss_AddDriverInfo8 *r,
1171 const char **source_disk_name)
1174 struct inf_context *inf_ctx;
1176 if (!filename || !environment) {
1177 return NT_STATUS_INVALID_PARAMETER;
1180 status = init_inf_context(mem_ctx,
1184 if (!NT_STATUS_IS_OK(status)) {
1188 status = setup_driver_by_name(mem_ctx, inf_ctx,
1194 if (!NT_STATUS_IS_OK(status)) {
1198 return NT_STATUS_OK;
1201 NTSTATUS driver_inf_list(TALLOC_CTX *mem_ctx,
1202 const char *core_driver_inf,
1203 const char *filename,
1204 const char *environment,
1206 struct spoolss_AddDriverInfo8 **_r)
1209 const char *short_environment;
1210 size_t num_devices = 0;
1211 const char **devices = NULL;
1212 const char **device_values = NULL;
1213 struct inf_context *inf_ctx;
1216 if (!filename || !environment) {
1217 return NT_STATUS_INVALID_PARAMETER;
1220 short_environment = spoolss_get_short_filesys_environment(environment);
1221 if (short_environment == NULL) {
1222 return NT_STATUS_INVALID_PARAMETER;
1225 status = init_inf_context(mem_ctx,
1229 if (!NT_STATUS_IS_OK(status)) {
1233 status = enum_devices_in_toc(inf_ctx->ctx, mem_ctx,
1237 if (!NT_STATUS_IS_OK(status)) {
1241 for (d = 0; d < num_devices; d++) {
1243 struct spoolss_AddDriverInfo8 r;
1244 const char *source_disk_name;
1248 status = setup_driver_by_name(mem_ctx, inf_ctx, filename,
1249 environment, devices[d], &r,
1251 if (!NT_STATUS_IS_OK(status)) {
1255 ADD_TO_ARRAY(mem_ctx, struct spoolss_AddDriverInfo8, r, _r, count);
1258 return NT_STATUS_OK;