1

I can create a named pipe in Windows via CreateNamedPipe.

p = win32pipe.CreateNamedPipe(r'\\.\pipe\test_pipe',
    win32pipe.PIPE_ACCESS_DUPLEX,
    win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT,
    1, 65536, 65536,300,None)

This is a file-like object, and in contrast to Linux FIFOs it does not live in the main filesystem, but in a special kernel namespace (that's what the \\.\pipe is for). Now, I have a device that lives at //./xillybus_read_32, and would like to mock it out for tests, i.e. create a fake that behaves like it. According to MSDN, this is the Win32 device namespace. If possible, how can I create a pipe-like object there? Would it be neccessary to write a driver, or is there a userspace API?

(Of course, I can just change the consuming code to use my pipe, or solve it in a dozen other ways. But I'm really curious about this Win32 device namespace.)

jdm
  • 9,470
  • 12
  • 58
  • 110
  • Not an answer to your question, but you may be interested in Sysinternal's WinObj (available for download from the Microsoft web site) which allows you to view the contents of the kernel namespace. – Harry Johnston May 31 '17 at 23:50
  • 1
    I *think* that the way `\\.foo` is interpreted means that you could use `DefineDosDevice` to create a symbolic link in the device namespace from `xillybus_read_32` to a named pipe. But I'm not sure about the details. – Harry Johnston May 31 '17 at 23:54

1 Answers1

2

I think I found it. This comment, the comments from Harry Johnston, and some browsing through WinObj brought me to the solution.

import win32pipe, win32file, win32con

win32file.DefineDosDevice(win32con.DDD_RAW_TARGET_PATH, r'test_device', r'\??\GLOBAL\pipe\test_pipe')

fileHandle = win32file.CreateFile(r"//./test_device",
                              win32file.GENERIC_READ | win32file.GENERIC_WRITE,
                              0, None,
                              win32file.OPEN_EXISTING,
                              0, None)
data = win32file.ReadFile(fileHandle, 4096)
print (data)

What happens here is that \?? leaves you in \Sessions\0\DosDevices\[LogonID]. In that folder, there is a symlink GLOBAL which leads to \GLOBAL??, in which the named pipes live.

Why I can't access the path directly via \\.\GLOBAL??\pipe\test_pipe, and why CreateFile and CreateNamedPipe can find it under \\.\pipe\test_pipe, I don't know yet. I'm also not sure if I should do some cleanup afterwards. Nevertheless this seems to work.

jdm
  • 9,470
  • 12
  • 58
  • 110
  • you can access it by path `\\?\pipe\test_pipe` . the path `\\.\GLOBAL??\pipe\test_pipe` is converted by win32 to `\??\GLOBAL??\pipe\test_pipe` which is invalid. also in call `DefineDosDevice` you can use `\GLOBAL??\pipe\test_pipe` or `\Device\NamedPipe\test_pipe` instead path which you use – RbMm Jun 01 '17 at 20:11
  • nt-path \??\ is virtual - it not exist - *Ob-manager* try convert it to 2 paths when view - first to \Sessions\0\DosDevices\LogonID (if you run not under LocalSystem luid) and then (if first path not found) - to \GLOBAL??\ . if you want use direct paths as is and access \GLOBAL??\ direct - you need use `Nt*` api. win32 api use own namespace and convert it to nt-form before call native api. but not any native path have win32 equivalent. say \GLOBAL??\ - not have. and win32 layer convert \\.\ and \\?\ to \??\ – RbMm Jun 01 '17 at 20:19