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 i
, num_manufacturers
= 0;
334 const char **manufacturers
= NULL
;
335 const char **values
= NULL
;
339 status
= gp_inifile_enum_section(ctx
, "Manufacturer", &num_manufacturers
, &manufacturers
, &values
);
340 if (!NT_STATUS_IS_OK(status
)) {
344 for (i
= 0; i
< num_manufacturers
; i
++) {
346 const char *models_section_name
;
351 DEBUG(11,("processing manufacturer: %s\n", manufacturers
[i
]));
353 status
= gp_inifile_getstring(ctx
, manufacturers
[i
], &s
);
354 if (!NT_STATUS_IS_OK(status
)) {
358 decorations
= str_list_make_v3(mem_ctx
, s
, ",");
359 if (decorations
== NULL
) {
360 return NT_STATUS_NO_MEMORY
;
363 models_section_name
= decorations
[0];
365 for (j
= 1; decorations
[j
] != NULL
; j
++) {
368 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-models-section
371 const char *decorated_models_section_name
;
372 size_t d
, num_devices
= 0;
373 const char **devices
= NULL
;
374 const char **device_values
= NULL
;
377 decorated_models_section_name
= talloc_asprintf(mem_ctx
, "%s.%s",
380 if (decorated_models_section_name
== NULL
) {
381 return NT_STATUS_NO_MEMORY
;
384 DEBUG(11,("processing decorated models_section_name: %s\n",
385 decorated_models_section_name
));
387 status
= gp_inifile_enum_section(ctx
, decorated_models_section_name
,
388 &num_devices
, &devices
,
390 for (d
= 0; d
< num_devices
; d
++) {
392 DEBUG(11,("processing device: %s\n",
395 s
= talloc_strdup(mem_ctx
, devices
[d
]);
397 return NT_STATUS_NO_MEMORY
;
402 return NT_STATUS_DRIVER_INTERNAL_ERROR
;
408 s
= get_string_unquote(p
);
410 ok
= add_string_to_array(mem_ctx
, s
, pdevices
, pnum_devices
);
412 return NT_STATUS_NO_MEMORY
;
414 ok
= add_string_to_array(mem_ctx
, device_values
[d
], pdevice_values
, &c
);
416 return NT_STATUS_NO_MEMORY
;
425 static NTSTATUS
find_device_in_toc(struct gp_inifile_context
*ctx
,
427 const char *device_description
,
431 size_t d
, num_devices
= 0;
432 const char **devices
= NULL
;
433 const char **device_values
= NULL
;
435 if (device_description
== NULL
) {
436 return NT_STATUS_INVALID_PARAMETER
;
439 status
= enum_devices_in_toc(ctx
, mem_ctx
,
443 if (!NT_STATUS_IS_OK(status
)) {
447 for (d
= 0; d
< num_devices
; d
++) {
449 if (strequal(device_description
, devices
[d
])) {
451 DEBUG(10,("found device_description: %s\n",
452 device_description
));
454 *value
= talloc_strdup(mem_ctx
, device_values
[d
]);
455 if (*value
== NULL
) {
456 return NT_STATUS_NO_MEMORY
;
458 DEBUGADD(10,("and returned: %s\n", *value
));
464 return NT_STATUS_DRIVER_INTERNAL_ERROR
;
468 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-copyfiles-directive
471 static NTSTATUS
process_driver_section_copyfiles(struct gp_inifile_context
*ctx
,
473 const char *driver_section
,
474 struct spoolss_AddDriverInfo8
*r
)
477 size_t i
, num_keys
= 0;
479 const char **keys
= NULL
;
480 const char **values
= NULL
;
484 key
= talloc_asprintf(mem_ctx
, "%s:%s", driver_section
, "CopyFiles");
486 return NT_STATUS_NO_MEMORY
;
489 DEBUG(10,("Checking for CopyFiles entry in %s\n", driver_section
));
491 status
= gp_inifile_getstring(ctx
, key
, &s
);
492 if (!NT_STATUS_IS_OK(status
)) {
496 DEBUG(10,("these are the files to copy: %s\n", s
));
498 while (next_token_talloc(mem_ctx
, &s
, &str
, ",")) {
500 DEBUG(10,("trying section: %s\n", str
));
503 DEBUG(10,("adding dependent driver file: %s\n", str
));
504 status
= add_dependent_driver_file(mem_ctx
, str
, &r
->dependent_files
);
505 if (!NT_STATUS_IS_OK(status
)) {
511 status
= gp_inifile_enum_section(ctx
, str
, &num_keys
, &keys
, &values
);
512 if (NT_STATUS_IS_OK(status
)) {
513 for (i
= 0; i
< num_keys
; i
++) {
514 p
= strchr(keys
[i
], ':');
516 return NT_STATUS_INVALID_PARAMETER
;
521 DEBUG(10,("adding dependent driver file: %s\n", p
));
523 status
= add_dependent_driver_file(mem_ctx
, p
, &r
->dependent_files
);
524 if (!NT_STATUS_IS_OK(status
)) {
536 #define process_driver_section_val(_ctx, _mem_ctx, _section, _r, _key, _element) \
539 const char *__key, *_s; \
540 __key = talloc_asprintf(_mem_ctx, "%s:%s", _section, _key); \
541 NT_STATUS_HAVE_NO_MEMORY(__key); \
542 _status = gp_inifile_getstring(_ctx, __key, &_s); \
543 if (NT_STATUS_IS_OK(_status)) { \
544 (_r)->_element = talloc_strdup(mem_ctx, _s); \
545 NT_STATUS_HAVE_NO_MEMORY((_r)->_element); \
549 static NTSTATUS
process_driver_section_colorprofiles(struct gp_inifile_context
*ctx
,
552 struct spoolss_AddDriverInfo8
*r
)
557 key
= talloc_asprintf(mem_ctx
, "%s:%s", section
, "ColorProfiles");
559 return NT_STATUS_NO_MEMORY
;
562 status
= gp_inifile_getstring_ext(ctx
, key
, &s
);
563 if (NT_STATUS_IS_OK(status
)) {
565 status
= add_string_to_spoolss_array(mem_ctx
, s
, &r
->color_profiles
);
566 if (!NT_STATUS_IS_OK(status
)) {
574 static NTSTATUS
process_driver_section_printprocessor(struct gp_inifile_context
*ctx
,
577 struct spoolss_AddDriverInfo8
*r
)
583 key
= talloc_asprintf(mem_ctx
, "%s:%s", section
, "PrintProcessor");
585 return NT_STATUS_NO_MEMORY
;
588 status
= gp_inifile_getstring_ext(ctx
, key
, &s
);
589 if (NT_STATUS_IS_OK(status
)) {
590 s
= get_string_unquote(s
);
594 return NT_STATUS_INVALID_PARAMETER
;
597 r
->print_processor
= talloc_strdup(mem_ctx
, s
);
598 if (r
->print_processor
== NULL
) {
599 return NT_STATUS_NO_MEMORY
;
606 static NTSTATUS
process_driver_section_data_section(struct gp_inifile_context
*ctx
,
609 struct spoolss_AddDriverInfo8
*r
)
615 key
= talloc_asprintf(mem_ctx
, "%s:%s", section
, "DataSection");
617 return NT_STATUS_NO_MEMORY
;
620 status
= gp_inifile_getstring(ctx
, key
, &s
);
621 if (NT_STATUS_IS_OK(status
)) {
622 process_driver_section_val(ctx
, mem_ctx
, s
, r
,
623 "DriverFile", driver_path
);
624 process_driver_section_val(ctx
, mem_ctx
, s
, r
,
625 "HelpFile", help_file
);
626 process_driver_section_val(ctx
, mem_ctx
, s
, r
,
627 "DataFile", data_file
);
628 process_driver_section_val(ctx
, mem_ctx
, s
, r
,
629 "ConfigFile", config_file
);
636 static NTSTATUS
process_one_core_driver_section(struct gp_inifile_context
*core_ctx
,
638 const char *driver_section
,
639 struct spoolss_AddDriverInfo8
*r
)
642 size_t i
, num_keys
= 0;
643 const char **keys
= NULL
;
644 const char **values
= NULL
;
646 DEBUG(10,("CoreDriverSection is: %s\n", driver_section
));
648 status
= gp_inifile_enum_section(core_ctx
, driver_section
, &num_keys
, &keys
, &values
);
649 if (!NT_STATUS_IS_OK(status
)) {
653 for (i
= 0; i
< num_keys
; i
++) {
655 status
= process_driver_section_copyfiles(core_ctx
, mem_ctx
, driver_section
, r
);
656 if (!NT_STATUS_IS_OK(status
)) {
660 process_driver_section_val(core_ctx
, mem_ctx
, driver_section
, r
,
661 "DriverFile", driver_path
);
662 process_driver_section_val(core_ctx
, mem_ctx
, driver_section
, r
,
663 "HelpFile", help_file
);
664 process_driver_section_val(core_ctx
, mem_ctx
, driver_section
, r
,
665 "ConfigFile", config_file
);
667 status
= process_driver_section_colorprofiles(core_ctx
, mem_ctx
, driver_section
, r
);
668 if (!NT_STATUS_IS_OK(status
)) {
680 * 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"
682 static NTSTATUS
process_core_driver_sections(struct gp_inifile_context
*core_ctx
,
685 struct spoolss_AddDriverInfo8
*r
)
692 list
= str_list_make_v3(mem_ctx
, value
, ",");
694 return NT_STATUS_NO_MEMORY
;
697 for (i
= 0; list
[i
] != NULL
; i
++) {
701 /* FIXME: do we have to validate the core driver guid ? */
703 p
= strchr(list
[i
], ',');
709 DEBUG(10,("CoreDriverSections we have to process: %s\n", p
));
711 array
= str_list_make_v3(mem_ctx
, p
, ",");
713 return NT_STATUS_NO_MEMORY
;
716 for (a
= 0; array
[a
] != NULL
; a
++) {
718 if (core_ctx
== NULL
) {
719 DEBUG(0,("Need to process CoreDriverSections but "
720 "have no Core Driver Context!\n"));
721 return NT_STATUS_DRIVER_INTERNAL_ERROR
;
724 status
= process_one_core_driver_section(core_ctx
, mem_ctx
, array
[a
], r
);
725 if (!NT_STATUS_IS_OK(status
)) {
735 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-ddinstall-section
737 static NTSTATUS
find_driver_files(struct gp_inifile_context
*ctx
,
738 struct gp_inifile_context
*core_ctx
,
740 const char *driver_name
,
741 struct spoolss_AddDriverInfo8
*r
)
747 char *install_section_name
;
751 status
= find_device_in_toc(ctx
, mem_ctx
, driver_name
, &value
);
752 if (!NT_STATUS_IS_OK(status
)) {
756 r
->driver_name
= talloc_strdup(mem_ctx
, driver_name
);
757 if (r
->driver_name
== NULL
) {
758 return NT_STATUS_NO_MEMORY
;
761 ok
= next_token_talloc(mem_ctx
, &value
, &install_section_name
, ",");
763 return NT_STATUS_INVALID_PARAMETER
;
766 DEBUG(10,("driver_name: %s, value: %s, install_section_name: %s\n",
767 driver_name
, value
, install_section_name
));
769 /* Hardware Id is optional */
770 ok
= next_token_talloc(mem_ctx
, &value
, &hw_id
, ",");
772 r
->hardware_id
= hw_id
;
775 status
= process_driver_section_copyfiles(ctx
, mem_ctx
, install_section_name
, r
);
776 if (!NT_STATUS_IS_OK(status
)) {
780 process_driver_section_val(ctx
, mem_ctx
, install_section_name
, r
,
781 "DriverFile", driver_path
);
782 process_driver_section_val(ctx
, mem_ctx
, install_section_name
, r
,
783 "HelpFile", help_file
);
784 process_driver_section_val(ctx
, mem_ctx
, install_section_name
, r
,
785 "DataFile", data_file
);
786 process_driver_section_val(ctx
, mem_ctx
, install_section_name
, r
,
787 "ConfigFile", config_file
);
789 status
= process_driver_section_printprocessor(ctx
, mem_ctx
, install_section_name
, r
);
790 if (!NT_STATUS_IS_OK(status
)) {
794 status
= process_driver_section_data_section(ctx
, mem_ctx
, install_section_name
, r
);
795 if (!NT_STATUS_IS_OK(status
)) {
799 key
= talloc_asprintf(mem_ctx
, "%s:%s", install_section_name
, "CoreDriverSections");
801 return NT_STATUS_NO_MEMORY
;
804 status
= gp_inifile_getstring(ctx
, key
, &s
);
805 if (NT_STATUS_IS_OK(status
)) {
807 DEBUG(10,("found CoreDriverSections: %s\n", s
));
809 status
= process_core_driver_sections(core_ctx
, mem_ctx
, s
, r
);
810 if (!NT_STATUS_IS_OK(status
)) {
819 struct gp_inifile_context
*ctx
;
820 struct gp_inifile_context
*core_ctx
;
823 static NTSTATUS
init_inf_context(TALLOC_CTX
*mem_ctx
,
824 const char *inf_filename
,
825 const char *core_filename
,
826 struct inf_context
**_inf_ctx
)
829 struct gp_inifile_context
*ctx
;
830 struct gp_inifile_context
*core_ctx
= NULL
;
831 struct inf_context
*inf_ctx
;
833 inf_ctx
= talloc_zero(mem_ctx
, struct inf_context
);
834 if (inf_ctx
== NULL
) {
835 return NT_STATUS_NO_MEMORY
;
838 status
= gp_inifile_init_context_direct(mem_ctx
,
841 if (!NT_STATUS_IS_OK(status
)) {
842 DEBUG(10,("init_inf_context: failed to load %s\n", inf_filename
));
846 if (ctx
->generated_filename
!= NULL
) {
847 unlink(ctx
->generated_filename
);
850 if (core_filename
!= NULL
) {
851 status
= gp_inifile_init_context_direct(mem_ctx
,
854 if (!NT_STATUS_IS_OK(status
)) {
855 DEBUG(10,("init_inf_context: failed to load %s\n", core_filename
));
859 if (core_ctx
->generated_filename
!= NULL
) {
860 unlink(core_ctx
->generated_filename
);
865 inf_ctx
->core_ctx
= core_ctx
;
872 static NTSTATUS
process_driver_driverver(struct gp_inifile_context
*ctx
,
873 struct spoolss_AddDriverInfo8
*r
)
881 status
= gp_inifile_getstring(ctx
, "Version:DriverVer", &s
);
882 if (!NT_STATUS_IS_OK(status
)) {
886 str
= talloc_strdup(ctx
, s
);
888 return NT_STATUS_NO_MEMORY
;
891 p
= strchr(str
, ',');
897 ok
= spoolss_timestr_to_NTTIME(str
, &r
->driver_date
);
899 return NT_STATUS_INVALID_PARAMETER
;
902 ok
= spoolss_driver_version_to_qword(p
, &r
->driver_version
);
904 return NT_STATUS_INVALID_PARAMETER
;
911 * Parse a SourceDisksNames section,
912 * https://msdn.microsoft.com/de-de/windows/hardware/drivers/install/inf-sourcedisksnames-section?f=255&MSPPError=-2147217396
914 static NTSTATUS
process_source_disk_name(struct gp_inifile_context
*ctx
,
916 const char *short_environment
,
917 const char **source_disk_name
)
922 size_t i
, num_keys
= 0;
923 const char **keys
= NULL
;
924 const char **values
= NULL
;
926 key
= talloc_asprintf(mem_ctx
, "SourceDisksNames.%s", short_environment
);
928 return NT_STATUS_NO_MEMORY
;
931 status
= gp_inifile_enum_section(ctx
, key
, &num_keys
, &keys
, &values
);
932 if (!NT_STATUS_IS_OK(status
)) {
936 if (keys
== NULL
&& values
== NULL
) {
937 key
= "SourceDisksNames";
939 status
= gp_inifile_enum_section(ctx
, key
, &num_keys
, &keys
, &values
);
940 if (!NT_STATUS_IS_OK(status
)) {
945 for (i
= 0; i
< num_keys
; i
++) {
948 * 1 = %Disk1%,,,"Amd64"
949 * diskid = disk-description[,[tag-or-cab-file],[unused],[path],[flags][,tag-file]]
951 char *disk_description
, *tag_or_cab_file
, *unused
, *path
;
953 ok
= next_token_no_ltrim_talloc(mem_ctx
, &values
[i
], &disk_description
, ",");
958 ok
= next_token_no_ltrim_talloc(mem_ctx
, &values
[i
], &tag_or_cab_file
, ",");
963 ok
= next_token_no_ltrim_talloc(mem_ctx
, &values
[i
], &unused
, ",");
968 ok
= next_token_no_ltrim_talloc(mem_ctx
, &values
[i
], &path
, ",");
973 *source_disk_name
= path
;
978 return NT_STATUS_NOT_FOUND
;
981 static NTSTATUS
setup_driver_by_name(TALLOC_CTX
*mem_ctx
,
982 struct inf_context
*inf_ctx
,
983 const char *filename
,
984 const char *environment
,
985 const char *driver_name
,
986 struct spoolss_AddDriverInfo8
*r
,
987 const char **source_disk_name
)
990 struct gp_inifile_context
*ctx
= inf_ctx
->ctx
;
991 struct gp_inifile_context
*core_ctx
= inf_ctx
->core_ctx
;
994 const char *short_environment
;
997 short_environment
= spoolss_get_short_filesys_environment(environment
);
998 if (short_environment
== NULL
) {
999 return NT_STATUS_INVALID_PARAMETER
;
1002 status
= find_driver_files(ctx
, core_ctx
, mem_ctx
, driver_name
, r
);
1003 if (!NT_STATUS_IS_OK(status
)) {
1007 status
= process_source_disk_name(ctx
, mem_ctx
,
1010 if (!NT_STATUS_IS_OK(status
)) {
1014 r
->inf_path
= talloc_strdup(mem_ctx
, filename
);
1015 if (r
->inf_path
== NULL
) {
1016 return NT_STATUS_NO_MEMORY
;
1019 r
->architecture
= talloc_strdup(mem_ctx
, environment
);
1020 if (r
->architecture
== NULL
) {
1021 return NT_STATUS_NO_MEMORY
;
1024 if (r
->print_processor
== NULL
) {
1025 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
1026 if (r
->print_processor
== NULL
) {
1027 return NT_STATUS_NO_MEMORY
;
1031 status
= gp_inifile_getstring_ext(ctx
, "Version:Class", &s
);
1032 if (NT_STATUS_IS_OK(status
)) {
1033 if (strequal(s
, "Printer")) {
1034 r
->printer_driver_attributes
|= PRINTER_DRIVER_CLASS
;
1038 status
= gp_inifile_getstring(ctx
, "Version:Signature", &s
);
1039 if (!NT_STATUS_IS_OK(status
)) {
1042 if (!strequal(s
, "\"$Windows NT$\"")) {
1043 return NT_STATUS_INVALID_SIGNATURE
;
1046 r
->version
= SPOOLSS_DRIVER_VERSION_200X
;
1047 status
= gp_inifile_getstring(ctx
, "Version:ClassVer", &s
);
1048 if (NT_STATUS_IS_OK(status
)) {
1049 int cmp
= strncasecmp_m(s
, "4.0", 3);
1051 r
->version
= SPOOLSS_DRIVER_VERSION_2012
;
1053 if (strequal(s
, "3.0")) {
1054 r
->version
= SPOOLSS_DRIVER_VERSION_200X
;
1058 status
= gp_inifile_getstring_ext(ctx
, "Version:Provider", &s
);
1059 if (NT_STATUS_IS_OK(status
)) {
1061 r
->provider
= talloc_strdup(mem_ctx
, s
);
1062 if (r
->provider
== NULL
) {
1063 return NT_STATUS_NO_MEMORY
;
1068 status
= process_driver_driverver(ctx
, r
);
1069 if (!NT_STATUS_IS_OK(status
)) {
1073 r
->printer_driver_attributes
&= ~PRINTER_DRIVER_SANDBOX_ENABLED
;
1075 status
= gp_inifile_getstring(ctx
, "Version:DriverIsolation", &s
);
1076 if (NT_STATUS_IS_OK(status
)) {
1077 int cmp
= strncasecmp_m(s
, "2", 1);
1079 r
->printer_driver_attributes
|= PRINTER_DRIVER_SANDBOX_ENABLED
;
1081 cmp
= strncasecmp_m(s
, "0", 1);
1083 r
->printer_driver_attributes
&= ~PRINTER_DRIVER_SANDBOX_ENABLED
;
1087 status
= find_manufacturer_name(ctx
, mem_ctx
, "Manufacturer", &r
->manufacturer_name
);
1088 if (!NT_STATUS_IS_OK(status
)) {
1092 status
= find_manufacturer_url(ctx
, mem_ctx
, "OEM URLS", r
->manufacturer_name
, &r
->manufacturer_url
);
1093 if (!NT_STATUS_IS_OK(status
)) {
1097 status
= gp_inifile_getbool(ctx
, "PrinterPackageInstallation:PackageAware", &ok
);
1098 if (NT_STATUS_IS_OK(status
)) {
1100 r
->printer_driver_attributes
|= PRINTER_DRIVER_PACKAGE_AWARE
;
1104 key
= talloc_asprintf(mem_ctx
, "%s.%s:%s",
1105 "PrinterPackageInstallation", short_environment
, "PackageAware");
1107 return NT_STATUS_NO_MEMORY
;
1110 status
= gp_inifile_getbool(ctx
, key
, &ok
);
1111 if (NT_STATUS_IS_OK(status
)) {
1113 r
->printer_driver_attributes
|= PRINTER_DRIVER_PACKAGE_AWARE
;
1117 key
= talloc_asprintf(mem_ctx
, "%s.%s:%s",
1118 "PrinterPackageInstallation", short_environment
, "CoreDriverDependencies");
1120 return NT_STATUS_NO_MEMORY
;
1123 status
= gp_inifile_getstring(ctx
, key
, &s
);
1124 if (NT_STATUS_IS_OK(status
)) {
1126 r
->core_driver_dependencies
= talloc_zero(mem_ctx
, struct spoolss_StringArray
);
1127 if (r
->core_driver_dependencies
== NULL
) {
1128 return NT_STATUS_NO_MEMORY
;
1131 list
= str_list_make_v3(r
->core_driver_dependencies
, s
, ",");
1133 return NT_STATUS_NO_MEMORY
;
1135 r
->core_driver_dependencies
->string
= const_str_list(list
);
1138 key
= talloc_asprintf(mem_ctx
, "%s.%s:%s",
1139 "PrinterPackageInstallation", short_environment
, "InboxVersionRequired");
1141 return NT_STATUS_NO_MEMORY
;
1144 status
= gp_inifile_getstring(ctx
, key
, &s
);
1145 if (NT_STATUS_IS_OK(status
)) {
1146 if (strequal(s
, "UseDriverVer")) {
1147 r
->min_inbox_driver_ver_date
= r
->driver_date
;
1148 r
->min_inbox_driver_ver_version
= r
->driver_version
;
1152 return NT_STATUS_OK
;
1155 /****************************************************************
1156 parse the a printer inf file
1157 ****************************************************************/
1159 NTSTATUS
driver_inf_parse(TALLOC_CTX
*mem_ctx
,
1160 const char *core_driver_inf
,
1161 const char *filename
,
1162 const char *environment
,
1163 const char *driver_name
,
1164 struct spoolss_AddDriverInfo8
*r
,
1165 const char **source_disk_name
)
1168 struct inf_context
*inf_ctx
;
1170 if (!filename
|| !environment
) {
1171 return NT_STATUS_INVALID_PARAMETER
;
1174 status
= init_inf_context(mem_ctx
,
1178 if (!NT_STATUS_IS_OK(status
)) {
1182 status
= setup_driver_by_name(mem_ctx
, inf_ctx
,
1188 if (!NT_STATUS_IS_OK(status
)) {
1192 return NT_STATUS_OK
;
1195 NTSTATUS
driver_inf_list(TALLOC_CTX
*mem_ctx
,
1196 const char *core_driver_inf
,
1197 const char *filename
,
1198 const char *environment
,
1200 struct spoolss_AddDriverInfo8
**_r
)
1203 const char *short_environment
;
1204 size_t d
, num_devices
= 0;
1205 const char **devices
= NULL
;
1206 const char **device_values
= NULL
;
1207 struct inf_context
*inf_ctx
;
1209 if (!filename
|| !environment
) {
1210 return NT_STATUS_INVALID_PARAMETER
;
1213 short_environment
= spoolss_get_short_filesys_environment(environment
);
1214 if (short_environment
== NULL
) {
1215 return NT_STATUS_INVALID_PARAMETER
;
1218 status
= init_inf_context(mem_ctx
,
1222 if (!NT_STATUS_IS_OK(status
)) {
1226 status
= enum_devices_in_toc(inf_ctx
->ctx
, mem_ctx
,
1230 if (!NT_STATUS_IS_OK(status
)) {
1234 for (d
= 0; d
< num_devices
; d
++) {
1236 struct spoolss_AddDriverInfo8 r
;
1237 const char *source_disk_name
;
1241 status
= setup_driver_by_name(mem_ctx
, inf_ctx
, filename
,
1242 environment
, devices
[d
], &r
,
1244 if (!NT_STATUS_IS_OK(status
)) {
1248 ADD_TO_ARRAY(mem_ctx
, struct spoolss_AddDriverInfo8
, r
, _r
, count
);
1251 return NT_STATUS_OK
;