Solución: Imprimir desde ArchLinux a impresoras compartidas de Windows 10

PC Windows: 192.168.0.203 (hostname LIVING, workgroup WORKGROUP, usuario living\aligra) Impresoras: Brother HL-L1222 Printer (USB002) y HP PSC 1400 series (USB001) Origen: ArchLinux (cliente SMB/CUPS) Resultado: ✅ Ambas impresoras imprimen desde Linux.


TL;DR — Las claves que lo hicieron funcionar

  1. Ambas impresoras son “host-based” (GDI): NO aceptan texto plano. Hay que renderizar en Linux con el driver correcto antes de enviar. Texto crudo → 0 páginas, sin ruido.
  2. La HP daba un falso “cartucho de tinta vacío”: lo disparaba el soporte bidireccional (BIDI) de Windows, que consultaba el estado de la impresora y detenía el job RAW. Solución: desactivar BIDI en la impresora HP.
  3. Se necesita una cuenta autenticada para imprimir (el anónimo solo puede listar shares, no enviar trabajos).

Cambios ejecutados EN WINDOWS

1. Impresoras compartidas

Ya estaban compartidas. Verificado el share y puerto:

  • Brother HL-L1222 Printer → puerto USB002 (default)
  • HP PSC 1400 series → puerto USB001

2. Usuario local para autenticación

net user arctest P@ssw0rd123 /add

Oculto del login (que no aparezca en la pantalla de inicio, dejando solo 1 usuario visible):

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList
    arctest = 0   (DWORD)

¿Era necesario? VERIFICADO: SÍ.

  • Listar shares sin credenciales sí funciona → smbclient -N -L //192.168.0.203 lista las impresoras.
  • Imprimir sin credenciales NO → smbspool anónimo devuelve NT_STATUS_ACCESS_DENIED. Windows exige un usuario autenticado con permiso Print para enviar un trabajo (se atribuye a un usuario). El anónimo solo puede ver los recursos, no imprimir. No borrar arctest. (Nota: se pudo haber reutilizado living\aligra en vez de crear uno nuevo, pero una cuenta hacía falta.)

3. Permisos de impresión (ACL) en ambas impresoras

Se concedió el permiso Print a arctest (y Everyone/AUTHENTICATED USERS/BUILTIN ADMIN) usando la API Win32 SetPrinter vía P/Invoke (PRINTER_ALL_ACCESS = 0x000F000C), ya que PowerShell no tiene cmdlet directo para la ACL de impresora.

4. Política de seguridad de red (modelo clásico)

Valor Ruta Cambio
ForceGuest HKLM\SYSTEM\CurrentControlSet\Control\Lsa → 0 (modelo clásico)
RestrictAnonymous HKLM\SYSTEM\CurrentControlSet\Control\Lsa → 0
EveryoneIncludesAnonymous ...\Control\Lsa\MSV1_0 → 1
RestrictNullSessAccess HKLM\SYSTEM\CurrentControlSet\Control\Lsa → 0

5. Print processor de la HP

Revirtió al original hpzpplhn y luego se cambió a winprint. No fue la solución, pero se dejó en winprint.

6. ★ LA CLAVE DE LA HP: desactivar el soporte bidireccional (BIDI) ★

Con BIDI activo, Windows consultaba el estado por USB, leía un estado falso de “tinta vacío” y detenía el job RAW a mitad (la HP hacía ruido y se traba sin imprimir). Se quitó el bit PRINTER_ATTRIBUTE_ENABLE_BIDI (0x800):

HKLM\SYSTEM\CurrentControlSet\Control\Print\Printers\HP PSC 1400 series
    Attributes:  0xA08  →  0x208
net stop spooler /y
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Print\Printers\HP PSC 1400 series" `
    -Name Attributes -Value 0x208 -Type DWord
net start spooler

7. Vaciado de la cola (spool) — repetidas veces

Para limpiar trabajos atascados (“Retained”, “documento remoto de bajo nivel”):

Get-Printer | ForEach-Object { Get-PrintJob -PrinterName $_.Name -EA SilentlyContinue | Remove-PrintJob }
net stop spooler /y
Remove-Item "C:\Windows\System32\spool\PRINTERS\*" -Force -Recurse -EA SilentlyContinue
net start spooler

