customer investigated and reported an issue with printer drivers which could indeed lead to several issues related to Windows printing: =============================================================== Hello, while investigating unexplained printer driver problems yesterday I noticed an interesting malfunction in Samba that could have been responsible for all kinds of printing problems for ages. The scenario: A Windows printer driver, e.g. from Lexmark, is uploaded to the Samba server via the mechanisms integrated in Windows and ends up in the "print$" share. A few years later it is necessary to upload a newer version of the driver, but the manufacturer has decided to specify the individual driver files in the INF file now completely in Uppercase, which is no problem in the Windows world, because "driver.dll" and "DRIVER.DLL" reference the same file there and cannot both exist in the same folder. But if the new driver is uploaded to the Samba server, the new files will not overwrite the old ones, but suddenly there is a "driver.dll" and a "DRIVER.DLL" in the print$ share. This seems to cause an undefined behavior when Windows accesses the file later - sometimes the old file is loaded, sometimes the new one, which leads to crashes of the printer driver due to version mismatches. Even if the driver is deleted later, the "duplicate" files remain in the share and become orphaned. I suppose the problem has its origin in the fact that Windows does not copy the driver files directly into the destination folder "\print$\$Architecture\3\" when uploading the driver files, but into a randomly generated folder "\print$\$Architecture\{$RANDOMGUID}\". It then calls a specific function call on the server, which causes Samba to move the files from the temporary folder to the "\3" folder on the server side. Samba uses the target filenames exactly as they appear in the INF file (I checked this by modifying the INF file) - and probably doesn't care if there is already a file with the same name in the target folder. Another interesting fact is that Samba apparently compares the versions of new and existing driver files on the server side, but is correctly case-insensitive: If a "driver.dll" in version "2.0.0.0" already exists and the client tries to upload a "DRIVER.DLL" in version "1.0.0.0", the latter will not be moved to the destination folder. So the resulting files in the "\3" folder also depend on the order in which you upload your printer drivers. I had already tested whether it helps to work with the Samba parameters "case sensitive", "default case", "preserve case", etc. for the "print$" share, but these parameters only affect the files that Windows initially copies into the temporary folder. When finally moving them to their destination, Samba always uses exactly the file names from the INF file, as mentioned before. =======================================================================
From smb.conf man page: case sensitive = yes/no/auto controls whether filenames are case sensitive. If they aren't, Samba must do a filename search and match on passed names. The default setting of auto allows clients that support case sensitive filenames (Linux CIFSVFS and smbclient 3.0.5 and above currently) to tell the Samba server on a per-packet basis that they wish to access the file system in a case-sensitive manner (to support UNIX case sensitive semantics). No Windows or DOS system supports case-sensitive filename so setting this option to auto is that same as setting it to no for them. Default auto. On my UCS Systems, "case sensitive" is not defined or is set to "No" for a few shares. From my understanding, the description of this bug conflicts with the behaviour documented by the samba team. Was the configuration of the system where this bug occured the default configuration? Can this bug be reproduced? Remark: Windows 10 can be configured to be case sensitive for more than 2 years now, see for example https://www.windowscentral.com/how-enable-ntfs-treat-folders-case-sensitive-windows-10 - so this problem is going to be generic, not samba only.
First, the smb.con man pages states: "No Windows or DOS system supports case-sensitive filename so setting this option to auto is that same as setting it to no for them. Default auto." So there is no need to change this flag for Samba/UCS as the customer mostly uses Windows client machines and tested as described different settings and none changed the behavior. Second, regarding the provided link. This applies only if the optional LinuxSubSystem feature on Windows is enabled. Which is usually not. And if it is enabled you are allowed to change the behavior for local paths but not for connected shares and especially not for a share named "print$". Additionally (from https://devblogs.microsoft.com/commandline/per-directory-case-sensitivity-and-wsl/): "Note that the per-directory case sensitivity flag is not inherited; directories created in a case sensitive directory are not automatically case sensitive themselves. You must explicitly mark each directory as case sensitive. Changing the flag requires “write attributes” permission to the directory." So there is no way to make windows taking care of cases while installing printer drivers. This is because the destination folder is created on the fly and therefore doe not inherit an theoretically set "case sensitive" flag. Nevermind, the behavior is as described. There will be multiple files in the directory with different cases and it can not be told which file Windows takes to install the printer. Leading in different driver versions causing issues.
Thank you for the additional information. Can you also answer my questions? > Was the configuration of the system where this bug occured the default > configuration? > > Can this bug be reproduced?
We would need the exact driver and vendor to reproduce.
Comment from customer: ==================== Laden Sie mal den „HP Universal Treiber“ und den „Lexmark Universal Treiber“ auf einen Samba-Server hoch. Beide enthalten ein paar gemeinsame (offenbar von Windows geborgte) DLLs, u.a. die „unidrv.dll“. Bei HP wird sie klein geschrieben, bei Lexmark groß… ==================== Upload the "HP Universal Driver" and the "Lexmark Universal Driver" to a Samba server. Both contain a few common DLLs (apparently borrowed from Windows), including the "unidrv.dll". At HP it is written in lower case, at Lexmark it is written in capital letters... ==================== Both drivers attached.
Created attachment 10501 [details] Lexmark Driver
Created attachment 10502 [details] HP Driver
Am I right that a workround once this ugly problem has been identified exists?
I am not aware of a workaround. What should it be?
Maybe we can experiment with "preserve case = no" for the print$ share.
Samba had case issues in the print$ share directories, maybe we can learn something from that, e.g. https://bugzilla.samba.org/show_bug.cgi?id=6669
The problem can most likely not be mitigated with Samba's case sensitivity options. As soon as Samba has decided to move a driver file from the temporary location to the final location in the print$ share, it uses the exact file name as specified in the .inf file. If that happens to be "driver.dll" and "DRIVER.DLL" already exists there, both files will remain, causing trouble.
(In reply to Christian Völker from comment #11) > I am not aware of a workaround. What should it be? my understand was that there is a way to correct upper and lower case following the .ini file. Am I wrong?
(In reply to Ingo Steuwer from comment #15) > (In reply to Christian Völker from comment #11) > > I am not aware of a workaround. What should it be? > > my understand was that there is a way to correct upper and lower case > following the .ini file. Am I wrong? No, there is not. Again, the explanation of the issue here: In driver version 1 we have the file written as "PRINTER.DLL". In driver version 2 we have it as "printer.dll" Windows preserves the capitalization but the file system does not differ. So in a Windows-only environment the following will happen: 1. PRINTER.DLL is copied to temp directory 2. Windows moves PRINTER.DLL to final destination 3. new version installed; printer.dll copied to temp dir 4. file printer.dll moved to final dest overwriting the PRINTER.DLL as is appears to be a file system call which does not differ capitalized names. 5. Only a single file "printer.dll" exists and can be accessed by clients. 6. Clients accessing the printer.dll or PrInTeR.DlL PRINTER.dll will get the printer.dll as Windows is not case sensitive. In Samba environment it looks like this (1-3 the same): 1. PRINTER.DLL is copied to temp directory 2. Samba moves PRINTER.DLL to final destination 3. new version installed; printer.dll copied to temp dir 4. file printer.dll moved to final dest - by NOT overwriting the PRINTER.DLL as is handled by the file system as different file 5. Two files in directory named printer.dll and PRINTER.DLL 6. Clients will always get the file with first match in the linux filesystem structure. If "PRINTER.DLL" is "higher" than "printer.dll" it will bring "PRINTER.DLL". If the directory entry of "PRINTER.DLL" is lower it will deliver printer.dll Yes, it might help to modify the .inf file but this would result in a huge work: 1. Identify dll versions on all configured printers and remove outdated ones from final destination manually (is there a way to identify dll file versions?) OR Remove all printers and Re-Install ALL printers from scratch 2. For ALL further updates, manually edit the driver .inf files to match the existing driver file. I would say this is not a suitable workaround...
Thank you for the clarification, that helped a lot. What I'm now wondering: what is the desired behaviour? In both examples (windows behaviour and Samba behaviour) in the end a randomly choosen printer.dll is delivered to the client: either the one from the driver installed latest (Windows) or the one found earlier in the directory structure (Linux). None of them sounds reliable to me. How does Windows ensure that the printer.dll related to the needed driver is delivered to the client?
> In both examples (windows behaviour and Samba behaviour) in the end a > randomly choosen printer.dll is delivered to the client: No, it is not. In Windows there is only a single file. As the previous gets overwritten because Windows does not care about upper or lower. Therefore it is always the latest (and correct) one. > How does Windows ensure that the printer.dll related to the needed driver is > delivered to the client? See above. There is only a single file as the filesystem does not keep multiple ones.
Of course having all printer driver related files in one single directory is not ideal to begin with, especially when multiple printer drivers ship with different versions of the same file (e.g. "unires.dll"). It's an NT4 legacy contruct and probably just assumed that always keeping the newest version of such a shared file doesn't break anything. But in a Samba environment, due to this bug, it's possible that a client gets an older version of a file, that will crash the driver. This specifically happened in our environment with the newest Lexmark Universal driver, because there were 10 years older versions of DLL files from the HP Universal Driver present as well. But I guess that's why Microsoft decided to introduce package-aware drivers and the MS-PAR protocol back in Windows Vista, which I really want to see supported by Samba as soon as possible. That is being worked on, just not with high priority, it seems: https://bugzilla.redhat.com/show_bug.cgi?id=1369515
As Christian wrote: > See above. There is only a single file as the filesystem does not keep multiple ones. We need to find out why Samba decides to store both files instead of just keeping one, regardless what the manpage claims or promises.
(In reply to Arvid Requate from comment #20) > We need to find out why Samba decides to store both files instead of just > keeping one, regardless what the manpage claims or promises. Up to you. I guess it just uses the default Linux file systems calls. And they differ between upper and lower case.
* fixed by overwriting existing driver files regardless of case Package: samba Version: 2:4.16.8-1A~5.0.0.202302241311 Branch: ucs_5.0-0 Scope: errata5.0-3 * samba.yaml * added test Package: ucs-test Version: 10.0.10-13A~5.0.0.202302241333 Branch: ucs_5.0-0 Scope: errata5.0-3
* Functional test: OK [2023/02/27 22:54:48, 5, pid=2030, effective(0, 5000), real(0, 0)] ../../source3/printing/nt_printing.c:499(handle_pe_file) handle_pe_file: PE file [x64/3/unidrv.dll] Version = 00000003:3fab018c (0.3.16299.396) [2023/02/27 22:54:48, 5, pid=2030, effective(0, 5000), real(0, 0)] ../../source3/printing/nt_printing.c:499(handle_pe_file) handle_pe_file: PE file [x64/{E5138BBB-E51F-411A-B690-A2C89F1DE4AD}/unidrv.dll] Version = 00000003:3fab0192 (0.3.16299.402) [2023/02/27 22:54:48, 10, pid=2030, effective(0, 5000), real(0, 0)] ../../source3/smbd/filename.c:1370(unix_convert) unix_convert: Conversion finished [x64/3/unidrv.dll] -> [x64/3/UNIDRV.DLL] [2023/02/27 22:54:48, 10, pid=2030, effective(0, 5000), real(0, 0)] ../../source3/printing/nt_printing.c:1458(move_driver_file_to_download_area) move_driver_file_to_download_area: copying 'x64/{E5138BBB-E51F-411A-B690-A2C89F1DE4AD}/unidrv.dll' to 'x64/3/UNIDRV.DLL' * Test case OK: ucs-test/53_samba-common/39_upload_printer_driver_case * 52a228554b | wording adjustment in advisory
<https://errata.software-univention.de/#/?erratum=5.0x599>