Sin UI: la interfaz de Windows cambia en cada versión, los cmdlets, el registro y las herramientas de consola son estables. Esta guía se ejecuta entera por PowerShell, comando por comando, en una PC nueva con la impresora recién instalada.

SOLUCION_impresion_Linux_a_Windows.md queda como log técnico (diagnóstico). Esta guía es el procedimiento limpio y reproducible.

Requisitos

  • Windows PowerShell 5.1 (powershell.exe — siempre está en Windows 10/11; no usar pwsh 7, porque Set-LocalUser y Out-Printer solo existen en 5.1).
  • Abrirlo como Administrador: Win + X → Terminal (administrador), o desde una shell normal:
    Start-Process powershell -Verb RunAs
    
  • Comprobar que sos admin (debe dar True):
    ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
        [Security.Principal.WindowsBuiltInRole]::Administrator)
    

Datos de esta guía (cambialos por los tuyos)

Dato Ejemplo (tu red) Dónde verlo
PC host (la de la impresora) IP 192.168.0.203, nombre LIVING ipconfig
Impresora Brother HL-L1222 Printer (o HP PSC 1400 series) Get-Printer
Share (recurso compartido) Brother HL-L1222 Printer net share
Usuario de autenticación arctest Paso 1
Contraseña P@ssw0rd123 la elegís vos
Cliente ArchLinux (CUPS + SMB) Paso 8

Orden de ejecución

  • 1 — Crear el usuario arctest
  • 2 — Red (firewall/perfil) + compartir la impresora
  • 3 — Permiso Imprimir para arctest
  • 4 — Política de seguridad de red (modelo clásico)
  • 5 — (Solo HP) desactivar BIDI
  • 6 — Limpiar spooler, activar eventos, prueba local
  • 7 — ⚠️ Cada PC Windows cliente: borrar la impresora vieja (sin contraseña) y reagregarla CON contraseña
  • 8 — Linux: colas CUPS e imprimir

¿Por qué un usuario? Verificado: sin credenciales se pueden listar los shares, pero no imprimir (el spooler rechaza/borra trabajos de invitados/anónimos). No borrar arctest jamás.


PASO 1 — Usuario de autenticación

# 1) crear el usuario
net user arctest P@ssw0rd123 /add

# 2) contraseña que no caduca (imprescindible: si caduca, Linux queda sin imprimir)
Get-LocalUser -Name arctest | Set-LocalUser -PasswordNeverExpires $true

# 3) ocultarlo de la pantalla de inicio (queda solo tu usuario visible; NO afecta a SMB)
$k = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts"
if (-not (Test-Path "$k\UserList")) { New-Item "$k\UserList" -Force | Out-Null }
New-ItemProperty -Path "$k\UserList" -Name "arctest" -Value 0 -PropertyType DWord -Force | Out-Null

⚠️ Nunca net user arctest /active:no: una cuenta deshabilitada no puede autenticar por SMB.

✅ Verificar:

net user arctest          # debe listar sin errores

PASO 2 — Red + compartir la impresora

# 2.0 red: perfil privado y firewall abierto (si está "Público", nada funciona)
Get-NetConnectionProfile | Set-NetConnectionProfile -NetworkCategory Private
Get-NetFirewallRule | Where-Object { $_.DisplayGroup -match 'impresora|printer|descubrimiento|discovery' } |
    Enable-NetFirewallRule

# 2.1 ver el nombre EXACTO de la impresora y su puerto
Get-Printer | Format-Table Name, PortName, Shared, ShareName

# 2.2 compartir (el share lleva el mismo nombre que la impresora)
Set-Printer -Name "Brother HL-L1222 Printer" -Shared $true -ShareName "Brother HL-L1222 Printer"

✅ Verificar:

net share                                     # debe aparecer el share de la impresora
Get-SmbShare | Format-Table Name, Path

PASO 3 — Permiso “Imprimir” para arctest

PowerShell sí puede (con Set-Printer -PermissionSDDL; hace poco era imposible sin P/Invoke): toma el SDDL actual, mete un ACE de impresión para el SID de arctest y lo vuelve a aplicar.

$pr  = "Brother HL-L1222 Printer"
$sid = (New-Object System.Security.Principal.NTAccount('arctest')).Translate(
         [System.Security.Principal.SecurityIdentifier]).Value
$sddl = (Get-Printer -Name $pr -Full).PermissionSDDL
$ace  = "(A;;SWRC;;;$sid)"      # SW = permiso Print

