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
;