Guest User

Untitled

a guest
May 23rd, 2020
343
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.68 KB | None | 0 0
  1. class __declspec(novtable) IoPrimitive
  2. {
  3. protected:
  4.     virtual void IOCompletionRoutine(ULONG Code, ULONG dwErrorCode, ULONG_PTR dwNumberOfBytesTransfered, PVOID Pointer) = 0;
  5.  
  6.     HANDLE m_hFile;
  7.     LONG m_nRef;
  8.  
  9.     IoPrimitive() : m_nRef(1), m_hFile(0)
  10.     {
  11.     }
  12.  
  13.     virtual ~IoPrimitive()
  14.     {
  15.         if (m_hFile) CloseHandle(m_hFile);
  16.     }
  17.  
  18. public:
  19.     void AddRef()
  20.     {
  21.         InterlockedIncrementNoFence(&m_nRef);
  22.     }
  23.  
  24.     void Release()
  25.     {
  26.         if (!InterlockedDecrement(&m_nRef)) delete this;
  27.     }
  28.  
  29.     class irp : public OVERLAPPED
  30.     {
  31.         IoPrimitive* _pObj;
  32.         PVOID _Pointer;
  33.         ULONG _Code;
  34.  
  35.         void IOCompletionRoutine(ULONG dwErrorCode, ULONG_PTR dwNumberOfBytesTransfered)
  36.         {
  37.             _pObj->IOCompletionRoutine(_Code, dwErrorCode, dwNumberOfBytesTransfered, _Pointer);
  38.             delete this;
  39.         }
  40.     public:
  41.  
  42.         static VOID WINAPI s_IOCompletionRoutine(
  43.             _In_    DWORD status,
  44.             _In_    DWORD dwNumberOfBytesTransfered,
  45.             _Inout_ LPOVERLAPPED lpOverlapped
  46.             )
  47.         {
  48.             static_cast<irp*>(lpOverlapped)->IOCompletionRoutine(RtlNtStatusToDosError(status), dwNumberOfBytesTransfered);
  49.         }
  50.  
  51.         irp(IoPrimitive* pObj, ULONG Code, PVOID Pointer) : _pObj(pObj), _Code(Code), _Pointer(Pointer)
  52.         {
  53.             pObj->AddRef();
  54.             RtlZeroMemory(static_cast<OVERLAPPED*>(this), sizeof(OVERLAPPED));
  55.         }
  56.  
  57.         ~irp()
  58.         {
  59.             _pObj->Release();
  60.         }
  61.  
  62.         void Check(BOOL fOk)
  63.         {
  64.             if (!fOk)
  65.             {
  66.                 switch (ULONG dwError = GetLastError())
  67.                 {
  68.                 case ERROR_IO_PENDING:
  69.                     return;
  70.                 default:
  71.                     IOCompletionRoutine(dwError, 0);
  72.                 }
  73.             }
  74.         }
  75.     };
  76.  
  77.     ULONG Assign(HANDLE hFile)
  78.     {
  79.         m_hFile = hFile;
  80.         return BindIoCompletionCallback(hFile, irp::s_IOCompletionRoutine, 0) ? NOERROR : GetLastError();
  81.     }
  82. };
  83.  
  84. class Pipe : public IoPrimitive
  85. {
  86.     PCSTR _name;
  87.     ULONG _n;
  88.     char _buf[256];
  89.  
  90.     enum { e_read, e_write, e_connect, e_disconnect };
  91.  
  92.     PCSTR GetCodeName(ULONG code)
  93.     {
  94.         switch(code)
  95.         {
  96.         case e_read: return "e_read";
  97.         case e_write: return "e_write";
  98.         case e_connect: return "e_connect";
  99.         case e_disconnect: return "e_disconnect";
  100.         }
  101.         return 0;
  102.     }
  103.  
  104.     void Read()
  105.     {
  106.         if (irp* pi = new irp(this, e_read, _buf))
  107.         {
  108.             pi->Check(ReadFile(m_hFile, _buf, sizeof(_buf), 0, pi));
  109.         }
  110.     }
  111.  
  112.     void Write(PCSTR fmt, ...)
  113.     {
  114.         va_list v;
  115.         va_start(v, fmt);
  116.        
  117.         int len = _vscprintf(fmt, v);
  118.  
  119.         if (0 < len)
  120.         {
  121.             if (PSTR buf = new CHAR[len + 1])
  122.             {
  123.                 if (0 < (len = _vsnprintf_s(buf, len + 1, _TRUNCATE, fmt, v)))
  124.                 {
  125.                     if (irp* pi = new irp(this, e_write, buf))
  126.                     {
  127.                         pi->Check(WriteFile(m_hFile, buf, len, 0, pi));
  128.                         va_end(v);
  129.                         return ;
  130.                     }
  131.                 }
  132.  
  133.                 delete [] buf;
  134.             }
  135.         }
  136.  
  137.         va_end(v);
  138.     }
  139.  
  140.     void Write()
  141.     {
  142.         if (_n) Write("%s write #%u\n", _name, --_n); else CancelIoEx(m_hFile, 0);
  143.     }
  144.  
  145.     virtual void IOCompletionRoutine(ULONG Code, ULONG dwErrorCode, ULONG_PTR dwNumberOfBytesTransfered, PVOID Pointer)
  146.     {
  147.         DbgPrint("%s<%p, %s>(%s, %u, %x, %p)\n", __FUNCTION__, this, _name,
  148.             GetCodeName(Code), dwErrorCode, dwNumberOfBytesTransfered, Pointer);
  149.  
  150.         switch (Code)
  151.         {
  152.         case e_connect:
  153.             switch (dwErrorCode)
  154.             {
  155.             case NOERROR:
  156.             case ERROR_PIPE_CONNECTED:
  157.             case ERROR_NO_DATA:
  158.                 Read();
  159.                 Write();
  160.                 break;
  161.             }
  162.             break;
  163.         case e_disconnect:
  164.             if (dwErrorCode == NOERROR && _n)
  165.             {
  166.                 Listen();
  167.             }
  168.             break;
  169.         case e_write:
  170.             delete [] Pointer;
  171.             break;
  172.         case e_read:
  173.             switch (dwErrorCode)
  174.             {
  175.             case NOERROR:
  176.                 DbgPrint("[%s]: %.*s\n", _name, dwNumberOfBytesTransfered, Pointer);
  177.                 Read();
  178.                 Write();
  179.                 break;
  180.             case ERROR_BROKEN_PIPE:
  181.             case ERROR_NO_DATA:
  182.                 Disconnect();
  183.                 break;
  184.             }
  185.             break;
  186.         default: __debugbreak();
  187.         }
  188.     }
  189.  
  190.     virtual ~Pipe()
  191.     {
  192.         DbgPrint("%s<%p, %s>\n", __FUNCTION__, this, _name);
  193.     }
  194. public:
  195.    
  196.     Pipe(PCSTR name, ULONG n) : _name(name), _n(n)
  197.     {
  198.         DbgPrint("%s<%p, %s>\n", __FUNCTION__, this, _name);
  199.     }
  200.  
  201.     void Listen()
  202.     {
  203.         if (irp* pi = new irp(this, e_connect, 0))
  204.         {
  205.             pi->Check(ConnectNamedPipe(m_hFile, pi));
  206.         }
  207.     }
  208.  
  209.     void Connect(PCWSTR name)
  210.     {
  211.         HANDLE hFile = CreateFileW(name, FILE_READ_DATA|FILE_WRITE_DATA, 0, 0, OPEN_EXISTING,
  212.             FILE_FLAG_OVERLAPPED, 0);
  213.  
  214.         IOCompletionRoutine(e_connect, hFile != INVALID_HANDLE_VALUE ? Assign(hFile) : GetLastError(), 0, 0);
  215.     }
  216.  
  217.     void Disconnect()
  218.     {
  219.         if (irp* pi = new irp(this, e_disconnect, 0))
  220.         {
  221.             NTSTATUS status = NtFsControlFile(m_hFile, 0, 0, pi, (PIO_STATUS_BLOCK)pi, FSCTL_PIPE_DISCONNECT, 0, 0, 0, 0);
  222.             if (0 > status)
  223.             {
  224.                 RtlNtStatusToDosError(status);
  225.             }
  226.             pi->Check(0 <= status);
  227.         }
  228.     }
  229. };
  230.  
  231. void _()
  232. {
  233.     MessageBoxW(0, 0, L"...", MB_ICONINFORMATION);
  234.  
  235.     static const WCHAR name[] = L"\\\\.\\pipe\\1234";
  236.  
  237.     if (Pipe* p = new Pipe("server", 8))
  238.     {
  239.         HANDLE hPipe = CreateNamedPipeW(name,
  240.             PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
  241.             PIPE_TYPE_BYTE|PIPE_READMODE_BYTE, 1, 0, 0, 0, 0);
  242.        
  243.         if (hPipe != INVALID_HANDLE_VALUE)
  244.         {
  245.             if (NOERROR == p->Assign(hPipe))
  246.             {
  247.                 p->Listen();
  248.             }
  249.         }
  250.         p->Release();
  251.     }
  252.  
  253.     do
  254.     {
  255.         if (Pipe* p = new Pipe("client", 2))
  256.         {
  257.             p->Connect(name);
  258.             p->Release();
  259.         }
  260.     } while (MessageBoxW(0, 0, L"continue ?", MB_ICONQUESTION|MB_YESNO) == IDYES);
  261.  
  262.     MessageBoxW(0, 0, L"...", MB_ICONINFORMATION);
  263. }
  264.  
  265. /*
  266.  
  267. Pipe::Pipe<000002173D4FFB90, server>
  268. Pipe::Pipe<000002173D4FA410, client>
  269. Pipe::IOCompletionRoutine<000002173D4FA410, client>(e_connect, 0, 0, 0000000000000000)
  270. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_connect, 0, 0, 0000000000000000)
  271. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D4FCB80)
  272. Pipe::IOCompletionRoutine<000002173D4FA410, client>(e_read, 0, 10, 000002173D4FA434)
  273. [client]: server write #7
  274.  
  275. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 0, 10, 000002173D4FFBB4)
  276. [server]: client write #1
  277.  
  278. Pipe::IOCompletionRoutine<000002173D4FA410, client>(e_write, 0, 10, 000002173D53E100)
  279. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D53C6D0)
  280. Pipe::IOCompletionRoutine<000002173D4FA410, client>(e_read, 0, 10, 000002173D4FA434)
  281. [client]: server write #6
  282.  
  283. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 0, 10, 000002173D4FFBB4)
  284. [server]: client write #0
  285.  
  286. Pipe::IOCompletionRoutine<000002173D4FA410, client>(e_write, 0, 10, 000002173D53B1A0)
  287. Pipe::IOCompletionRoutine<000002173D4FA410, client>(e_read, 995, 0, 000002173D4FA434)
  288. Pipe::~Pipe<000002173D4FA410, client>
  289. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 109, 0, 000002173D4FFBB4)
  290. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 109, 0, 000002173D4FB570)
  291. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_disconnect, 0, 0, 0000000000000000)
  292. Pipe::Pipe<000002173D528B10, client>
  293. Pipe::IOCompletionRoutine<000002173D528B10, client>(e_connect, 0, 0, 0000000000000000)
  294. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_connect, 0, 0, 0000000000000000)
  295. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D4FB150)
  296. Pipe::IOCompletionRoutine<000002173D528B10, client>(e_read, 0, 10, 000002173D528B34)
  297. [client]: server write #4
  298.  
  299. Pipe::IOCompletionRoutine<000002173D528B10, client>(e_write, 0, 10, 000002173D53B1A0)
  300. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 0, 10, 000002173D4FFBB4)
  301. [server]: client write #1
  302.  
  303. Pipe::IOCompletionRoutine<000002173D528B10, client>(e_write, 0, 10, 000002173D4FB150)
  304. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 0, 10, 000002173D4FFBB4)
  305. [server]: client write #0
  306.  
  307. Pipe::IOCompletionRoutine<000002173D528B10, client>(e_read, 0, 10, 000002173D528B34)
  308. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D4F5550)
  309. [client]: server write #3
  310.  
  311. Pipe::IOCompletionRoutine<000002173D528B10, client>(e_read, 0, 10, 000002173D528B34)
  312. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D4FB150)
  313. [client]: server write #2
  314.  
  315. Pipe::IOCompletionRoutine<000002173D528B10, client>(e_read, 995, 0, 000002173D528B34)
  316. Pipe::~Pipe<000002173D528B10, client>
  317. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 109, 0, 000002173D4FFBB4)
  318. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_disconnect, 0, 0, 0000000000000000)
  319. Pipe::Pipe<000002173D53E280, client>
  320. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_connect, 0, 0, 0000000000000000)
  321. Pipe::IOCompletionRoutine<000002173D53E280, client>(e_connect, 0, 0, 0000000000000000)
  322. Pipe::IOCompletionRoutine<000002173D53E280, client>(e_read, 0, 10, 000002173D53E2A4)
  323. [client]: server write #1
  324.  
  325. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D4F5610)
  326. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 0, 10, 000002173D4FFBB4)
  327. [server]: client write #1
  328.  
  329. Pipe::IOCompletionRoutine<000002173D53E280, client>(e_write, 0, 10, 000002173D4FB150)
  330. Pipe::IOCompletionRoutine<000002173D53E280, client>(e_write, 0, 10, 000002173D4F5610)
  331. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 0, 10, 000002173D4FFBB4)
  332. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_write, 0, 10, 000002173D4FB150)
  333. [server]: client write #0
  334.  
  335. Pipe::IOCompletionRoutine<000002173D53E280, client>(e_read, 0, 10, 000002173D53E2A4)
  336. [client]: server write #0
  337.  
  338. Pipe::IOCompletionRoutine<000002173D4FFB90, server>(e_read, 995, 0, 000002173D4FFBB4)
  339. Pipe::~Pipe<000002173D4FFB90, server>
  340. Pipe::IOCompletionRoutine<000002173D53E280, client>(e_read, 995, 0, 000002173D53E2A4)
  341. Pipe::~Pipe<000002173D53E280, client>
  342. Pipe::Pipe<000002173D4FFB90, client>
  343. Pipe::IOCompletionRoutine<000002173D4FFB90, client>(e_connect, 2, 0, 0000000000000000)
  344. Pipe::~Pipe<000002173D4FFB90, client>
  345. Pipe::Pipe<000002173D4FFB90, client>
  346. Pipe::IOCompletionRoutine<000002173D4FFB90, client>(e_connect, 2, 0, 0000000000000000)
  347. Pipe::~Pipe<000002173D4FFB90, client>
  348.  
  349. */
Add Comment
Please, Sign In to add comment