if ($sddl -notmatch [regex]::Escape($sid)) {
    $nuevo = ([regex]'D:[A-Z]*').Replace($sddl, { param($m) $m.Value + $ace }, 1)  # al inicio del DACL
    Set-Printer -Name $pr -PermissionSDDL $nuevo
    Write-Host "Permiso Print agregado para arctest ($sid)"
} else {
    Write-Host "arctest ya tenía permiso"
}

✅ Verificar:

(Get-Printer -Name $pr -Full).PermissionSDDL   # debe verse el SID de arctest (S-1-5-21-...)

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

4 valores (por defecto existen todos):

Valor Ruta (HKLM) Dato
ForceGuest SYSTEM\CurrentControlSet\Control\Lsa 0 (modelo clásico)
RestrictAnonymous SYSTEM\CurrentControlSet\Control\Lsa 0
EveryoneIncludesAnonymous SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0 1
RestrictNullSessAccess SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0 0
$n = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa"
$m = "$n\MSV1_0"
Set-ItemProperty $n -Name ForceGuest                -Value 0 -Type DWord
Set-ItemProperty $n -Name RestrictAnonymous         -Value 0 -Type DWord
Set-ItemProperty $m -Name EveryoneIncludesAnonymous -Value 1 -Type DWord
Set-ItemProperty $m -Name RestrictNullSessAccess    -Value 0 -Type DWord

(Si alguno faltara: New-ItemProperty -Path $n -Name X -Value 0 -PropertyType DWord -Force.)

El usuario Invitado puede quedar deshabilitado; esta guía no depende de él:

net user Invitado /active:no

✅ Verificar:

Get-ItemProperty $n -Name ForceGuest, RestrictAnonymous | Select-Object ForceGuest, RestrictAnonymous
Get-ItemProperty $m -Name EveryoneIncludesAnonymous, RestrictNullSessAccess |
    Select-Object EveryoneIncludesAnonymous, RestrictNullSessAccess
# deben dar: 0, 0, 1, 0

PASO 5 — (Solo HP) Desactivar BIDI

Con BIDI activo, Windows consulta el estado por USB, lee un falso “cartucho vacío” y detiene el job (la HP hace ruido y se traba). Se limpia el bit 0x800 de Attributes:

$hp = "HKLM:\SYSTEM\CurrentControlSet\Control\Print\Printers\HP PSC 1400 series"
$v  = (Get-ItemProperty $hp).Attributes
Set-ItemProperty $hp -Name Attributes -Value ($v -band 0xFFFFF7FF) -Type DWord
Restart-Service Spooler

✅ Verificar: Get-ItemProperty $hp | Select-Object Attributes → el bit 0x800 apagado (en esa HP el valor quedó 0x208).


PASO 6 — Spooler limpio, eventos y prueba local

# 6.1 vaciar trabajos atascados y reiniciar el servicio
Get-Printer | ForEach-Object { Get-PrintJob -PrinterName $_.Name -ErrorAction SilentlyContinue | Remove-PrintJob }
Stop-Service Spooler -Force
Remove-Item "C:\Windows\System32\spool\PRINTERS\*" -Force -Recurse -ErrorAction SilentlyContinue
Start-Service Spooler

# 6.2 activar el registro de eventos de impresión (para poder verificar con el 307)
wevtutil sl Microsoft-Windows-PrintService/Operational /e:true

# 6.3 imprimir una prueba desde Windows
"Prueba de impresión $(Get-Date)" | Out-Printer -Name "Brother HL-L1222 Printer"

✅ Verificar (evento 307 = “documento impreso”):

Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PrintService/Operational'; Id=307} -MaxEvents 3 |
    Format-List TimeCreated, Message

Si salió la página desde Windows, el host está listo.


PASO 7 — ⚠️ Cada PC Windows cliente: borrar la impresora vieja y reagregarla CON contraseña

El paso que faltaba. Las PCs Windows que ya la tenían agregada la tenían conectada sin contraseña (invitado). Después de los Pasos 1–6 hay que quitar esa conexión vieja, borrar las credenciales guardadas del host y agregarla de nuevo autenticando con arctest. Windows usa la conexión cacheada: si no la borrás, puede seguir fallando o pedir credenciales de forma errática. Ejecutar en cada PC Windows cliente.

7.1 Quitar la impresora vieja

Get-Printer | Where-Object Name -like '\\192.168.0.203*' | Remove-Printer

7.2 Borrar credenciales guardadas del host

cmdkey /list | findstr /i "192.168.0.203"            # ver qué hay guardado
cmdkey /delete:192.168.0.203                         # borrar
cmdkey /delete:LegacyGeneric:target=192.168.0.203    # por si figuraba con ese formato

7.3 Agregarla de nuevo, ahora con usuario y contraseña

