How can I write to a named pipe in Windows using js-ctypes?

153 Views Asked by At

I am able to connect to the pipe (I can see the connection), but WriteFile always yields a result of 0 and bytesWritten is 0. What is going on?

  let pipeName = "\\\\.\\pipe\\xxx.pipe";
  let hFile = createFile(pipeName, pipeMode, 0, null, OPEN_EXISTING, 0, null);
  let hFileInt = ctypes.cast(hFile, ctypes.intptr_t);
  if (ctypes.Int64.compare(hFileInt.value, INVALID_HANDLE_VALUE) == 0) {
    throw new Error("CreateFile failed for " + pipeName + ", error " +
                 ctypes.winLastError);
  }

  let bytesWritten = ctypes.uint32_t(88);
  let msg = "hello world\n";
  let result = writeFile(hFile, msg, 12, bytesWritten.address(), null);
  result = flushFileBuffer(hFile);

the result of writeFile is 0 as is flushFileBuffer, and bytesWritten changes from 88 to 0. :( Here are the declarations:

  let writeFile = kernel32.declare(
    "WriteFile",
    ctypes.winapi_abi,
    ctypes.int32_t,     //bool  // return type: 1 indicates success, 0 failure
    ctypes.voidptr_t,   // in: hObject
    ctypes.jschar.ptr,  // in: lpBuffer
    ctypes.uint32_t,    // in: nNumberOfBytesToWrite
    ctypes.uint32_t.ptr,    // out: lpNumberOfBytesWritten
    ctypes.voidptr_t.ptr    // inout: lpOverlapped
  );  

  let flushFileBuffer = kernel32.declare(
    "FlushFileBuffers",
    ctypes.winapi_abi,
    ctypes.int32_t,     //bool  // return type: 1 indicates success, 0 failure
    ctypes.voidptr_t    // in: hObject
  );

Update. I changed pipeMode to GENERIC_WRITE and got a successful write. But this is confusing. I have

  var GENERIC_READ = ctypes.uint32_t(0x80000000);
  var GENERIC_WRITE = ctypes.uint32_t(0x40000000);

and

let pipeMode = GENERIC_WRITE;

but

let pipeMode = GENERIC_READ | GENERIC_WRITE;

doesn't. Why doesn't it work? Am I doing the bitwise comparison wrong?

Update 2. pipeMode is fixed using >>> 0

  var GENERIC_READ = 0x80000000;
  var GENERIC_WRITE = 0x40000000;
  let pipeMode = ctypes.uint32_t((GENERIC_READ | GENERIC_WRITE) >>> 0);

However, it does not look like the pipe is written to (even with flush) until I close using

  closeHandle(hFile);

and when the handle is closed, my receiving application gets the message, but it is strange. From my C# app, I see

h\0e\0l\0l\0l\0o \0

Update 3. From the C# line, I was waiting for a whole line, so waiting for the \n. I increased the buffer length to 24 and it now triggers at the right time. The only remaining problem (for this question) is why I get \0 after each letter.

Update 4. This is probably the problem

jschar A 16-bit unsigned character. This is different from uint16_t in that C jschar values are automatically converted into 1-character JavaScript strings. These are Unicode characters.

I just want a regular character.

Update 5. Yup that's it. Changing to

ctypes.char.ptr,  // in: lpBuffer

makes it work. Or we should account for the 16-byte char on the other side.

0

There are 0 best solutions below