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"
25 #include "source3/include/smb_macros.h"
27 /* GetPrinterDriverDirectory -> drivers and dependent files */
28 #define PRINTER_INF_DIRID_66000
30 /* GetPrintProcessorDirectory -> print processors */
31 #define PRINTER_INF_DIRID_66001
33 /* GetColorDirectory -> color profiles */
34 #define PRINTER_INF_DIRID_66003
36 static const char *get_string_unquote(const char *s
)
50 if (s
[0] == '"' && s
[len
-1] == '"') {
51 ok
= trim_string(discard_const(s
), "\"", "\"");
61 * '%STRING%' indicates STRING is localized in the [Strings] section
64 static const char *get_string_token(struct gp_inifile_context
*ctx
,
72 if (s
!= NULL
&& s
[0] != '%' && s
[strlen(s
)-1] != '%') {
76 ok
= trim_string(discard_const(s
), "%", "%");
81 key
= talloc_asprintf(ctx
, "Strings:%s", s
);
86 status
= gp_inifile_getstring(ctx
, key
, &s2
);
88 if (!NT_STATUS_IS_OK(status
)) {
89 /* what can you do... */
96 static NTSTATUS
gp_inifile_getstring_ext(struct gp_inifile_context
*ctx
,
103 status
= gp_inifile_getstring(ctx
, key
, &s
);
104 if (!NT_STATUS_IS_OK(status
)) {
108 s
= get_string_unquote(s
);
110 return NT_STATUS_INTERNAL_ERROR
;
113 if (s
[0] == '%' && s
[strlen(s
)-1] == '%') {
114 s
= get_string_token(ctx
, s
);
117 s
= get_string_unquote(s
);
119 return NT_STATUS_INTERNAL_ERROR
;
127 static NTSTATUS
find_manufacturer_name(struct gp_inifile_context
*ctx
,
129 const char *section_name
,
130 const char **manufacturer_name
)
134 const char **keys
= NULL
;
135 const char **values
= NULL
;
139 status
= gp_inifile_enum_section(ctx
, section_name
, &num_keys
, &keys
, &values
);
140 if (!NT_STATUS_IS_OK(status
)) {
145 return NT_STATUS_INVALID_PARAMETER
;
148 s
= talloc_strdup(mem_ctx
, keys
[0]);
150 return NT_STATUS_NO_MEMORY
;
155 return NT_STATUS_NO_MEMORY
;
160 s
= get_string_unquote(p
);
162 return NT_STATUS_INTERNAL_ERROR
;
165 s
= get_string_token(ctx
, s
);
167 s
= get_string_unquote(s
);
169 return NT_STATUS_INTERNAL_ERROR
;
173 *manufacturer_name
= talloc_strdup(mem_ctx
, s
);
174 if (*manufacturer_name
== NULL
) {
175 return NT_STATUS_NO_MEMORY
;
185 static NTSTATUS
find_manufacturer_url(struct gp_inifile_context
*ctx
,
187 const char *section_name
,
188 const char *manufacturer_name
,
189 const char **manufacturer_url
)
193 const char **keys
= NULL
;
194 const char **values
= NULL
;
198 status
= gp_inifile_enum_section(ctx
, section_name
, &num_keys
, &keys
, &values
);
200 if (!NT_STATUS_IS_OK(status
)) {
205 return NT_STATUS_INVALID_PARAMETER
;
208 p
= strchr(keys
[0], ':');
210 return NT_STATUS_NO_MEMORY
;
215 s
= get_string_unquote(p
);
217 return NT_STATUS_INTERNAL_ERROR
;
220 s
= get_string_token(ctx
, s
);
222 s
= get_string_unquote(s
);
224 return NT_STATUS_INTERNAL_ERROR
;
227 if (strequal(s
, manufacturer_name
)) {
228 s
= get_string_unquote(values
[0]);
230 return NT_STATUS_INTERNAL_ERROR
;
235 *manufacturer_url
= talloc_strdup(mem_ctx
, s
);
236 if (*manufacturer_url
== NULL
) {
237 return NT_STATUS_NO_MEMORY
;
247 static NTSTATUS
add_string_to_spoolss_array(TALLOC_CTX
*mem_ctx
,
249 struct spoolss_StringArray
**r
)
252 struct spoolss_StringArray
*a
= *r
;
257 a
= talloc_zero(mem_ctx
, struct spoolss_StringArray
);
259 return NT_STATUS_NO_MEMORY
;
263 if (a
->string
== NULL
) {
264 a
->string
= talloc_zero_array(a
, const char *, count
);
265 if (a
->string
== NULL
) {
266 return NT_STATUS_NO_MEMORY
;
270 for (i
= 0; a
->string
[i
] != NULL
; i
++) { ;; }
273 ok
= add_string_to_array(mem_ctx
, s
, &a
->string
, &count
);
275 return NT_STATUS_NO_MEMORY
;
278 a
->string
= talloc_realloc(mem_ctx
, a
->string
, const char *, count
+ 1);
279 if (a
->string
== NULL
) {
280 return NT_STATUS_NO_MEMORY
;
282 a
->string
[count
] = NULL
;
289 static NTSTATUS
add_dependent_driver_file(TALLOC_CTX
*mem_ctx
,
291 struct spoolss_StringArray
**r
)
296 return NT_STATUS_INVALID_PARAMETER
;
299 if (file
[0] == '@') {
303 p
= strchr(file
, ',');
308 return add_string_to_spoolss_array(mem_ctx
, file
, r
);
312 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-manufacturer-section
315 * "Kyocera"=Kyocera,NTx86.5.1,NTx86.6.0,NTamd64.5.1,NTamd64.6.0
318 static NTSTATUS
enum_devices_in_toc(struct gp_inifile_context
*ctx
,
320 size_t *pnum_devices
,
321 const char ***pdevices
,
322 const char ***pdevice_values
)
325 size_t i
, num_manufacturers
= 0;
326 const char **manufacturers
= NULL
;
327 const char **values
= NULL
;
331 status
= gp_inifile_enum_section(ctx
, "Manufacturer", &num_manufacturers
, &manufacturers
, &values
);
332 if (!NT_STATUS_IS_OK(status
)) {
336 for (i
= 0; i
< num_manufacturers
; i
++) {
338 const char *models_section_name
;
343 DEBUG(11,("processing manufacturer: %s\n", manufacturers
[i
]));
345 status
= gp_inifile_getstring(ctx
, manufacturers
[i
], &s
);
346 if (!NT_STATUS_IS_OK(status
)) {
350 decorations
= str_list_make_v3(mem_ctx
, s
, ",");
351 if (decorations
== NULL
) {
352 return NT_STATUS_NO_MEMORY
;
355 models_section_name
= decorations
[0];
357 for (j
= 1; decorations
[j
] != NULL
; j
++) {
360 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-models-section
363 const char *decorated_models_section_name
;
364 size_t d
, num_devices
= 0;
365 const char **devices
= NULL
;
366 const char **device_values
= NULL
;
369 decorated_models_section_name
= talloc_asprintf(mem_ctx
, "%s.%s",
372 if (decorated_models_section_name
== NULL
) {
373 return NT_STATUS_NO_MEMORY
;
376 DEBUG(11,("processing decorated models_section_name: %s\n",
377 decorated_models_section_name
));
379 status
= gp_inifile_enum_section(ctx
, decorated_models_section_name
,
380 &num_devices
, &devices
,
382 if (!NT_STATUS_IS_OK(status
)) {
385 for (d
= 0; d
< num_devices
; d
++) {
387 DEBUG(11,("processing device: %s\n",
390 s
= talloc_strdup(mem_ctx
, devices
[d
]);
392 return NT_STATUS_NO_MEMORY
;
397 return NT_STATUS_DRIVER_INTERNAL_ERROR
;
403 s
= get_string_unquote(p
);
405 ok
= add_string_to_array(mem_ctx
, s
, pdevices
, pnum_devices
);
407 return NT_STATUS_NO_MEMORY
;
409 ok
= add_string_to_array(mem_ctx
, device_values
[d
], pdevice_values
, &c
);
411 return NT_STATUS_NO_MEMORY
;
420 static NTSTATUS
find_device_in_toc(struct gp_inifile_context
*ctx
,
422 const char *device_description
,
426 size_t d
, num_devices
= 0;
427 const char **devices
= NULL
;
428 const char **device_values
= NULL
;
430 if (device_description
== NULL
) {
431 return NT_STATUS_INVALID_PARAMETER
;
434 status
= enum_devices_in_toc(ctx
, mem_ctx
,
438 if (!NT_STATUS_IS_OK(status
)) {
442 for (d
= 0; d
< num_devices
; d
++) {
444 if (strequal(device_description
, devices
[d
])) {
446 DEBUG(10,("found device_description: %s\n",
447 device_description
));
449 *value
= talloc_strdup(mem_ctx
, device_values
[d
]);
450 if (*value
== NULL
) {
451 return NT_STATUS_NO_MEMORY
;
453 DEBUGADD(10,("and returned: %s\n", *value
));
459 return NT_STATUS_DRIVER_INTERNAL_ERROR
;
463 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-copyfiles-directive
466 static NTSTATUS
process_driver_section_copyfiles(struct gp_inifile_context
*ctx
,
468 const char *driver_section
,
469 struct spoolss_AddDriverInfo8
*r
)
472 size_t i
, num_keys
= 0;
474 const char **keys
= NULL
;
475 const char **values
= NULL
;
479 key
= talloc_asprintf(mem_ctx
, "%s:%s", driver_section
, "CopyFiles");
481 return NT_STATUS_NO_MEMORY
;
484 DEBUG(10,("Checking for CopyFiles entry in %s\n", driver_section
));
486 status
= gp_inifile_getstring(ctx
, key
, &s
);
487 if (!NT_STATUS_IS_OK(status
)) {
491 DEBUG(10,("these are the files to copy: %s\n", s
));
493 while (next_token_talloc(mem_ctx
, &s
, &str
, ",")) {
495 DEBUG(10,("trying section: %s\n", str
));
498 DEBUG(10,("adding dependent driver file: %s\n", str
));
499 status
= add_dependent_driver_file(mem_ctx
, str
, &r
->dependent_files
);
500 if (!NT_STATUS_IS_OK(status
)) {
506 status
= gp_inifile_enum_section(ctx
, str
, &num_keys
, &keys
, &values
);
507 if (NT_STATUS_IS_OK(status
)) {
508 for (i
= 0; i
< num_keys
; i
++) {
509 p
= strchr(keys
[i
], ':');
511 return NT_STATUS_INVALID_PARAMETER
;
516 DEBUG(10,("adding dependent driver file: %s\n", p
));
518 status
= add_dependent_driver_file(mem_ctx
, p
, &r
->dependent_files
);
519 if (!NT_STATUS_IS_OK(status
)) {
531 #define process_driver_section_val(_ctx, _mem_ctx, _section, _r, _key, _element) \
534 const char *__key, *_s; \
535 __key = talloc_asprintf(_mem_ctx, "%s:%s", _section, _key); \
536 NT_STATUS_HAVE_NO_MEMORY(__key); \
537 _status = gp_inifile_getstring(_ctx, __key, &_s); \
538 if (NT_STATUS_IS_OK(_status)) { \
539 (_r)->_element = talloc_strdup(mem_ctx, _s); \
540 NT_STATUS_HAVE_NO_MEMORY((_r)->_element); \
544 static NTSTATUS
process_driver_section_colorprofiles(struct gp_inifile_context
*ctx
,
547 struct spoolss_AddDriverInfo8
*r
)
552 key
= talloc_asprintf(mem_ctx
, "%s:%s", section
, "ColorProfiles");
554 return NT_STATUS_NO_MEMORY
;
557 status
= gp_inifile_getstring_ext(ctx
, key
, &s
);
558 if (NT_STATUS_IS_OK(status
)) {
560 status
= add_string_to_spoolss_array(mem_ctx
, s
, &r
->color_profiles
);
561 if (!NT_STATUS_IS_OK(status
)) {
569 static NTSTATUS
process_driver_section_printprocessor(struct gp_inifile_context
*ctx
,
572 struct spoolss_AddDriverInfo8
*r
)
578 key
= talloc_asprintf(mem_ctx
, "%s:%s", section
, "PrintProcessor");
580 return NT_STATUS_NO_MEMORY
;
583 status
= gp_inifile_getstring_ext(ctx
, key
, &s
);
584 if (NT_STATUS_IS_OK(status
)) {
585 s
= get_string_unquote(s
);
589 return NT_STATUS_INVALID_PARAMETER
;
592 r
->print_processor
= talloc_strdup(mem_ctx
, s
);
593 if (r
->print_processor
== NULL
) {
594 return NT_STATUS_NO_MEMORY
;
601 static NTSTATUS
process_driver_section_data_section(struct gp_inifile_context
*ctx
,
604 struct spoolss_AddDriverInfo8
*r
)
610 key
= talloc_asprintf(mem_ctx
, "%s:%s", section
, "DataSection");
612 return NT_STATUS_NO_MEMORY
;
615 status
= gp_inifile_getstring(ctx
, key
, &s
);
616 if (NT_STATUS_IS_OK(status
)) {
617 process_driver_section_val(ctx
, mem_ctx
, s
, r
,
618 "DriverFile", driver_path
);
619 process_driver_section_val(ctx
, mem_ctx
, s
, r
,
620 "HelpFile", help_file
);
621 process_driver_section_val(ctx
, mem_ctx
, s
, r
,
622 "DataFile", data_file
);
623 process_driver_section_val(ctx
, mem_ctx
, s
, r
,
624 "ConfigFile", config_file
);
631 static NTSTATUS
process_one_core_driver_section(struct gp_inifile_context
*core_ctx
,
633 const char *driver_section
,
634 struct spoolss_AddDriverInfo8
*r
)
637 size_t i
, num_keys
= 0;
638 const char **keys
= NULL
;
639 const char **values
= NULL
;
641 DEBUG(10,("CoreDriverSection is: %s\n", driver_section
));
643 status
= gp_inifile_enum_section(core_ctx
, driver_section
, &num_keys
, &keys
, &values
);
644 if (!NT_STATUS_IS_OK(status
)) {
648 for (i
= 0; i
< num_keys
; i
++) {
650 status
= process_driver_section_copyfiles(core_ctx
, mem_ctx
, driver_section
, r
);
651 if (!NT_STATUS_IS_OK(status
)) {
655 process_driver_section_val(core_ctx
, mem_ctx
, driver_section
, r
,
656 "DriverFile", driver_path
);
657 process_driver_section_val(core_ctx
, mem_ctx
, driver_section
, r
,
658 "HelpFile", help_file
);
659 process_driver_section_val(core_ctx
, mem_ctx
, driver_section
, r
,
660 "ConfigFile", config_file
);
662 status
= process_driver_section_colorprofiles(core_ctx
, mem_ctx
, driver_section
, r
);
663 if (!NT_STATUS_IS_OK(status
)) {
675 * 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"
677 static NTSTATUS
process_core_driver_sections(struct gp_inifile_context
*core_ctx
,
680 struct spoolss_AddDriverInfo8
*r
)
687 list
= str_list_make_v3(mem_ctx
, value
, ",");
689 return NT_STATUS_NO_MEMORY
;
692 for (i
= 0; list
[i
] != NULL
; i
++) {
696 /* FIXME: do we have to validate the core driver guid ? */
698 p
= strchr(list
[i
], ',');
704 DEBUG(10,("CoreDriverSections we have to process: %s\n", p
));
706 array
= str_list_make_v3(mem_ctx
, p
, ",");
708 return NT_STATUS_NO_MEMORY
;
711 for (a
= 0; array
[a
] != NULL
; a
++) {
713 if (core_ctx
== NULL
) {
714 DEBUG(0,("Need to process CoreDriverSections but "
715 "have no Core Driver Context!\n"));
716 return NT_STATUS_DRIVER_INTERNAL_ERROR
;
719 status
= process_one_core_driver_section(core_ctx
, mem_ctx
, array
[a
], r
);
720 if (!NT_STATUS_IS_OK(status
)) {
730 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-ddinstall-section
732 static NTSTATUS
find_driver_files(struct gp_inifile_context
*ctx
,
733 struct gp_inifile_context
*core_ctx
,
735 const char *driver_name
,
736 struct spoolss_AddDriverInfo8
*r
)
742 char *install_section_name
;
746 status
= find_device_in_toc(ctx
, mem_ctx
, driver_name
, &value
);
747 if (!NT_STATUS_IS_OK(status
)) {
751 r
->driver_name
= talloc_strdup(mem_ctx
, driver_name
);
752 if (r
->driver_name
== NULL
) {
753 return NT_STATUS_NO_MEMORY
;
756 ok
= next_token_talloc(mem_ctx
, &value
, &install_section_name
, ",");
758 return NT_STATUS_INVALID_PARAMETER
;
761 DEBUG(10,("driver_name: %s, value: %s, install_section_name: %s\n",
762 driver_name
, value
, install_section_name
));
764 /* Hardware Id is optional */
765 ok
= next_token_talloc(mem_ctx
, &value
, &hw_id
, ",");
767 r
->hardware_id
= hw_id
;
770 status
= process_driver_section_copyfiles(ctx
, mem_ctx
, install_section_name
, r
);
771 if (!NT_STATUS_IS_OK(status
)) {
775 process_driver_section_val(ctx
, mem_ctx
, install_section_name
, r
,
776 "DriverFile", driver_path
);
777 process_driver_section_val(ctx
, mem_ctx
, install_section_name
, r
,
778 "HelpFile", help_file
);
779 process_driver_section_val(ctx
, mem_ctx
, install_section_name
, r
,
780 "DataFile", data_file
);
781 process_driver_section_val(ctx
, mem_ctx
, install_section_name
, r
,
782 "ConfigFile", config_file
);
784 status
= process_driver_section_printprocessor(ctx
, mem_ctx
, install_section_name
, r
);
785 if (!NT_STATUS_IS_OK(status
)) {
789 status
= process_driver_section_data_section(ctx
, mem_ctx
, install_section_name
, r
);
790 if (!NT_STATUS_IS_OK(status
)) {
794 key
= talloc_asprintf(mem_ctx
, "%s:%s", install_section_name
, "CoreDriverSections");
796 return NT_STATUS_NO_MEMORY
;
799 status
= gp_inifile_getstring(ctx
, key
, &s
);
800 if (NT_STATUS_IS_OK(status
)) {
802 DEBUG(10,("found CoreDriverSections: %s\n", s
));
804 status
= process_core_driver_sections(core_ctx
, mem_ctx
, s
, r
);
805 if (!NT_STATUS_IS_OK(status
)) {
814 struct gp_inifile_context
*ctx
;
815 struct gp_inifile_context
*core_ctx
;
818 static NTSTATUS
init_inf_context(TALLOC_CTX
*mem_ctx
,
819 const char *inf_filename
,
820 const char *core_filename
,
821 struct inf_context
**_inf_ctx
)
824 struct gp_inifile_context
*ctx
;
825 struct gp_inifile_context
*core_ctx
= NULL
;
826 struct inf_context
*inf_ctx
;
828 inf_ctx
= talloc_zero(mem_ctx
, struct inf_context
);
829 if (inf_ctx
== NULL
) {
830 return NT_STATUS_NO_MEMORY
;
833 status
= gp_inifile_init_context_direct(mem_ctx
,
836 if (!NT_STATUS_IS_OK(status
)) {
837 DEBUG(10,("init_inf_context: failed to load %s\n", inf_filename
));
841 if (ctx
->generated_filename
!= NULL
) {
842 unlink(ctx
->generated_filename
);
845 if (core_filename
!= NULL
) {
846 status
= gp_inifile_init_context_direct(mem_ctx
,
849 if (!NT_STATUS_IS_OK(status
)) {
850 DEBUG(10,("init_inf_context: failed to load %s\n", core_filename
));
854 if (core_ctx
->generated_filename
!= NULL
) {
855 unlink(core_ctx
->generated_filename
);
860 inf_ctx
->core_ctx
= core_ctx
;
867 static NTSTATUS
process_driver_driverver(struct gp_inifile_context
*ctx
,
868 struct spoolss_AddDriverInfo8
*r
)
876 status
= gp_inifile_getstring(ctx
, "Version:DriverVer", &s
);
877 if (!NT_STATUS_IS_OK(status
)) {
881 str
= talloc_strdup(ctx
, s
);
883 return NT_STATUS_NO_MEMORY
;
886 p
= strchr(str
, ',');
892 ok
= spoolss_timestr_to_NTTIME(str
, &r
->driver_date
);
894 return NT_STATUS_INVALID_PARAMETER
;
897 ok
= spoolss_driver_version_to_qword(p
, &r
->driver_version
);
899 return NT_STATUS_INVALID_PARAMETER
;
906 * Parse a SourceDisksNames section,
907 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-sourcedisksnames-section?f=255&MSPPError=-2147217396
909 static NTSTATUS
process_source_disk_name(struct gp_inifile_context
*ctx
,
911 const char *short_environment
,
912 const char **source_disk_name
)
917 size_t i
, num_keys
= 0;
918 const char **keys
= NULL
;
919 const char **values
= NULL
;
921 key
= talloc_asprintf(mem_ctx
, "SourceDisksNames.%s", short_environment
);
923 return NT_STATUS_NO_MEMORY
;
926 status
= gp_inifile_enum_section(ctx
, key
, &num_keys
, &keys
, &values
);
927 if (!NT_STATUS_IS_OK(status
)) {
931 if (keys
== NULL
&& values
== NULL
) {
932 key
= "SourceDisksNames";
934 status
= gp_inifile_enum_section(ctx
, key
, &num_keys
, &keys
, &values
);
935 if (!NT_STATUS_IS_OK(status
)) {
940 for (i
= 0; i
< num_keys
; i
++) {
943 * 1 = %Disk1%,,,"Amd64"
944 * diskid = disk-description[,[tag-or-cab-file],[unused],[path],[flags][,tag-file]]
946 char *disk_description
, *tag_or_cab_file
, *unused
, *path
;
948 ok
= next_token_no_ltrim_talloc(mem_ctx
, &values
[i
], &disk_description
, ",");
953 ok
= next_token_no_ltrim_talloc(mem_ctx
, &values
[i
], &tag_or_cab_file
, ",");
958 ok
= next_token_no_ltrim_talloc(mem_ctx
, &values
[i
], &unused
, ",");
963 ok
= next_token_no_ltrim_talloc(mem_ctx
, &values
[i
], &path
, ",");
968 *source_disk_name
= path
;
973 return NT_STATUS_NOT_FOUND
;
976 static NTSTATUS
setup_driver_by_name(TALLOC_CTX
*mem_ctx
,
977 struct inf_context
*inf_ctx
,
978 const char *filename
,
979 const char *environment
,
980 const char *driver_name
,
981 struct spoolss_AddDriverInfo8
*r
,
982 const char **source_disk_name
)
985 struct gp_inifile_context
*ctx
= inf_ctx
->ctx
;
986 struct gp_inifile_context
*core_ctx
= inf_ctx
->core_ctx
;
989 const char *short_environment
;
992 short_environment
= spoolss_get_short_filesys_environment(environment
);
993 if (short_environment
== NULL
) {
994 return NT_STATUS_INVALID_PARAMETER
;
997 status
= find_driver_files(ctx
, core_ctx
, mem_ctx
, driver_name
, r
);
998 if (!NT_STATUS_IS_OK(status
)) {
1002 status
= process_source_disk_name(ctx
, mem_ctx
,
1005 if (!NT_STATUS_IS_OK(status
)) {
1009 r
->inf_path
= talloc_strdup(mem_ctx
, filename
);
1010 if (r
->inf_path
== NULL
) {
1011 return NT_STATUS_NO_MEMORY
;
1014 r
->architecture
= talloc_strdup(mem_ctx
, environment
);
1015 if (r
->architecture
== NULL
) {
1016 return NT_STATUS_NO_MEMORY
;
1019 if (r
->print_processor
== NULL
) {
1020 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
1021 if (r
->print_processor
== NULL
) {
1022 return NT_STATUS_NO_MEMORY
;
1026 status
= gp_inifile_getstring_ext(ctx
, "Version:Class", &s
);
1027 if (NT_STATUS_IS_OK(status
)) {
1028 if (strequal(s
, "Printer")) {
1029 r
->printer_driver_attributes
|= PRINTER_DRIVER_CLASS
;
1033 status
= gp_inifile_getstring(ctx
, "Version:Signature", &s
);
1034 if (!NT_STATUS_IS_OK(status
)) {
1037 if (!strequal(s
, "\"$Windows NT$\"")) {
1038 return NT_STATUS_INVALID_SIGNATURE
;
1041 r
->version
= SPOOLSS_DRIVER_VERSION_200X
;
1042 status
= gp_inifile_getstring(ctx
, "Version:ClassVer", &s
);
1043 if (NT_STATUS_IS_OK(status
)) {
1044 int cmp
= strncasecmp_m(s
, "4.0", 3);
1046 r
->version
= SPOOLSS_DRIVER_VERSION_2012
;
1048 if (strequal(s
, "3.0")) {
1049 r
->version
= SPOOLSS_DRIVER_VERSION_200X
;
1053 status
= gp_inifile_getstring_ext(ctx
, "Version:Provider", &s
);
1054 if (NT_STATUS_IS_OK(status
)) {
1056 r
->provider
= talloc_strdup(mem_ctx
, s
);
1057 if (r
->provider
== NULL
) {
1058 return NT_STATUS_NO_MEMORY
;
1063 status
= process_driver_driverver(ctx
, r
);
1064 if (!NT_STATUS_IS_OK(status
)) {
1068 r
->printer_driver_attributes
&= ~PRINTER_DRIVER_SANDBOX_ENABLED
;
1070 status
= gp_inifile_getstring(ctx
, "Version:DriverIsolation", &s
);
1071 if (NT_STATUS_IS_OK(status
)) {
1072 int cmp
= strncasecmp_m(s
, "2", 1);
1074 r
->printer_driver_attributes
|= PRINTER_DRIVER_SANDBOX_ENABLED
;
1076 cmp
= strncasecmp_m(s
, "0", 1);
1078 r
->printer_driver_attributes
&= ~PRINTER_DRIVER_SANDBOX_ENABLED
;
1082 status
= find_manufacturer_name(ctx
, mem_ctx
, "Manufacturer", &r
->manufacturer_name
);
1083 if (!NT_STATUS_IS_OK(status
)) {
1087 status
= find_manufacturer_url(ctx
, mem_ctx
, "OEM URLS", r
->manufacturer_name
, &r
->manufacturer_url
);
1088 if (!NT_STATUS_IS_OK(status
)) {
1092 status
= gp_inifile_getbool(ctx
, "PrinterPackageInstallation:PackageAware", &ok
);
1093 if (NT_STATUS_IS_OK(status
)) {
1095 r
->printer_driver_attributes
|= PRINTER_DRIVER_PACKAGE_AWARE
;
1099 key
= talloc_asprintf(mem_ctx
, "%s.%s:%s",
1100 "PrinterPackageInstallation", short_environment
, "PackageAware");
1102 return NT_STATUS_NO_MEMORY
;
1105 status
= gp_inifile_getbool(ctx
, key
, &ok
);
1106 if (NT_STATUS_IS_OK(status
)) {
1108 r
->printer_driver_attributes
|= PRINTER_DRIVER_PACKAGE_AWARE
;
1112 key
= talloc_asprintf(mem_ctx
, "%s.%s:%s",
1113 "PrinterPackageInstallation", short_environment
, "CoreDriverDependencies");
1115 return NT_STATUS_NO_MEMORY
;
1118 status
= gp_inifile_getstring(ctx
, key
, &s
);
1119 if (NT_STATUS_IS_OK(status
)) {
1121 r
->core_driver_dependencies
= talloc_zero(mem_ctx
, struct spoolss_StringArray
);
1122 if (r
->core_driver_dependencies
== NULL
) {
1123 return NT_STATUS_NO_MEMORY
;
1126 list
= str_list_make_v3(r
->core_driver_dependencies
, s
, ",");
1128 return NT_STATUS_NO_MEMORY
;
1130 r
->core_driver_dependencies
->string
= const_str_list(list
);
1133 key
= talloc_asprintf(mem_ctx
, "%s.%s:%s",
1134 "PrinterPackageInstallation", short_environment
, "InboxVersionRequired");
1136 return NT_STATUS_NO_MEMORY
;
1139 status
= gp_inifile_getstring(ctx
, key
, &s
);
1140 if (NT_STATUS_IS_OK(status
)) {
1141 if (strequal(s
, "UseDriverVer")) {
1142 r
->min_inbox_driver_ver_date
= r
->driver_date
;
1143 r
->min_inbox_driver_ver_version
= r
->driver_version
;
1147 return NT_STATUS_OK
;
1150 /****************************************************************
1151 parse a printer inf file
1152 ****************************************************************/
1154 NTSTATUS
driver_inf_parse(TALLOC_CTX
*mem_ctx
,
1155 const char *core_driver_inf
,
1156 const char *filename
,
1157 const char *environment
,
1158 const char *driver_name
,
1159 struct spoolss_AddDriverInfo8
*r
,
1160 const char **source_disk_name
)
1163 struct inf_context
*inf_ctx
;
1165 if (!filename
|| !environment
) {
1166 return NT_STATUS_INVALID_PARAMETER
;
1169 status
= init_inf_context(mem_ctx
,
1173 if (!NT_STATUS_IS_OK(status
)) {
1177 status
= setup_driver_by_name(mem_ctx
, inf_ctx
,
1183 if (!NT_STATUS_IS_OK(status
)) {
1187 return NT_STATUS_OK
;
1190 NTSTATUS
driver_inf_list(TALLOC_CTX
*mem_ctx
,
1191 const char *core_driver_inf
,
1192 const char *filename
,
1193 const char *environment
,
1195 struct spoolss_AddDriverInfo8
**_r
)
1198 const char *short_environment
;
1199 size_t d
, num_devices
= 0;
1200 const char **devices
= NULL
;
1201 const char **device_values
= NULL
;
1202 struct inf_context
*inf_ctx
;
1204 if (!filename
|| !environment
) {
1205 return NT_STATUS_INVALID_PARAMETER
;
1208 short_environment
= spoolss_get_short_filesys_environment(environment
);
1209 if (short_environment
== NULL
) {
1210 return NT_STATUS_INVALID_PARAMETER
;
1213 status
= init_inf_context(mem_ctx
,
1217 if (!NT_STATUS_IS_OK(status
)) {
1221 status
= enum_devices_in_toc(inf_ctx
->ctx
, mem_ctx
,
1225 if (!NT_STATUS_IS_OK(status
)) {
1229 for (d
= 0; d
< num_devices
; d
++) {
1231 struct spoolss_AddDriverInfo8 r
;
1232 const char *source_disk_name
;
1236 status
= setup_driver_by_name(mem_ctx
, inf_ctx
, filename
,
1237 environment
, devices
[d
], &r
,
1239 if (!NT_STATUS_IS_OK(status
)) {
1243 ADD_TO_ARRAY(mem_ctx
, struct spoolss_AddDriverInfo8
, r
, _r
, count
);
1246 return NT_STATUS_OK
;