# 1) dejar guardadas las credenciales del host ANTES de conectar
cmdkey /add:192.168.0.203 /user:arctest /pass:P@ssw0rd123

# 2) conectar la impresora de red (pide credenciales si el paso anterior no bastó)
Add-Printer -ConnectionName "\\192.168.0.203\Brother HL-L1222 Printer"

# 3) opcional: impresora predeterminada
(New-Object -ComObject WScript.Network).SetDefaultPrinter("\\192.168.0.203\Brother HL-L1222 Printer")

Fallback si da “acceso denegado” (fuerza una sesión SMB autenticada al servidor primero):

net use \\192.168.0.203\print$ /user:arctest P@ssw0rd123 /persistent:no
Add-Printer -ConnectionName "\\192.168.0.203\Brother HL-L1222 Printer"
net use \\192.168.0.203\print$ /delete

7.4 ✅ Verificar

Get-Printer | Where-Object Name -like '\\192.168.0.203*'   # la impresora debe figurar
"Prueba desde cliente $(Get-Date)" | Out-Printer -Name "\\192.168.0.203\Brother HL-L1222 Printer"

Y en el host: evento 307 (comando del Paso 6).


PASO 8 — Linux: colas CUPS e imprimir

(Acá obvio que no hay PowerShell: son comandos de la propia máquina Linux.)

# 8.1 paquetes
sudo pacman -S --needed cups cups-filters ghostscript gutenprint hplip a2ps
sudo systemctl enable --now cups
yay -S brother-hll1222                      # driver oficial Brother (AUR)

# 8.2 encontrar el PPD instalado
find /usr/share/ppd -iname '*1222*'         # HP: find /usr/share/ppd -iname '*psc_1400*'

# 8.3 crear la cola (renderiza en Linux y envía por SMB al host Windows)
sudo lpadmin -p Brother1222 -E -P /usr/share/ppd/Brother/HL1222.ppd \
  -v 'smb://arctest:P@ssw0rd123@192.168.0.203/Brother HL-L1222 Printer'
sudo lpadmin -d Brother1222

# HP equivalente:
# sudo lpadmin -p HP1400 -E -P /usr/share/ppd/hplip/HP/hp-psc_1400_series.ppd \
#   -v 'smb://arctest:P@ssw0rd123@192.168.0.203/HP PSC 1400 series'

# 8.4 imprimir y verificar
lpstat -p -d
lp -d Brother1222 documento.pdf

URI: smb://USUARIO:CONTRASEÑA@IP/NOMBRE_DEL_SHARE. Las de arriba son las que ya funcionaron probadas. Si cambiás la contraseña y falla la autenticación, codificá los caracteres especiales (@ → %40).

✅ Verificar: evento 307 en el host. Si el trabajo aparece y se borra solo (eventos 800 → 310), volver a los Pasos 1, 3 y 7.

Debug si hace falta:

sudo cupsctl LogLevel=debug2
tail -f /var/log/cups/error_log
smbclient -N -L //192.168.0.203                       # listar shares sin credenciales (no imprime)
smbclient -L //192.168.0.203 -U 'arctest%P@ssw0rd123' # con credenciales

Apéndice A — Todo el setup del host en un solo bloque (copiar/pegar)

Ajustá las variables y ejecutá todo junto (Windows PowerShell 5.1 como admin):

# ===== DATOS =====
$Impresora = "Brother HL-L1222 Printer"
$Usuario   = "arctest"
$Pass      = "P@ssw0rd123"

# ===== 1 USUARIO =====
net user $Usuario $Pass /add
Get-LocalUser -Name $Usuario | Set-LocalUser -PasswordNeverExpires $true
$k = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts"
if (-not (Test-Path "$k\UserList")) { New-Item "$k\UserList" -Force | Out-Null }
New-ItemProperty -Path "$k\UserList" -Name $Usuario -Value 0 -PropertyType DWord -Force | Out-Null

# ===== 2 RED + COMPARTIR =====
Get-NetConnectionProfile | Set-NetConnectionProfile -NetworkCategory Private
Get-NetFirewallRule | Where-Object { $_.DisplayGroup -match 'impresora|printer|descubrimiento|discovery' } |
    Enable-NetFirewallRule
Set-Printer -Name $Impresora -Shared $true -ShareName $Impresora

# ===== 3 PERMISO PRINT =====
$sid  = (New-Object System.Security.Principal.NTAccount($Usuario)).Translate(
         [System.Security.Principal.SecurityIdentifier]).Value