Cambios ejecutados EN LINUX (necesarios para el resultado)

Paquetes instalados

cups, cups-filters, gutenprint, hplip, ghostscript, a2ps, y desde AUR brother-hll1222.

Colas de CUPS creadas (renderizan en Linux y mandan por SMB)

Cola CUPS Driver (render) URI destino
Brother1222 brother-hll1222 (oficial Brother) smb://arctest:P@ssw0rd123@192.168.0.203/Brother HL-L1222 Printer
HP1400 hplip → hp-psc_1400_series.ppd smb://arctest:P@ssw0rd123@192.168.0.203/HP PSC 1400 series

Backend: /usr/lib/cups/backend/smb → smbspool (libsmbclient), envía el trabajo como RAW al share.

Impresión

lp -d Brother1222 documento.pdf
lp -d HP1400 documento.pdf

Nota sobre color

La HP imprime correctamente texto y páginas en negro desde Linux. Las páginas a color salen en negro (probablemente el cartucho de color no está instalado/activo en la impresora). No bloquea la impresión; el objetivo (imprimir desde Linux) se cumple para documentos en negro.


Diagnóstico: por qué fallaba (lo que se aprendió)

Síntoma Causa real
Trabajo llega como “documento remoto de bajo nivel”, 0 páginas, sin ruido Impresora GDI/host-based no entiende texto crudo. Necesita driver que la renderice.
Brother no imprimía con texto crudo (410 bytes, 0 páginas) Faltaba el driver; con brother-hll1222 (oficial) sí imprimió.
HP hacía ruido y se traba, con falso “cartucho de tinta vacío” BIDI activo → Windows leía estado falso y detenía el job RAW. Se desactivó BIDI.
smbclient print → NT_STATUS_ACCESS_DENIED smbclient no usa el mismo mecanismo; smbspool (libsmbclient) sí funciona con credenciales.
texttopdf crasheaba (signal 11) en CUPS Se enviaba text/plain; se envía PDF para evitar ese filtro.

Confirmado: el “cartucho de tinta vacío” era falso — la HP imprimía bien desde Windows (Out-Printer); el job RAW desde Linux fallaba hasta desactivar BIDI.


Archivos / scripts dejados en Windows

En C:\Users\Public\: hp.ps1, hpfix.ps1, hpdiag.ps1, state.ps1, dump.ps1, sec.ps1, setacl2.ps1, share.ps1. (Diagnósticos; pueden borrarse.)

Nota sobre “imprimir desde Linux”

El trabajo se origina y renderiza en Linux y solo usa Windows como spooler/interfaz con la impresora USB. El uso de PowerShell/Windows fue solo para habilitar el acceso (usuario, ACLs, BIDI, política), no para ejecutar la impresión.

¿Se puede imprimir SIN usuario? No — probado y descartado

Se probó exhaustivamente (con ACL de la HP en estado original: Todos/Autenticados/ANONYMOUS LOGON con permiso Print 0x00020008):

  • Anónimo (smbclient -N, sin credenciales) → falla.
  • Invitado/Guest, con y sin contraseña → el trabajo llega a la cola (evento 800) pero Windows lo borra solo al instante (evento 310, y el .SPL/.SHD nunca se escribe: error 0x2).
  • ACL completa para Todos/anónimos (0x000F004C, temporal) → mismos resultados.
  • Usuario normal recién creado (testprint, grupo Usuarios) → también denegado en esos tests.

Conclusión: hace falta una cuenta de usuario local con contraseña (la ACL no es el limitante; el spooler rechaza/borra trabajos de cuentas invitadas/anónimas en este equipo). La cuenta usada es arctest (oculta en el login vía SpecialAccounts\UserList), y es la que documentan los tutoriales.

Cambios temporales de prueba (ya revertidos)

  • Se creó el usuario testprint → borrado.
  • Se puso temporalmente la ACL de la HP en completo para Todos/Autenticados/ANONYMOUS → restaurada byte a byte desde backup, spooler reiniciado; verificado con arctest (evento 307, imprimió).
  • Invitado quedó con la contraseña P@ssw0rd123 (antes estaba en blanco). Si se quiere volver en blanco: en la PC de Windows, net user Invitado * y dejar vacía dos veces.