Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
8.9 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. mailslot.c
  5. Abstract:
  6. This module contains the Win32 Mailslot API
  7. Author:
  8. Manny Weiser (mannyw) 4-Mar-1991
  9. Revision History:
  10. --*/
  11. #include "basedll.h"
  12. HANDLE
  13. APIENTRY
  14. CreateMailslotW(
  15. IN LPCWSTR lpName,
  16. IN DWORD nMaxMessageSize,
  17. IN DWORD lReadTimeout,
  18. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL
  19. )
  20. /*++
  21. Routine Description:
  22. The create mailslot API creates a local mailslot and return a
  23. server-side handle to the mailslot.
  24. Arguments:
  25. lpName - The name of the mailslot. This must be a local mailslot
  26. name.
  27. nMaxMessageSize - The size (in bytes) of the largest message that
  28. can be written to the mailslot.
  29. lReadTimeout - The initial read timeout, in milliseconds. This
  30. is the amount of time a read operation will block waiting for
  31. a message to be written to the mailslot. This value can be
  32. changed with the SetMailslotInfo API.
  33. lpSecurityAttributes - An optional pointer to security information
  34. for this mailslot.
  35. Return Value:
  36. Returns one of the following:
  37. 0xFFFFFFFF --An error occurred. Call GetLastError for more
  38. information.
  39. Anything else --Returns a handle for use in the server side of
  40. subsequent mailslot operations.
  41. --*/
  42. {
  43. OBJECT_ATTRIBUTES objectAttributes;
  44. UNICODE_STRING fileName;
  45. LPWSTR filePart;
  46. RTL_RELATIVE_NAME relativeName;
  47. IO_STATUS_BLOCK ioStatusBlock;
  48. LARGE_INTEGER readTimeout;
  49. HANDLE handle;
  50. NTSTATUS status;
  51. PVOID freeBuffer;
  52. BOOLEAN TranslationStatus;
  53. RtlInitUnicodeString( &fileName, lpName );
  54. TranslationStatus = RtlDosPathNameToNtPathName_U(
  55. lpName,
  56. &fileName,
  57. &filePart,
  58. &relativeName
  59. );
  60. if ( !TranslationStatus ) {
  61. SetLastError(ERROR_PATH_NOT_FOUND);
  62. return INVALID_HANDLE_VALUE;
  63. }
  64. freeBuffer = fileName.Buffer;
  65. if ( relativeName.RelativeName.Length ) {
  66. fileName = *(PUNICODE_STRING)&relativeName.RelativeName;
  67. } else {
  68. relativeName.ContainingDirectory = NULL;
  69. }
  70. InitializeObjectAttributes(
  71. &objectAttributes,
  72. &fileName,
  73. OBJ_CASE_INSENSITIVE,
  74. relativeName.ContainingDirectory,
  75. NULL
  76. );
  77. if ( ARGUMENT_PRESENT(lpSecurityAttributes) ) {
  78. objectAttributes.SecurityDescriptor =
  79. lpSecurityAttributes->lpSecurityDescriptor;
  80. if ( lpSecurityAttributes->bInheritHandle ) {
  81. objectAttributes.Attributes |= OBJ_INHERIT;
  82. }
  83. }
  84. if (lReadTimeout == MAILSLOT_WAIT_FOREVER) {
  85. readTimeout.HighPart = 0xFFFFFFFF;
  86. readTimeout.LowPart = 0xFFFFFFFF;
  87. } else {
  88. readTimeout.QuadPart = - (LONGLONG)UInt32x32To64( lReadTimeout, 10 * 1000 );
  89. }
  90. status = NtCreateMailslotFile (
  91. &handle,
  92. GENERIC_READ | SYNCHRONIZE | WRITE_DAC,
  93. &objectAttributes,
  94. &ioStatusBlock,
  95. FILE_CREATE,
  96. 0,
  97. nMaxMessageSize,
  98. (PLARGE_INTEGER)&readTimeout
  99. );
  100. if ( status == STATUS_NOT_SUPPORTED ||
  101. status == STATUS_INVALID_DEVICE_REQUEST ) {
  102. //
  103. // The request must have been processed by some other device driver
  104. // (other than MSFS). Map the error to something reasonable.
  105. //
  106. status = STATUS_OBJECT_NAME_INVALID;
  107. }
  108. RtlFreeHeap( RtlProcessHeap(), 0, freeBuffer );
  109. if (!NT_SUCCESS(status)) {
  110. BaseSetLastNTError( status );
  111. return INVALID_HANDLE_VALUE;
  112. }
  113. return handle;
  114. }
  115. HANDLE
  116. APIENTRY
  117. CreateMailslotA(
  118. IN LPCSTR lpName,
  119. IN DWORD nMaxMessageSize,
  120. IN DWORD lReadTimeout,
  121. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL
  122. )
  123. {
  124. PUNICODE_STRING unicode;
  125. ANSI_STRING ansiString;
  126. NTSTATUS status;
  127. unicode = &NtCurrentTeb()->StaticUnicodeString;
  128. RtlInitAnsiString( &ansiString, lpName );
  129. status = RtlAnsiStringToUnicodeString( unicode, &ansiString, FALSE );
  130. if ( !NT_SUCCESS( status ) ) {
  131. if ( status == STATUS_BUFFER_OVERFLOW ) {
  132. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  133. } else {
  134. BaseSetLastNTError(status);
  135. }
  136. return INVALID_HANDLE_VALUE;
  137. }
  138. return ( CreateMailslotW( unicode->Buffer,
  139. nMaxMessageSize,
  140. lReadTimeout,
  141. lpSecurityAttributes
  142. ) );
  143. }
  144. BOOL
  145. APIENTRY
  146. GetMailslotInfo(
  147. IN HANDLE hMailslot,
  148. OUT LPDWORD lpMaxMessageSize OPTIONAL,
  149. OUT LPDWORD lpNextSize OPTIONAL,
  150. OUT LPDWORD lpMessageCount OPTIONAL,
  151. OUT LPDWORD lpReadTimeout OPTIONAL
  152. )
  153. /*++
  154. Routine Description:
  155. This function will return the requested information about the
  156. specified mailslot.
  157. Arguments:
  158. hMailslot - A handle to the mailslot.
  159. lpMaxMessageSize - If specified returns the size of the largest
  160. message that can be written to the mailslot.
  161. lpNextSize - If specified returns the size of the next message in
  162. the mailslot buffer. It will return MAILSLOT_NO_MESSAGE if
  163. there are no messages in the mailslot.
  164. lpMessageCount - If specified returns the number of unread message
  165. currently in the mailslot.
  166. lpReadTimeout - If specified returns the read timeout, in
  167. milliseconds.
  168. Return Value:
  169. TRUE - The operation was successful.
  170. FALSE/NULL - The operation failed. Extended error status is available
  171. using GetLastError.
  172. --*/
  173. {
  174. NTSTATUS status;
  175. IO_STATUS_BLOCK ioStatusBlock;
  176. FILE_MAILSLOT_QUERY_INFORMATION mailslotInfo;
  177. LARGE_INTEGER millisecondTimeout, tmp;
  178. status = NtQueryInformationFile( hMailslot,
  179. &ioStatusBlock,
  180. &mailslotInfo,
  181. sizeof( mailslotInfo ),
  182. FileMailslotQueryInformation );
  183. if ( !NT_SUCCESS( status ) ) {
  184. BaseSetLastNTError( status );
  185. return ( FALSE );
  186. }
  187. if ( ARGUMENT_PRESENT( lpMaxMessageSize ) ) {
  188. *lpMaxMessageSize = mailslotInfo.MaximumMessageSize;
  189. }
  190. if ( ARGUMENT_PRESENT( lpNextSize ) ) {
  191. *lpNextSize = mailslotInfo.NextMessageSize;
  192. }
  193. if ( ARGUMENT_PRESENT( lpMessageCount ) ) {
  194. *lpMessageCount = mailslotInfo.MessagesAvailable;
  195. }
  196. if ( ARGUMENT_PRESENT( lpReadTimeout ) ) {
  197. //
  198. // Convert read timeout from 100 ns intervals to milliseconds.
  199. // The readtime is currently negative, since it is a relative time.
  200. //
  201. if ( mailslotInfo.ReadTimeout.HighPart != 0xFFFFFFFF
  202. || mailslotInfo.ReadTimeout.LowPart != 0xFFFFFFFF ) {
  203. tmp.QuadPart = - mailslotInfo.ReadTimeout.QuadPart;
  204. millisecondTimeout = RtlExtendedLargeIntegerDivide(
  205. tmp,
  206. 10 * 1000,
  207. NULL );
  208. if ( millisecondTimeout.HighPart == 0 ) {
  209. *lpReadTimeout = millisecondTimeout.LowPart;
  210. } else {
  211. //
  212. // The millisecond calculation would overflow the dword.
  213. // Approximate a large number as best we can.
  214. //
  215. *lpReadTimeout = 0xFFFFFFFE;
  216. }
  217. } else {
  218. //
  219. // The mailslot timeout is infinite.
  220. //
  221. *lpReadTimeout = MAILSLOT_WAIT_FOREVER;
  222. }
  223. }
  224. return( TRUE );
  225. }
  226. BOOL
  227. APIENTRY
  228. SetMailslotInfo(
  229. IN HANDLE hMailslot,
  230. IN DWORD lReadTimeout
  231. )
  232. /*++
  233. Routine Description:
  234. This function will set the read timeout for the specified mailslot.
  235. Arguments:
  236. hMailslot - A handle to the mailslot.
  237. lReadTimeout - The new read timeout, in milliseconds.
  238. Return Value:
  239. TRUE - The operation was successful.
  240. FALSE/NULL - The operation failed. Extended error status is available
  241. using GetLastError.
  242. --*/
  243. {
  244. NTSTATUS status;
  245. IO_STATUS_BLOCK ioStatusBlock;
  246. FILE_MAILSLOT_SET_INFORMATION mailslotInfo;
  247. LARGE_INTEGER timeout;
  248. if ( lReadTimeout == MAILSLOT_WAIT_FOREVER ) {
  249. timeout.HighPart = 0xFFFFFFFF;
  250. timeout.LowPart = 0xFFFFFFFF;
  251. } else {
  252. timeout.QuadPart = - (LONGLONG)UInt32x32To64( lReadTimeout, 10 * 1000 );
  253. }
  254. mailslotInfo.ReadTimeout = &timeout;
  255. status = NtSetInformationFile( hMailslot,
  256. &ioStatusBlock,
  257. &mailslotInfo,
  258. sizeof( mailslotInfo ),
  259. FileMailslotSetInformation );
  260. if ( !NT_SUCCESS( status ) ) {
  261. BaseSetLastNTError( status );
  262. return ( FALSE );
  263. }
  264. return TRUE;
  265. }