$sddl = (Get-Printer -Name $Impresora -Full).PermissionSDDL
$ace  = "(A;;SWRC;;;$sid)"
if ($sddl -notmatch [regex]::Escape($sid)) {
    $nuevo = ([regex]'D:[A-Z]*').Replace($sddl, { param($m) $m.Value + $ace }, 1)
    Set-Printer -Name $Impresora -PermissionSDDL $nuevo
}

# ===== 4 POLÍTICA =====
$n = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa"
$m = "$n\MSV1_0"
Set-ItemProperty $n -Name ForceGuest                -Value 0 -Type DWord
Set-ItemProperty $n -Name RestrictAnonymous         -Value 0 -Type DWord
Set-ItemProperty $m -Name EveryoneIncludesAnonymous -Value 1 -Type DWord
Set-ItemProperty $m -Name RestrictNullSessAccess    -Value 0 -Type DWord

# ===== 5 (SOLO HP) BIDI OFF =====
# $hp = "HKLM:\SYSTEM\CurrentControlSet\Control\Print\Printers\HP PSC 1400 series"
# $v  = (Get-ItemProperty $hp).Attributes
# Set-ItemProperty $hp -Name Attributes -Value ($v -band 0xFFFFF7FF) -Type DWord

# ===== 6 SPOOLER + EVENTOS + PRUEBA =====
Get-Printer | ForEach-Object { Get-PrintJob -PrinterName $_.Name -ErrorAction SilentlyContinue | Remove-PrintJob }
Stop-Service Spooler -Force
Remove-Item "C:\Windows\System32\spool\PRINTERS\*" -Force -Recurse -ErrorAction SilentlyContinue
Start-Service Spooler
wevtutil sl Microsoft-Windows-PrintService/Operational /e:true
"Prueba $(Get-Date)" | Out-Printer -Name $Impresora

# ===== ✅ VERIFICAR =====
net share
Get-Printer | Format-Table Name, Shared, ShareName
(Get-Printer -Name $Impresora -Full).PermissionSDDL
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PrintService/Operational'; Id=307} -MaxEvents 1 |
    Format-List TimeCreated, Message

⚠️ En cada PC Windows cliente (Paso 7): Remove-Printer de la vieja → cmdkey /delete → cmdkey /add con arctest → Add-Printer -ConnectionName.


Apéndice B — Linux en orden

sudo pacman -S --needed cups cups-filters ghostscript gutenprint hplip a2ps
sudo systemctl enable --now cups
yay -S brother-hll1222
find /usr/share/ppd -iname '*1222*'
sudo lpadmin -p Brother1222 -E -P /usr/share/ppd/Brother/HL1222.ppd \
  -v 'smb://arctest:P@ssw0rd123@192.168.0.203/Brother HL-L1222 Printer'
sudo lpadmin -d Brother1222
lpstat -p -d
lp -d Brother1222 documento.pdf

Apéndice C — Problemas conocidos y su causa real

Síntoma Causa real / solución
Job llega como “documento remoto de bajo nivel”, 0 páginas, sin ruido Impresora GDI/host-based: no acepta texto crudo. Renderizar en Linux con el driver correcto y enviar PDF (nunca -o raw).
Brother no imprime (410 bytes, 0 páginas) Falta el driver (brother-hll1222 desde AUR).
HP hace ruido y se traba; “cartucho vacío” falso BIDI activo → Paso 5 (bit 0x800).
NT_STATUS_ACCESS_DENIED Sin credenciales válidas → Pasos 1 (usuario), 3 (permiso Print) y 7 (reagregar con contraseña).
El trabajo llega y Windows lo borra solo (evento 800 y luego 310) El spooler rechaza invitados/anónimos: imprimir autenticado con arctest.
Las PCs Windows dejaron de imprimir tras los cambios Paso 7: la conexión vieja quedó sin credenciales → borrar y reagregar.
“Acceso denegado” o “no se encuentra la ruta” al agregar Firewall/perfil (Paso 2), credenciales sin guardar, o spooler caído.
texttopdf crasheaba (signal 11) en CUPS Se enviaba text/plain; enviar PDF evita ese filtro.

Apéndice D — Limpieza y notas

  • No borrar arctest: única cuenta con la que Linux y las demás PCs imprimen.
  • En la PC host vieja quedaron scripts de diagnóstico en C:\Users\Public\ (hp.ps1, hpfix.ps1, hpdiag.ps1, state.ps1, dump.ps1, sec.ps1, setacl2.ps1, share.ps1): se pueden borrar.
  • El trabajo se renderiza en Linux; Windows solo hace de spooler/interfaz con la impresora USB.
  • Prueba final de “todo OK”: imprimir un PDF desde Linux → evento 307 en el host.