Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WritePrinter doesn't support international characters #1049

Open
hvpavan opened this issue Nov 22, 2023 · 2 comments
Open

WritePrinter doesn't support international characters #1049

hvpavan opened this issue Nov 22, 2023 · 2 comments

Comments

@hvpavan
Copy link

hvpavan commented Nov 22, 2023

Has anyone been successful in printing international charset using raw datatype? Here is the 3 step process I have

Step 1: Open Printer

let printer_name = "MY_PRINTER_NAME";

// Convert the printer name to a wide string (UTF-16)
let mut printer_name_wide: Vec<u16> = printer_name.encode_utf16().chain(std::iter::once(0)).collect();

// Declare a pointer to store the printer handle
let mut printer_handle: winapi::um::winnt::HANDLE = std::ptr::null_mut();
let mut datatype: &str = "RAW"; // XPS_PASS, EMF, 
let datatype_utf8 = std::ffi::CString::new(datatype).expect("CString::new failed");                          

let mut defaults = **PRINTER_DEFAULTSW**  {
    pDataType: ptr::null_mut(),
    pDevMode: ptr::null_mut(),
    DesiredAccess: 0x40000000, //GENERIC_WRITE
};    

// Call OpenPrinterW to open the specified printer
let result = unsafe {
    OpenPrinter2W(
        printer_name_wide.as_mut_ptr(),
        &mut printer_handle,
        &mut defaults,
        std::ptr::null_mut(),
    )
};

Step 2: Start Doc Printer

let job_name = "PrintJob";

let job_name_utf8 = std::ffi::CString::new(job_name).expect("CString::new failed");                          
let mut datatype: &str = "RAW"; // XPS_PASS, EMF, 
let datatype_utf8 = std::ffi::CString::new(datatype).expect("CString::new failed");                          

let mut datatype_wide: Vec<u8> = datatype.as_bytes().to_vec();

let docinfo1w = DOC_INFO_1W {
    pDocName: job_name_utf8.as_ptr() as *mut u16,
    pOutputFile: ptr::null_mut(),
    pDatatype: datatype_utf8.as_ptr() as *mut u16, // This works
};

fn struct_to_bytes<T>(data: &T) -> Vec<u8> {
    unsafe {
        let size = std::mem::size_of::<T>();
        let ptr = data as *const T as *const u8;
        std::slice::from_raw_parts(ptr, size).to_vec()
    }
}    

let struct_bytes: Vec<u8> = struct_to_bytes(&docinfo1w);   


let result = StartDocPrinterA (
    printer_handle,
    1, // Number of copies
    struct_bytes.as_ptr() as *mut u8); // DOC_INFO_1W

println!("Failed to start page. Error code: {}", unsafe {
    winapi::um::errhandlingapi::GetLastError()
});

Step 3: Print using WritePrinter

let page_result = unsafe { StartPagePrinter(printer_handle) };

println!("Page started successfully!");

let text_to_print = "Hello, 你好, привет!";      
let text_utf8 = std::ffi::CString::new(text_to_print).expect("CString::new failed");                          

let mut bytes_written: u32 = 0;

let write_result = unsafe {
    WritePrinter(
        printer_handle,
        text_utf8.as_ptr() as *mut winapi::ctypes::c_void,
        text_utf8.as_bytes().len() as u32 * 2,                        
        &mut bytes_written,
    )
};
@hvpavan
Copy link
Author

hvpavan commented Nov 22, 2023

I have tried encoding using encode_utf16 as well with no luck,

let text_to_print = "Hello, 你好, привет!";
let utf16_text: Vec = text_to_print.encode_utf16().collect();

@hvpavan hvpavan changed the title Thermal printer printing garbage while printing unicode international characters using WritePrinter WritePrinter doesn't support international characters Nov 25, 2023
@Kreijstal
Copy link

Just use windows-rs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants