Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class __declspec(novtable) IoPrimitive
- {
- protected:
- virtual void IOCompletionRoutine(ULONG Code, ULONG dwErrorCode, ULONG_PTR dwNumberOfBytesTransfered, PVOID Pointer) = 0;
- HANDLE m_hFile;
- LONG m_nRef;
- IoPrimitive() : m_nRef(1), m_hFile(0)
- {
- }
- virtual ~IoPrimitive()
- {
- if (m_hFile) CloseHandle(m_hFile);
- }
- public:
- void AddRef()
- {
- InterlockedIncrementNoFence(&m_nRef);
- }
- void Release()
- {
- if (!InterlockedDecrement(&m_nRef)) delete this;
- }
- class irp : public OVERLAPPED
- {
- IoPrimitive* _pObj;
- PVOID _Pointer;
- ULONG _Code;
- void IOCompletionRoutine(ULONG dwErrorCode, ULONG_PTR dwNumberOfBytesTransfered)
- {
- _pObj->IOCompletionRoutine(_Code, dwErrorCode, dwNumberOfBytesTransfered, _Pointer);
- delete this;
- }
- public:
- static VOID WINAPI s_IOCompletionRoutine(
- _In_ DWORD status,
- _In_ DWORD dwNumberOfBytesTransfered,
- _Inout_ LPOVERLAPPED lpOverlapped
- )
- {
- static_cast<irp*>(lpOverlapped)->IOCompletionRoutine(RtlNtStatusToDosError(status), dwNumberOfBytesTransfered);
- }
- irp(IoPrimitive* pObj, ULONG Code, PVOID Pointer) : _pObj(pObj), _Code(Code), _Pointer(Pointer)
- {
- pObj->AddRef();
- RtlZeroMemory(static_cast<OVERLAPPED*>(this), sizeof(OVERLAPPED));
- }
- ~irp()
- {
- _pObj->Release();
- }
- void Check(BOOL fOk)
- {
- if (!fOk)
- {
- switch (ULONG dwError = GetLastError())
- {
- case ERROR_IO_PENDING:
- return;
- default:
- IOCompletionRoutine(dwError, 0);
- }
- }
- }
- };
- ULONG Assign(HANDLE hFile)
- {
- m_hFile = hFile;
- return BindIoCompletionCallback(hFile, irp::s_IOCompletionRoutine, 0) ? NOERROR : GetLastError();
- }
- };
- class Pipe : public IoPrimitive
- {
- PCSTR _name;
- ULONG _n;
- char _buf[256];
- enum { e_read, e_write, e_connect, e_disconnect };
- PCSTR GetCodeName(ULONG code)
- {
- switch(code)
- {
- case e_read: return "e_read";
- case e_write: return "e_write";
- case e_connect: return "e_connect";
- case e_disconnect: return "e_disconnect";
- }
- return 0;
- }
- void Read()
- {
- if (irp* pi = new irp(this, e_read, _buf))
- {
- pi->Check(ReadFile(m_hFile, _buf, sizeof(_buf), 0, pi));
- }
- }
- void Write(PCSTR fmt, ...)
- {
- va_list v;
- va_start(v, fmt);
- int len = _vscprintf(fmt, v);
- if (0 < len)
- {
- if (PSTR buf = new CHAR[len + 1])
- {
- if (0 < (len = _vsnprintf_s(buf, len + 1, _TRUNCATE, fmt, v)))
- {
- if (irp* pi = new irp(this, e_write, buf))
- {
- pi->Check(WriteFile(m_hFile, buf, len, 0, pi));
- va_end(v);
- return ;
- }
- }
- delete [] buf;
- }
- }
- va_end(v);
- }
- void Write()
- {
- if (_n) Write("%s write #%u\n", _name, --_n); else CancelIoEx(m_hFile, 0);
- }
- virtual void IOCompletionRoutine(ULONG Code, ULONG dwErrorCode, ULONG_PTR dwNumberOfBytesTransfered, PVOID Pointer)
- {
- DbgPrint("%s<%p, %s>(%s, %u, %x, %p)\n", __FUNCTION__, this, _name,
- GetCodeName(Code), dwErrorCode, dwNumberOfBytesTransfered, Pointer);
- switch (Code)
- {
- case e_connect:
- switch (dwErrorCode)
- {
- case NOERROR:
- case ERROR_PIPE_CONNECTED:
- case ERROR_NO_DATA:
- Read();
- Write();
- break;
- }
- break;
- case e_disconnect:
- if (dwErrorCode == NOERROR && _n)
- {
- Listen();
- }
- break;
- case e_write:
- delete [] Pointer;
- break;
- case e_read:
- switch (dwErrorCode)
- {
- case NOERROR:
- DbgPrint("[%s]: %.*s\n", _name, dwNumberOfBytesTransfered, Pointer);
- Read();
- Write();
- break;
- case ERROR_BROKEN_PIPE:
- case ERROR_NO_DATA:
- Disconnect();
- break;
- }
- break;
- default: __debugbreak();
- }
- }
- virtual ~Pipe()
- {
- DbgPrint("%s<%p, %s>\n", __FUNCTION__, this, _name);
- }
- public:
- Pipe(PCSTR name, ULONG n) : _name(name), _n(n)
- {
- DbgPrint("%s<%p, %s>\n", __FUNCTION__, this, _name);
- }
- void Listen()
- {
- if (irp* pi = new irp(this, e_connect, 0))
- {
- pi->Check(ConnectNamedPipe(m_hFile, pi));
- }
- }
- void Connect(PCWSTR name)
- {
- HANDLE hFile = CreateFileW(name, FILE_READ_DATA|FILE_WRITE_DATA, 0, 0, OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED, 0);
- IOCompletionRoutine(e_connect, hFile != INVALID_HANDLE_VALUE ? Assign(hFile) : GetLastError(), 0, 0);
- }
- void Disconnect()
- {
- if (irp* pi = new irp(this, e_disconnect, 0))
- {
- NTSTATUS status = NtFsControlFile(m_hFile, 0, 0, pi, (PIO_STATUS_BLOCK)pi, FSCTL_PIPE_DISCONNECT, 0, 0, 0, 0);
- if (0 > status)
- {
- RtlNtStatusToDosError(status);
- }
- pi->Check(0 <= status);
- }
- }
- };
- void _()
- {
- MessageBoxW(0, 0, L"...", MB_ICONINFORMATION);
- static const WCHAR name[] = L"\\\\.\\pipe\\1234";
- if (Pipe* p = new Pipe("server", 8))
- {
- HANDLE hPipe = CreateNamedPipeW(name,
- PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
- PIPE_TYPE_BYTE|PIPE_READMODE_BYTE, 1, 0, 0, 0, 0);
- if (hPipe != INVALID_HANDLE_VALUE)
- {
- if (NOERROR == p->Assign(hPipe))
- {
- p->Listen();
- }
- }
- p->Release();
- }
- do
- {
- if (Pipe* p = new Pipe("client", 2))
- {
- p->Connect(name);
- p->Release();
- }
- } while (MessageBoxW(0, 0, L"continue ?", MB_ICONQUESTION|MB_YESNO) == IDYES);
- MessageBoxW(0, 0, L"...", MB_ICONINFORMATION);
- }
- /*
- Pipe::Pipe<000002173D4FFB90, server>
- Pipe::Pipe<000002173D4FA410, client>
- Pipe::IOCompletionRoutine<000002173D4FA410, client>(e_connect, 0, 0, 0000000000000000)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_connect, 0, 0, 0000000000000000)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D4FCB80)
- Pipe::IOCompletionRoutine<000002173D4FA410, client>(e_read, 0, 10, 000002173D4FA434)
- [client]: server write #7
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 0, 10, 000002173D4FFBB4)
- [server]: client write #1
- Pipe::IOCompletionRoutine<000002173D4FA410, client>(e_write, 0, 10, 000002173D53E100)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D53C6D0)
- Pipe::IOCompletionRoutine<000002173D4FA410, client>(e_read, 0, 10, 000002173D4FA434)
- [client]: server write #6
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 0, 10, 000002173D4FFBB4)
- [server]: client write #0
- Pipe::IOCompletionRoutine<000002173D4FA410, client>(e_write, 0, 10, 000002173D53B1A0)
- Pipe::IOCompletionRoutine<000002173D4FA410, client>(e_read, 995, 0, 000002173D4FA434)
- Pipe::~Pipe<000002173D4FA410, client>
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 109, 0, 000002173D4FFBB4)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 109, 0, 000002173D4FB570)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_disconnect, 0, 0, 0000000000000000)
- Pipe::Pipe<000002173D528B10, client>
- Pipe::IOCompletionRoutine<000002173D528B10, client>(e_connect, 0, 0, 0000000000000000)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_connect, 0, 0, 0000000000000000)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D4FB150)
- Pipe::IOCompletionRoutine<000002173D528B10, client>(e_read, 0, 10, 000002173D528B34)
- [client]: server write #4
- Pipe::IOCompletionRoutine<000002173D528B10, client>(e_write, 0, 10, 000002173D53B1A0)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 0, 10, 000002173D4FFBB4)
- [server]: client write #1
- Pipe::IOCompletionRoutine<000002173D528B10, client>(e_write, 0, 10, 000002173D4FB150)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 0, 10, 000002173D4FFBB4)
- [server]: client write #0
- Pipe::IOCompletionRoutine<000002173D528B10, client>(e_read, 0, 10, 000002173D528B34)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D4F5550)
- [client]: server write #3
- Pipe::IOCompletionRoutine<000002173D528B10, client>(e_read, 0, 10, 000002173D528B34)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D4FB150)
- [client]: server write #2
- Pipe::IOCompletionRoutine<000002173D528B10, client>(e_read, 995, 0, 000002173D528B34)
- Pipe::~Pipe<000002173D528B10, client>
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 109, 0, 000002173D4FFBB4)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_disconnect, 0, 0, 0000000000000000)
- Pipe::Pipe<000002173D53E280, client>
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_connect, 0, 0, 0000000000000000)
- Pipe::IOCompletionRoutine<000002173D53E280, client>(e_connect, 0, 0, 0000000000000000)
- Pipe::IOCompletionRoutine<000002173D53E280, client>(e_read, 0, 10, 000002173D53E2A4)
- [client]: server write #1
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D4F5610)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 0, 10, 000002173D4FFBB4)
- [server]: client write #1
- Pipe::IOCompletionRoutine<000002173D53E280, client>(e_write, 0, 10, 000002173D4FB150)
- Pipe::IOCompletionRoutine<000002173D53E280, client>(e_write, 0, 10, 000002173D4F5610)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 0, 10, 000002173D4FFBB4)
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D4FB150)
- [server]: client write #0
- Pipe::IOCompletionRoutine<000002173D53E280, client>(e_read, 0, 10, 000002173D53E2A4)
- [client]: server write #0
- Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 995, 0, 000002173D4FFBB4)
- Pipe::~Pipe<000002173D4FFB90, server>
- Pipe::IOCompletionRoutine<000002173D53E280, client>(e_read, 995, 0, 000002173D53E2A4)
- Pipe::~Pipe<000002173D53E280, client>
- Pipe::Pipe<000002173D4FFB90, client>
- Pipe::IOCompletionRoutine<000002173D4FFB90, client>(e_connect, 2, 0, 0000000000000000)
- Pipe::~Pipe<000002173D4FFB90, client>
- Pipe::Pipe<000002173D4FFB90, client>
- Pipe::IOCompletionRoutine<000002173D4FFB90, client>(e_connect, 2, 0, 0000000000000000)
- Pipe::~Pipe<000002173D4FFB90, client>
- */
Add Comment
Please, Sign In to add comment