namedPipeClient.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /**
  2. * WinPR: Windows Portable Runtime
  3. * File Functions
  4. *
  5. * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
  6. * Copyright 2014 Hewlett-Packard Development Company, L.P.
  7. * Copyright 2015 Thincast Technologies GmbH
  8. * Copyright 2015 bernhard.miklautz@thincast.com
  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/file.h>
  27. #ifdef HAVE_UNISTD_H
  28. #include <unistd.h>
  29. #endif
  30. #include "../log.h"
  31. #define TAG WINPR_TAG("file")
  32. #ifndef _WIN32
  33. #ifdef ANDROID
  34. #include <sys/vfs.h>
  35. #else
  36. #include <sys/statvfs.h>
  37. #endif
  38. #include "../handle/handle.h"
  39. #include "../pipe/pipe.h"
  40. static HANDLE_CREATOR _NamedPipeClientHandleCreator;
  41. static BOOL NamedPipeClientIsHandled(HANDLE handle)
  42. {
  43. WINPR_NAMED_PIPE* pFile = (WINPR_NAMED_PIPE*)handle;
  44. if (!pFile || (pFile->Type != HANDLE_TYPE_NAMED_PIPE) || (pFile == INVALID_HANDLE_VALUE))
  45. {
  46. SetLastError(ERROR_INVALID_HANDLE);
  47. return FALSE;
  48. }
  49. return TRUE;
  50. }
  51. static BOOL NamedPipeClientCloseHandle(HANDLE handle)
  52. {
  53. WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)handle;
  54. if (!NamedPipeClientIsHandled(handle))
  55. return FALSE;
  56. if (pNamedPipe->clientfd != -1)
  57. {
  58. // WLOG_DBG(TAG, "closing clientfd %d", pNamedPipe->clientfd);
  59. close(pNamedPipe->clientfd);
  60. }
  61. if (pNamedPipe->serverfd != -1)
  62. {
  63. // WLOG_DBG(TAG, "closing serverfd %d", pNamedPipe->serverfd);
  64. close(pNamedPipe->serverfd);
  65. }
  66. if (pNamedPipe->pfnUnrefNamedPipe)
  67. pNamedPipe->pfnUnrefNamedPipe(pNamedPipe);
  68. free(pNamedPipe->lpFileName);
  69. free(pNamedPipe->lpFilePath);
  70. free(pNamedPipe->name);
  71. free(pNamedPipe);
  72. return TRUE;
  73. }
  74. static int NamedPipeClientGetFd(HANDLE handle)
  75. {
  76. WINPR_NAMED_PIPE* file = (WINPR_NAMED_PIPE*)handle;
  77. if (!NamedPipeClientIsHandled(handle))
  78. return -1;
  79. if (file->ServerMode)
  80. return file->serverfd;
  81. else
  82. return file->clientfd;
  83. }
  84. static HANDLE_OPS ops = {
  85. NamedPipeClientIsHandled,
  86. NamedPipeClientCloseHandle,
  87. NamedPipeClientGetFd,
  88. NULL, /* CleanupHandle */
  89. NamedPipeRead,
  90. NULL, /* FileReadEx */
  91. NULL, /* FileReadScatter */
  92. NamedPipeWrite,
  93. NULL, /* FileWriteEx */
  94. NULL, /* FileWriteGather */
  95. NULL, /* FileGetFileSize */
  96. NULL, /* FlushFileBuffers */
  97. NULL, /* FileSetEndOfFile */
  98. NULL, /* FileSetFilePointer */
  99. NULL, /* SetFilePointerEx */
  100. NULL, /* FileLockFile */
  101. NULL, /* FileLockFileEx */
  102. NULL, /* FileUnlockFile */
  103. NULL, /* FileUnlockFileEx */
  104. NULL /* SetFileTime */
  105. };
  106. static HANDLE NamedPipeClientCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess,
  107. DWORD dwShareMode,
  108. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  109. DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
  110. HANDLE hTemplateFile)
  111. {
  112. char* name;
  113. int status;
  114. HANDLE hNamedPipe;
  115. struct sockaddr_un s;
  116. WINPR_NAMED_PIPE* pNamedPipe;
  117. if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
  118. {
  119. WLog_ERR(TAG, "WinPR %s does not support the FILE_FLAG_OVERLAPPED flag", __FUNCTION__);
  120. SetLastError(ERROR_NOT_SUPPORTED);
  121. return INVALID_HANDLE_VALUE;
  122. }
  123. if (!lpFileName)
  124. return INVALID_HANDLE_VALUE;
  125. if (!IsNamedPipeFileNameA(lpFileName))
  126. return INVALID_HANDLE_VALUE;
  127. name = GetNamedPipeNameWithoutPrefixA(lpFileName);
  128. if (!name)
  129. return INVALID_HANDLE_VALUE;
  130. free(name);
  131. pNamedPipe = (WINPR_NAMED_PIPE*)calloc(1, sizeof(WINPR_NAMED_PIPE));
  132. if (!pNamedPipe)
  133. {
  134. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  135. return INVALID_HANDLE_VALUE;
  136. }
  137. hNamedPipe = (HANDLE)pNamedPipe;
  138. WINPR_HANDLE_SET_TYPE_AND_MODE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE, WINPR_FD_READ);
  139. pNamedPipe->name = _strdup(lpFileName);
  140. if (!pNamedPipe->name)
  141. {
  142. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  143. free(pNamedPipe);
  144. return INVALID_HANDLE_VALUE;
  145. }
  146. pNamedPipe->dwOpenMode = 0;
  147. pNamedPipe->dwPipeMode = 0;
  148. pNamedPipe->nMaxInstances = 0;
  149. pNamedPipe->nOutBufferSize = 0;
  150. pNamedPipe->nInBufferSize = 0;
  151. pNamedPipe->nDefaultTimeOut = 0;
  152. pNamedPipe->dwFlagsAndAttributes = dwFlagsAndAttributes;
  153. pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpFileName);
  154. if (!pNamedPipe->lpFileName)
  155. {
  156. free((void*)pNamedPipe->name);
  157. free(pNamedPipe);
  158. return INVALID_HANDLE_VALUE;
  159. }
  160. pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpFileName);
  161. if (!pNamedPipe->lpFilePath)
  162. {
  163. free((void*)pNamedPipe->lpFileName);
  164. free((void*)pNamedPipe->name);
  165. free(pNamedPipe);
  166. return INVALID_HANDLE_VALUE;
  167. }
  168. pNamedPipe->clientfd = socket(PF_LOCAL, SOCK_STREAM, 0);
  169. pNamedPipe->serverfd = -1;
  170. pNamedPipe->ServerMode = FALSE;
  171. ZeroMemory(&s, sizeof(struct sockaddr_un));
  172. s.sun_family = AF_UNIX;
  173. sprintf_s(s.sun_path, ARRAYSIZE(s.sun_path), "%s", pNamedPipe->lpFilePath);
  174. status = connect(pNamedPipe->clientfd, (struct sockaddr*)&s, sizeof(struct sockaddr_un));
  175. pNamedPipe->ops = &ops;
  176. if (status != 0)
  177. {
  178. close(pNamedPipe->clientfd);
  179. free((char*)pNamedPipe->name);
  180. free((char*)pNamedPipe->lpFileName);
  181. free((char*)pNamedPipe->lpFilePath);
  182. free(pNamedPipe);
  183. return INVALID_HANDLE_VALUE;
  184. }
  185. if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
  186. {
  187. #if 0
  188. int flags = fcntl(pNamedPipe->clientfd, F_GETFL);
  189. if (flags != -1)
  190. fcntl(pNamedPipe->clientfd, F_SETFL, flags | O_NONBLOCK);
  191. #endif
  192. }
  193. return hNamedPipe;
  194. }
  195. HANDLE_CREATOR* GetNamedPipeClientHandleCreator(void)
  196. {
  197. _NamedPipeClientHandleCreator.IsHandled = IsNamedPipeFileNameA;
  198. _NamedPipeClientHandleCreator.CreateFileA = NamedPipeClientCreateFileA;
  199. return &_NamedPipeClientHandleCreator;
  200. }
  201. #endif
  202. /* Extended API */
  203. #define NAMED_PIPE_PREFIX_PATH "\\\\.\\pipe\\"
  204. BOOL IsNamedPipeFileNameA(LPCSTR lpName)
  205. {
  206. if (strncmp(lpName, NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH) - 1) != 0)
  207. return FALSE;
  208. return TRUE;
  209. }
  210. char* GetNamedPipeNameWithoutPrefixA(LPCSTR lpName)
  211. {
  212. char* lpFileName;
  213. if (!lpName)
  214. return NULL;
  215. if (!IsNamedPipeFileNameA(lpName))
  216. return NULL;
  217. lpFileName = _strdup(&lpName[strnlen(NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH))]);
  218. return lpFileName;
  219. }
  220. char* GetNamedPipeUnixDomainSocketBaseFilePathA()
  221. {
  222. char* lpTempPath;
  223. char* lpPipePath;
  224. lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
  225. if (!lpTempPath)
  226. return NULL;
  227. lpPipePath = GetCombinedPath(lpTempPath, ".pipe");
  228. free(lpTempPath);
  229. return lpPipePath;
  230. }
  231. char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName)
  232. {
  233. char* lpPipePath;
  234. char* lpFileName;
  235. char* lpFilePath;
  236. lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
  237. lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
  238. lpFilePath = GetCombinedPath(lpPipePath, (char*)lpFileName);
  239. free(lpPipePath);
  240. free(lpFileName);
  241. return lpFilePath;
  242. }
  243. int GetNamePipeFileDescriptor(HANDLE hNamedPipe)
  244. {
  245. #ifndef _WIN32
  246. int fd;
  247. WINPR_NAMED_PIPE* pNamedPipe;
  248. pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
  249. if (!pNamedPipe || pNamedPipe->Type != HANDLE_TYPE_NAMED_PIPE)
  250. return -1;
  251. fd = (pNamedPipe->ServerMode) ? pNamedPipe->serverfd : pNamedPipe->clientfd;
  252. return fd;
  253. #else
  254. return -1;
  255. #endif
  256. }