pipe.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  1. /**
  2. * WinPR: Windows Portable Runtime
  3. * Pipe Functions
  4. *
  5. * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
  6. * Copyright 2017 Armin Novak <armin.novak@thincast.com>
  7. * Copyright 2017 Thincast Technologies GmbH
  8. *
  9. * Licensed under the Apache License, Version 2.0 (the "License");
  10. * you may not use this file except in compliance with the License.
  11. * You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing, software
  16. * distributed under the License is distributed on an "AS IS" BASIS,
  17. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. * See the License for the specific language governing permissions and
  19. * limitations under the License.
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include "config.h"
  23. #endif
  24. #include <winpr/crt.h>
  25. #include <winpr/path.h>
  26. #include <winpr/synch.h>
  27. #include <winpr/handle.h>
  28. #include <winpr/pipe.h>
  29. #ifdef HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32. #ifndef _WIN32
  33. #include "../handle/handle.h"
  34. #include <fcntl.h>
  35. #include <errno.h>
  36. #include <sys/un.h>
  37. #include <sys/socket.h>
  38. #include <assert.h>
  39. #include <unistd.h>
  40. #ifdef HAVE_SYS_AIO_H
  41. #undef HAVE_SYS_AIO_H /* disable for now, incomplete */
  42. #endif
  43. #ifdef HAVE_SYS_AIO_H
  44. #include <aio.h>
  45. #endif
  46. #include "pipe.h"
  47. #include "../log.h"
  48. #define TAG WINPR_TAG("pipe")
  49. /*
  50. * Since the WinPR implementation of named pipes makes use of UNIX domain
  51. * sockets, it is not possible to bind the same name more than once (i.e.,
  52. * SO_REUSEADDR does not work with UNIX domain sockets). As a result, the
  53. * first call to CreateNamedPipe with name n creates a "shared" UNIX domain
  54. * socket descriptor that gets duplicated via dup() for the first and all
  55. * subsequent calls to CreateNamedPipe with name n.
  56. *
  57. * The following array keeps track of the references to the shared socked
  58. * descriptors. If an entry's reference count is zero the base socket
  59. * descriptor gets closed and the entry is removed from the list.
  60. */
  61. static wArrayList* g_NamedPipeServerSockets = NULL;
  62. typedef struct _NamedPipeServerSocketEntry
  63. {
  64. char* name;
  65. int serverfd;
  66. int references;
  67. } NamedPipeServerSocketEntry;
  68. static BOOL PipeIsHandled(HANDLE handle)
  69. {
  70. WINPR_PIPE* pPipe = (WINPR_PIPE*)handle;
  71. if (!pPipe || (pPipe->Type != HANDLE_TYPE_ANONYMOUS_PIPE))
  72. {
  73. SetLastError(ERROR_INVALID_HANDLE);
  74. return FALSE;
  75. }
  76. return TRUE;
  77. }
  78. static int PipeGetFd(HANDLE handle)
  79. {
  80. WINPR_PIPE* pipe = (WINPR_PIPE*)handle;
  81. if (!PipeIsHandled(handle))
  82. return -1;
  83. return pipe->fd;
  84. }
  85. static BOOL PipeCloseHandle(HANDLE handle)
  86. {
  87. WINPR_PIPE* pipe = (WINPR_PIPE*)handle;
  88. if (!PipeIsHandled(handle))
  89. return FALSE;
  90. if (pipe->fd != -1)
  91. {
  92. close(pipe->fd);
  93. pipe->fd = -1;
  94. }
  95. free(handle);
  96. return TRUE;
  97. }
  98. static BOOL PipeRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
  99. LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
  100. {
  101. int io_status;
  102. WINPR_PIPE* pipe;
  103. BOOL status = TRUE;
  104. if (lpOverlapped)
  105. {
  106. WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
  107. SetLastError(ERROR_NOT_SUPPORTED);
  108. return FALSE;
  109. }
  110. pipe = (WINPR_PIPE*)Object;
  111. do
  112. {
  113. io_status = read(pipe->fd, lpBuffer, nNumberOfBytesToRead);
  114. } while ((io_status < 0) && (errno == EINTR));
  115. if (io_status < 0)
  116. {
  117. status = FALSE;
  118. switch (errno)
  119. {
  120. case EWOULDBLOCK:
  121. SetLastError(ERROR_NO_DATA);
  122. break;
  123. }
  124. }
  125. if (lpNumberOfBytesRead)
  126. *lpNumberOfBytesRead = io_status;
  127. return status;
  128. }
  129. static BOOL PipeWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
  130. LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
  131. {
  132. int io_status;
  133. WINPR_PIPE* pipe;
  134. if (lpOverlapped)
  135. {
  136. WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
  137. SetLastError(ERROR_NOT_SUPPORTED);
  138. return FALSE;
  139. }
  140. pipe = (WINPR_PIPE*)Object;
  141. do
  142. {
  143. io_status = write(pipe->fd, lpBuffer, nNumberOfBytesToWrite);
  144. } while ((io_status < 0) && (errno == EINTR));
  145. if ((io_status < 0) && (errno == EWOULDBLOCK))
  146. io_status = 0;
  147. *lpNumberOfBytesWritten = io_status;
  148. return TRUE;
  149. }
  150. static HANDLE_OPS ops = {
  151. PipeIsHandled, PipeCloseHandle,
  152. PipeGetFd, NULL, /* CleanupHandle */
  153. PipeRead, NULL, /* FileReadEx */
  154. NULL, /* FileReadScatter */
  155. PipeWrite, NULL, /* FileWriteEx */
  156. NULL, /* FileWriteGather */
  157. NULL, /* FileGetFileSize */
  158. NULL, /* FlushFileBuffers */
  159. NULL, /* FileSetEndOfFile */
  160. NULL, /* FileSetFilePointer */
  161. NULL, /* SetFilePointerEx */
  162. NULL, /* FileLockFile */
  163. NULL, /* FileLockFileEx */
  164. NULL, /* FileUnlockFile */
  165. NULL, /* FileUnlockFileEx */
  166. NULL /* SetFileTime */
  167. };
  168. static BOOL NamedPipeIsHandled(HANDLE handle)
  169. {
  170. WINPR_NAMED_PIPE* pPipe = (WINPR_NAMED_PIPE*)handle;
  171. if (!pPipe || (pPipe->Type != HANDLE_TYPE_NAMED_PIPE) || (pPipe == INVALID_HANDLE_VALUE))
  172. {
  173. SetLastError(ERROR_INVALID_HANDLE);
  174. return FALSE;
  175. }
  176. return TRUE;
  177. }
  178. static int NamedPipeGetFd(HANDLE handle)
  179. {
  180. WINPR_NAMED_PIPE* pipe = (WINPR_NAMED_PIPE*)handle;
  181. if (!NamedPipeIsHandled(handle))
  182. return -1;
  183. if (pipe->ServerMode)
  184. return pipe->serverfd;
  185. return pipe->clientfd;
  186. }
  187. static BOOL NamedPipeCloseHandle(HANDLE handle)
  188. {
  189. WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)handle;
  190. /* This check confuses the analyzer. Since not all handle
  191. * types are handled here, it guesses that the memory of a
  192. * NamedPipeHandle may leak. */
  193. #ifndef __clang_analyzer__
  194. if (!NamedPipeIsHandled(handle))
  195. return FALSE;
  196. #endif
  197. if (pNamedPipe->pfnUnrefNamedPipe)
  198. pNamedPipe->pfnUnrefNamedPipe(pNamedPipe);
  199. free(pNamedPipe->name);
  200. free(pNamedPipe->lpFileName);
  201. free(pNamedPipe->lpFilePath);
  202. if (pNamedPipe->serverfd != -1)
  203. close(pNamedPipe->serverfd);
  204. if (pNamedPipe->clientfd != -1)
  205. close(pNamedPipe->clientfd);
  206. free(pNamedPipe);
  207. return TRUE;
  208. }
  209. BOOL NamedPipeRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
  210. LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
  211. {
  212. int io_status;
  213. WINPR_NAMED_PIPE* pipe;
  214. BOOL status = TRUE;
  215. if (lpOverlapped)
  216. {
  217. WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
  218. SetLastError(ERROR_NOT_SUPPORTED);
  219. return FALSE;
  220. }
  221. pipe = (WINPR_NAMED_PIPE*)Object;
  222. if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
  223. {
  224. if (pipe->clientfd == -1)
  225. return FALSE;
  226. do
  227. {
  228. io_status = read(pipe->clientfd, lpBuffer, nNumberOfBytesToRead);
  229. } while ((io_status < 0) && (errno == EINTR));
  230. if (io_status == 0)
  231. {
  232. SetLastError(ERROR_BROKEN_PIPE);
  233. status = FALSE;
  234. }
  235. else if (io_status < 0)
  236. {
  237. status = FALSE;
  238. switch (errno)
  239. {
  240. case EWOULDBLOCK:
  241. SetLastError(ERROR_NO_DATA);
  242. break;
  243. default:
  244. SetLastError(ERROR_BROKEN_PIPE);
  245. break;
  246. }
  247. }
  248. if (lpNumberOfBytesRead)
  249. *lpNumberOfBytesRead = io_status;
  250. }
  251. else
  252. {
  253. /* Overlapped I/O */
  254. if (!lpOverlapped)
  255. return FALSE;
  256. if (pipe->clientfd == -1)
  257. return FALSE;
  258. pipe->lpOverlapped = lpOverlapped;
  259. #ifdef HAVE_SYS_AIO_H
  260. {
  261. int aio_status;
  262. struct aiocb cb;
  263. ZeroMemory(&cb, sizeof(struct aiocb));
  264. cb.aio_fildes = pipe->clientfd;
  265. cb.aio_buf = lpBuffer;
  266. cb.aio_nbytes = nNumberOfBytesToRead;
  267. cb.aio_offset = lpOverlapped->Offset;
  268. cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
  269. cb.aio_sigevent.sigev_signo = SIGIO;
  270. cb.aio_sigevent.sigev_value.sival_ptr = (void*)lpOverlapped;
  271. InstallAioSignalHandler();
  272. aio_status = aio_read(&cb);
  273. WLog_DBG(TAG, "aio_read status: %d", aio_status);
  274. if (aio_status < 0)
  275. status = FALSE;
  276. return status;
  277. }
  278. #else
  279. /* synchronous behavior */
  280. lpOverlapped->Internal = 0;
  281. lpOverlapped->InternalHigh = (ULONG_PTR)nNumberOfBytesToRead;
  282. lpOverlapped->Pointer = (PVOID)lpBuffer;
  283. SetEvent(lpOverlapped->hEvent);
  284. #endif
  285. }
  286. return status;
  287. }
  288. BOOL NamedPipeWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
  289. LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
  290. {
  291. int io_status;
  292. WINPR_NAMED_PIPE* pipe;
  293. BOOL status = TRUE;
  294. if (lpOverlapped)
  295. {
  296. WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
  297. SetLastError(ERROR_NOT_SUPPORTED);
  298. return FALSE;
  299. }
  300. pipe = (WINPR_NAMED_PIPE*)Object;
  301. if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
  302. {
  303. if (pipe->clientfd == -1)
  304. return FALSE;
  305. do
  306. {
  307. io_status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite);
  308. } while ((io_status < 0) && (errno == EINTR));
  309. if (io_status < 0)
  310. {
  311. *lpNumberOfBytesWritten = 0;
  312. switch (errno)
  313. {
  314. case EWOULDBLOCK:
  315. io_status = 0;
  316. status = TRUE;
  317. break;
  318. default:
  319. status = FALSE;
  320. }
  321. }
  322. *lpNumberOfBytesWritten = io_status;
  323. return status;
  324. }
  325. else
  326. {
  327. /* Overlapped I/O */
  328. if (!lpOverlapped)
  329. return FALSE;
  330. if (pipe->clientfd == -1)
  331. return FALSE;
  332. pipe->lpOverlapped = lpOverlapped;
  333. #ifdef HAVE_SYS_AIO_H
  334. {
  335. struct aiocb cb;
  336. ZeroMemory(&cb, sizeof(struct aiocb));
  337. cb.aio_fildes = pipe->clientfd;
  338. cb.aio_buf = (void*)lpBuffer;
  339. cb.aio_nbytes = nNumberOfBytesToWrite;
  340. cb.aio_offset = lpOverlapped->Offset;
  341. cb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
  342. cb.aio_sigevent.sigev_signo = SIGIO;
  343. cb.aio_sigevent.sigev_value.sival_ptr = (void*)lpOverlapped;
  344. InstallAioSignalHandler();
  345. io_status = aio_write(&cb);
  346. WLog_DBG("aio_write status: %d", io_status);
  347. if (io_status < 0)
  348. status = FALSE;
  349. return status;
  350. }
  351. #else
  352. /* synchronous behavior */
  353. lpOverlapped->Internal = 1;
  354. lpOverlapped->InternalHigh = (ULONG_PTR)nNumberOfBytesToWrite;
  355. lpOverlapped->Pointer = (PVOID)lpBuffer;
  356. SetEvent(lpOverlapped->hEvent);
  357. #endif
  358. }
  359. return TRUE;
  360. }
  361. static HANDLE_OPS namedOps = { NamedPipeIsHandled,
  362. NamedPipeCloseHandle,
  363. NamedPipeGetFd,
  364. NULL, /* CleanupHandle */
  365. NamedPipeRead,
  366. NULL,
  367. NULL,
  368. NamedPipeWrite,
  369. NULL,
  370. NULL,
  371. NULL,
  372. NULL,
  373. NULL,
  374. NULL,
  375. NULL,
  376. NULL,
  377. NULL,
  378. NULL,
  379. NULL,
  380. NULL };
  381. static BOOL InitWinPRPipeModule()
  382. {
  383. if (g_NamedPipeServerSockets)
  384. return TRUE;
  385. g_NamedPipeServerSockets = ArrayList_New(FALSE);
  386. return g_NamedPipeServerSockets != NULL;
  387. }
  388. /*
  389. * Unnamed pipe
  390. */
  391. BOOL CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes,
  392. DWORD nSize)
  393. {
  394. int pipe_fd[2];
  395. WINPR_PIPE* pReadPipe;
  396. WINPR_PIPE* pWritePipe;
  397. pipe_fd[0] = -1;
  398. pipe_fd[1] = -1;
  399. if (pipe(pipe_fd) < 0)
  400. {
  401. WLog_ERR(TAG, "failed to create pipe");
  402. return FALSE;
  403. }
  404. pReadPipe = (WINPR_PIPE*)calloc(1, sizeof(WINPR_PIPE));
  405. pWritePipe = (WINPR_PIPE*)calloc(1, sizeof(WINPR_PIPE));
  406. if (!pReadPipe || !pWritePipe)
  407. {
  408. free(pReadPipe);
  409. free(pWritePipe);
  410. return FALSE;
  411. }
  412. pReadPipe->fd = pipe_fd[0];
  413. pWritePipe->fd = pipe_fd[1];
  414. WINPR_HANDLE_SET_TYPE_AND_MODE(pReadPipe, HANDLE_TYPE_ANONYMOUS_PIPE, WINPR_FD_READ);
  415. pReadPipe->ops = &ops;
  416. *((ULONG_PTR*)hReadPipe) = (ULONG_PTR)pReadPipe;
  417. WINPR_HANDLE_SET_TYPE_AND_MODE(pWritePipe, HANDLE_TYPE_ANONYMOUS_PIPE, WINPR_FD_READ);
  418. pWritePipe->ops = &ops;
  419. *((ULONG_PTR*)hWritePipe) = (ULONG_PTR)pWritePipe;
  420. return TRUE;
  421. }
  422. /**
  423. * Named pipe
  424. */
  425. static void winpr_unref_named_pipe(WINPR_NAMED_PIPE* pNamedPipe)
  426. {
  427. int index;
  428. NamedPipeServerSocketEntry* baseSocket;
  429. if (!pNamedPipe)
  430. return;
  431. assert(pNamedPipe->name);
  432. assert(g_NamedPipeServerSockets);
  433. // WLog_VRB(TAG, "%p (%s)", (void*) pNamedPipe, pNamedPipe->name);
  434. ArrayList_Lock(g_NamedPipeServerSockets);
  435. for (index = 0; index < ArrayList_Count(g_NamedPipeServerSockets); index++)
  436. {
  437. baseSocket =
  438. (NamedPipeServerSocketEntry*)ArrayList_GetItem(g_NamedPipeServerSockets, index);
  439. assert(baseSocket->name);
  440. if (!strcmp(baseSocket->name, pNamedPipe->name))
  441. {
  442. assert(baseSocket->references > 0);
  443. assert(baseSocket->serverfd != -1);
  444. if (--baseSocket->references == 0)
  445. {
  446. // WLog_DBG(TAG, "removing shared server socked resource");
  447. // WLog_DBG(TAG, "closing shared serverfd %d", baseSocket->serverfd);
  448. ArrayList_Remove(g_NamedPipeServerSockets, baseSocket);
  449. close(baseSocket->serverfd);
  450. free(baseSocket->name);
  451. free(baseSocket);
  452. }
  453. break;
  454. }
  455. }
  456. ArrayList_Unlock(g_NamedPipeServerSockets);
  457. }
  458. HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances,
  459. DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut,
  460. LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  461. {
  462. int index;
  463. char* lpPipePath;
  464. struct sockaddr_un s;
  465. WINPR_NAMED_PIPE* pNamedPipe = NULL;
  466. int serverfd = -1;
  467. NamedPipeServerSocketEntry* baseSocket = NULL;
  468. if (dwOpenMode & FILE_FLAG_OVERLAPPED)
  469. {
  470. WLog_ERR(TAG, "WinPR %s does not support the FILE_FLAG_OVERLAPPED flag", __FUNCTION__);
  471. SetLastError(ERROR_NOT_SUPPORTED);
  472. return INVALID_HANDLE_VALUE;
  473. }
  474. if (!lpName)
  475. return INVALID_HANDLE_VALUE;
  476. if (!InitWinPRPipeModule())
  477. return INVALID_HANDLE_VALUE;
  478. pNamedPipe = (WINPR_NAMED_PIPE*)calloc(1, sizeof(WINPR_NAMED_PIPE));
  479. if (!pNamedPipe)
  480. return INVALID_HANDLE_VALUE;
  481. ArrayList_Lock(g_NamedPipeServerSockets);
  482. WINPR_HANDLE_SET_TYPE_AND_MODE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE, WINPR_FD_READ);
  483. pNamedPipe->serverfd = -1;
  484. pNamedPipe->clientfd = -1;
  485. if (!(pNamedPipe->name = _strdup(lpName)))
  486. goto out;
  487. if (!(pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpName)))
  488. goto out;
  489. if (!(pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpName)))
  490. goto out;
  491. pNamedPipe->dwOpenMode = dwOpenMode;
  492. pNamedPipe->dwPipeMode = dwPipeMode;
  493. pNamedPipe->nMaxInstances = nMaxInstances;
  494. pNamedPipe->nOutBufferSize = nOutBufferSize;
  495. pNamedPipe->nInBufferSize = nInBufferSize;
  496. pNamedPipe->nDefaultTimeOut = nDefaultTimeOut;
  497. pNamedPipe->dwFlagsAndAttributes = dwOpenMode;
  498. pNamedPipe->clientfd = -1;
  499. pNamedPipe->ServerMode = TRUE;
  500. pNamedPipe->ops = &namedOps;
  501. for (index = 0; index < ArrayList_Count(g_NamedPipeServerSockets); index++)
  502. {
  503. baseSocket =
  504. (NamedPipeServerSocketEntry*)ArrayList_GetItem(g_NamedPipeServerSockets, index);
  505. if (!strcmp(baseSocket->name, lpName))
  506. {
  507. serverfd = baseSocket->serverfd;
  508. // WLog_DBG(TAG, "using shared socked resource for pipe %p (%s)", (void*) pNamedPipe,
  509. // lpName);
  510. break;
  511. }
  512. }
  513. /* If this is the first instance of the named pipe... */
  514. if (serverfd == -1)
  515. {
  516. /* Create the UNIX domain socket and start listening. */
  517. if (!(lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA()))
  518. goto out;
  519. if (!PathFileExistsA(lpPipePath))
  520. {
  521. if (!CreateDirectoryA(lpPipePath, 0))
  522. {
  523. free(lpPipePath);
  524. goto out;
  525. }
  526. UnixChangeFileMode(lpPipePath, 0xFFFF);
  527. }
  528. free(lpPipePath);
  529. if (PathFileExistsA(pNamedPipe->lpFilePath))
  530. DeleteFileA(pNamedPipe->lpFilePath);
  531. if ((serverfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  532. {
  533. WLog_ERR(TAG, "CreateNamedPipeA: socket error, %s", strerror(errno));
  534. goto out;
  535. }
  536. ZeroMemory(&s, sizeof(struct sockaddr_un));
  537. s.sun_family = AF_UNIX;
  538. sprintf_s(s.sun_path, ARRAYSIZE(s.sun_path), "%s", pNamedPipe->lpFilePath);
  539. if (bind(serverfd, (struct sockaddr*)&s, sizeof(struct sockaddr_un)) == -1)
  540. {
  541. WLog_ERR(TAG, "CreateNamedPipeA: bind error, %s", strerror(errno));
  542. goto out;
  543. }
  544. if (listen(serverfd, 2) == -1)
  545. {
  546. WLog_ERR(TAG, "CreateNamedPipeA: listen error, %s", strerror(errno));
  547. goto out;
  548. }
  549. UnixChangeFileMode(pNamedPipe->lpFilePath, 0xFFFF);
  550. if (!(baseSocket = (NamedPipeServerSocketEntry*)malloc(sizeof(NamedPipeServerSocketEntry))))
  551. goto out;
  552. if (!(baseSocket->name = _strdup(lpName)))
  553. {
  554. free(baseSocket);
  555. goto out;
  556. }
  557. baseSocket->serverfd = serverfd;
  558. baseSocket->references = 0;
  559. if (ArrayList_Add(g_NamedPipeServerSockets, baseSocket) < 0)
  560. {
  561. free(baseSocket->name);
  562. goto out;
  563. }
  564. // WLog_DBG(TAG, "created shared socked resource for pipe %p (%s). base serverfd = %d",
  565. // (void*) pNamedPipe, lpName, serverfd);
  566. }
  567. pNamedPipe->serverfd = dup(baseSocket->serverfd);
  568. // WLog_DBG(TAG, "using serverfd %d (duplicated from %d)", pNamedPipe->serverfd,
  569. // baseSocket->serverfd);
  570. pNamedPipe->pfnUnrefNamedPipe = winpr_unref_named_pipe;
  571. baseSocket->references++;
  572. if (dwOpenMode & FILE_FLAG_OVERLAPPED)
  573. {
  574. #if 0
  575. int flags = fcntl(pNamedPipe->serverfd, F_GETFL);
  576. if (flags != -1)
  577. fcntl(pNamedPipe->serverfd, F_SETFL, flags | O_NONBLOCK);
  578. #endif
  579. }
  580. ArrayList_Unlock(g_NamedPipeServerSockets);
  581. return pNamedPipe;
  582. out:
  583. NamedPipeCloseHandle(pNamedPipe);
  584. if (serverfd != -1)
  585. close(serverfd);
  586. ArrayList_Unlock(g_NamedPipeServerSockets);
  587. return INVALID_HANDLE_VALUE;
  588. }
  589. HANDLE CreateNamedPipeW(LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances,
  590. DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut,
  591. LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  592. {
  593. WLog_ERR(TAG, "%s is not implemented", __FUNCTION__);
  594. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  595. return NULL;
  596. }
  597. BOOL ConnectNamedPipe(HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped)
  598. {
  599. int status;
  600. socklen_t length;
  601. struct sockaddr_un s;
  602. WINPR_NAMED_PIPE* pNamedPipe;
  603. if (lpOverlapped)
  604. {
  605. WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
  606. SetLastError(ERROR_NOT_SUPPORTED);
  607. return FALSE;
  608. }
  609. if (!hNamedPipe)
  610. return FALSE;
  611. pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
  612. if (!(pNamedPipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
  613. {
  614. length = sizeof(struct sockaddr_un);
  615. ZeroMemory(&s, sizeof(struct sockaddr_un));
  616. status = accept(pNamedPipe->serverfd, (struct sockaddr*)&s, &length);
  617. if (status < 0)
  618. {
  619. WLog_ERR(TAG, "ConnectNamedPipe: accept error");
  620. return FALSE;
  621. }
  622. pNamedPipe->clientfd = status;
  623. pNamedPipe->ServerMode = FALSE;
  624. }
  625. else
  626. {
  627. if (!lpOverlapped)
  628. return FALSE;
  629. if (pNamedPipe->serverfd == -1)
  630. return FALSE;
  631. pNamedPipe->lpOverlapped = lpOverlapped;
  632. /* synchronous behavior */
  633. lpOverlapped->Internal = 2;
  634. lpOverlapped->InternalHigh = (ULONG_PTR)0;
  635. lpOverlapped->Pointer = (PVOID)NULL;
  636. SetEvent(lpOverlapped->hEvent);
  637. }
  638. return TRUE;
  639. }
  640. BOOL DisconnectNamedPipe(HANDLE hNamedPipe)
  641. {
  642. WINPR_NAMED_PIPE* pNamedPipe;
  643. pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
  644. if (pNamedPipe->clientfd != -1)
  645. {
  646. close(pNamedPipe->clientfd);
  647. pNamedPipe->clientfd = -1;
  648. }
  649. return TRUE;
  650. }
  651. BOOL PeekNamedPipe(HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesRead,
  652. LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage)
  653. {
  654. WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
  655. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  656. return FALSE;
  657. }
  658. BOOL TransactNamedPipe(HANDLE hNamedPipe, LPVOID lpInBuffer, DWORD nInBufferSize,
  659. LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesRead,
  660. LPOVERLAPPED lpOverlapped)
  661. {
  662. WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
  663. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  664. return FALSE;
  665. }
  666. BOOL WaitNamedPipeA(LPCSTR lpNamedPipeName, DWORD nTimeOut)
  667. {
  668. BOOL status;
  669. DWORD nWaitTime;
  670. char* lpFilePath;
  671. DWORD dwSleepInterval;
  672. if (!lpNamedPipeName)
  673. return FALSE;
  674. lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpNamedPipeName);
  675. if (!lpFilePath)
  676. return FALSE;
  677. if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT)
  678. nTimeOut = 50;
  679. nWaitTime = 0;
  680. status = TRUE;
  681. dwSleepInterval = 10;
  682. while (!PathFileExistsA(lpFilePath))
  683. {
  684. Sleep(dwSleepInterval);
  685. nWaitTime += dwSleepInterval;
  686. if (nWaitTime >= nTimeOut)
  687. {
  688. status = FALSE;
  689. break;
  690. }
  691. }
  692. free(lpFilePath);
  693. return status;
  694. }
  695. BOOL WaitNamedPipeW(LPCWSTR lpNamedPipeName, DWORD nTimeOut)
  696. {
  697. WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
  698. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  699. return FALSE;
  700. }
  701. BOOL SetNamedPipeHandleState(HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
  702. LPDWORD lpCollectDataTimeout)
  703. {
  704. int fd;
  705. int flags;
  706. WINPR_NAMED_PIPE* pNamedPipe;
  707. pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
  708. if (lpMode)
  709. {
  710. pNamedPipe->dwPipeMode = *lpMode;
  711. fd = (pNamedPipe->ServerMode) ? pNamedPipe->serverfd : pNamedPipe->clientfd;
  712. if (fd == -1)
  713. return FALSE;
  714. flags = fcntl(fd, F_GETFL);
  715. if (flags < 0)
  716. return FALSE;
  717. if (pNamedPipe->dwPipeMode & PIPE_NOWAIT)
  718. flags = (flags | O_NONBLOCK);
  719. else
  720. flags = (flags & ~(O_NONBLOCK));
  721. if (fcntl(fd, F_SETFL, flags) < 0)
  722. return FALSE;
  723. }
  724. if (lpMaxCollectionCount)
  725. {
  726. }
  727. if (lpCollectDataTimeout)
  728. {
  729. }
  730. return TRUE;
  731. }
  732. BOOL ImpersonateNamedPipeClient(HANDLE hNamedPipe)
  733. {
  734. WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
  735. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  736. return FALSE;
  737. }
  738. BOOL GetNamedPipeClientComputerNameA(HANDLE Pipe, LPCSTR ClientComputerName,
  739. ULONG ClientComputerNameLength)
  740. {
  741. WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
  742. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  743. return FALSE;
  744. }
  745. BOOL GetNamedPipeClientComputerNameW(HANDLE Pipe, LPCWSTR ClientComputerName,
  746. ULONG ClientComputerNameLength)
  747. {
  748. WLog_ERR(TAG, "%s: Not implemented", __FUNCTION__);
  749. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  750. return FALSE;
  751. }
  752. #endif