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.

1969 lines
58 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. namepipe.c
  5. Abstract:
  6. This module contains the Win32 Named Pipe API
  7. Author:
  8. Colin Watson (ColinW) 13-March-1991
  9. Revision History:
  10. --*/
  11. #include "basedll.h"
  12. #define DOS_LOCAL_PIPE_PREFIX L"\\\\.\\pipe\\"
  13. #define DOS_LOCAL_PIPE L"\\DosDevices\\pipe\\"
  14. #define DOS_REMOTE_PIPE L"\\DosDevices\\UNC\\"
  15. #define INVALID_PIPE_MODE_BITS ~(PIPE_READMODE_BYTE \
  16. | PIPE_READMODE_MESSAGE \
  17. | PIPE_WAIT \
  18. | PIPE_NOWAIT)
  19. BOOL
  20. NpGetUserNamep(
  21. HANDLE hNamedPipe,
  22. LPWSTR lpUserName,
  23. DWORD nMaxUserNameSize
  24. );
  25. typedef
  26. BOOL (WINAPI *REVERTTOSELF)( VOID );
  27. typedef
  28. BOOL (WINAPI *GETUSERNAMEW)( LPWSTR, LPDWORD );
  29. typedef
  30. BOOL (WINAPI *IMPERSONATENAMEDPIPECLIENT)( HANDLE );
  31. HANDLE
  32. APIENTRY
  33. CreateNamedPipeA(
  34. LPCSTR lpName,
  35. DWORD dwOpenMode,
  36. DWORD dwPipeMode,
  37. DWORD nMaxInstances,
  38. DWORD nOutBufferSize,
  39. DWORD nInBufferSize,
  40. DWORD nDefaultTimeOut,
  41. LPSECURITY_ATTRIBUTES lpSecurityAttributes
  42. )
  43. /*++
  44. Ansi thunk to CreateNamedPipeW.
  45. --*/
  46. {
  47. NTSTATUS Status;
  48. PUNICODE_STRING Unicode;
  49. ANSI_STRING AnsiString;
  50. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  51. RtlInitAnsiString(&AnsiString,lpName);
  52. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  53. if ( !NT_SUCCESS(Status) ) {
  54. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  55. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  56. }
  57. else {
  58. BaseSetLastNTError(Status);
  59. }
  60. return INVALID_HANDLE_VALUE;
  61. }
  62. return CreateNamedPipeW(
  63. (LPCWSTR)Unicode->Buffer,
  64. dwOpenMode,
  65. dwPipeMode,
  66. nMaxInstances,
  67. nOutBufferSize,
  68. nInBufferSize,
  69. nDefaultTimeOut,
  70. lpSecurityAttributes);
  71. }
  72. HANDLE
  73. APIENTRY
  74. CreateNamedPipeW(
  75. LPCWSTR lpName,
  76. DWORD dwOpenMode,
  77. DWORD dwPipeMode,
  78. DWORD nMaxInstances,
  79. DWORD nOutBufferSize,
  80. DWORD nInBufferSize,
  81. DWORD nDefaultTimeOut,
  82. LPSECURITY_ATTRIBUTES lpSecurityAttributes
  83. )
  84. /*++
  85. Parameters:
  86. lpName --Supplies the pipe name Documented in "Pipe Names" section
  87. earlier. This must be a local name.
  88. dwOpenMode --Supplies the set of flags that define the mode which the
  89. pipe is to be opened with. The open mode consists of access
  90. flags (one of three values) logically ORed with a writethrough
  91. flag (one of two values) and an overlapped flag (one of two
  92. values), as described below.
  93. dwOpenMode Flags:
  94. PIPE_ACCESS_DUPLEX --Pipe is bidirectional. (This is
  95. semantically equivalent to calling CreateFile with access
  96. flags of GENERIC_READ | GENERIC_WRITE.)
  97. PIPE_ACCESS_INBOUND --Data goes from client to server only.
  98. (This is semantically equivalent to calling CreateFile with
  99. access flags of GENERIC_READ.)
  100. PIPE_ACCESS_OUTBOUND --Data goes from server to client only.
  101. (This is semantically equivalent to calling CreateFile with
  102. access flags of GENERIC_WRITE.)
  103. PIPE_WRITETHROUGH --The redirector is not permitted to delay the
  104. transmission of data to the named pipe buffer on the remote
  105. server. This disables a performance enhancement for
  106. applications that need synchronization with every write
  107. operation.
  108. FILE_FLAG_OVERLAPPED --Indicates that the system should
  109. initialize the file so that ReadFile, WriteFile and other
  110. operations that may take a significant time to process will
  111. return ERROR_IO_PENDING. An event will be set to the
  112. signalled state when the operation completes.
  113. FILE_FLAG_WRITETHROUGH -- No intermediate buffering.
  114. WRITE_DAC -- Standard security desired access
  115. WRITE_OWNER -- ditto
  116. ACCESS_SYSTEM_SECURITY -- ditto
  117. dwPipeMode --Supplies the pipe-specific modes (as flags) of the pipe.
  118. This parameter is a combination of a read-mode flag, a type flag,
  119. and a wait flag.
  120. dwPipeMode Flags:
  121. PIPE_WAIT --Blocking mode is to be used for this handle.
  122. PIPE_NOWAIT --Nonblocking mode is to be used for this handle.
  123. PIPE_READMODE_BYTE --Read pipe as a byte stream.
  124. PIPE_READMODE_MESSAGE --Read pipe as a message stream. Note that
  125. this is not allowed with PIPE_TYPE_BYTE.
  126. PIPE_TYPE_BYTE --Pipe is a byte-stream pipe. Note that this is
  127. not allowed with PIPE_READMODE_MESSAGE.
  128. PIPE_TYPE_MESSAGE --Pipe is a message-stream pipe.
  129. nMaxInstances --Gives the maximum number of instances for this pipe.
  130. Acceptable values are 1 to PIPE_UNLIMITED_INSTANCES-1 and
  131. PIPE_UNLIMITED_INSTANCES.
  132. nMaxInstances Special Values:
  133. PIPE_UNLIMITED_INSTANCES --Unlimited instances of this pipe can
  134. be created.
  135. nOutBufferSize --Specifies an advisory on the number of bytes to
  136. reserve for the outgoing buffer.
  137. nInBufferSize --Specifies an advisory on the number of bytes to
  138. reserve for the incoming buffer.
  139. nDefaultTimeOut -- Specifies an optional pointer to a timeout value
  140. that is to be used if a timeout value is not specified when
  141. waiting for an instance of a named pipe. This parameter is only
  142. meaningful when the first instance of a named pipe is created. If
  143. neither CreateNamedPipe or WaitNamedPipe specify a timeout 50
  144. milliseconds will be used.
  145. lpSecurityAttributes --An optional parameter that, if present and
  146. supported on the target system, supplies a security descriptor
  147. for the named pipe. This parameter includes an inheritance flag
  148. for the handle. If this parameter is not present, the handle is
  149. not inherited by child processes.
  150. Return Value:
  151. Returns one of the following:
  152. INVALID_HANDLE_VALUE --An error occurred. Call GetLastError for more
  153. information.
  154. Anything else --Returns a handle for use in the server side of
  155. subsequent named pipe operations.
  156. --*/
  157. {
  158. NTSTATUS Status;
  159. OBJECT_ATTRIBUTES Obja;
  160. HANDLE Handle;
  161. UNICODE_STRING FileName;
  162. IO_STATUS_BLOCK IoStatusBlock;
  163. BOOLEAN TranslationStatus;
  164. LARGE_INTEGER Timeout;
  165. RTL_RELATIVE_NAME RelativeName;
  166. PVOID FreeBuffer;
  167. LPWSTR FilePart;
  168. ULONG CreateFlags;
  169. ULONG DesiredAccess;
  170. ULONG ShareAccess;
  171. ULONG MaxInstances;
  172. SECURITY_DESCRIPTOR SecurityDescriptor;
  173. PACL DefaultAcl = NULL;
  174. if ((nMaxInstances == 0) ||
  175. (nMaxInstances > PIPE_UNLIMITED_INSTANCES)) {
  176. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  177. return INVALID_HANDLE_VALUE;
  178. }
  179. // Convert Win32 maximum Instances to Nt maximum instances.
  180. MaxInstances = (nMaxInstances == PIPE_UNLIMITED_INSTANCES)?
  181. 0xffffffff : nMaxInstances;
  182. TranslationStatus = RtlDosPathNameToNtPathName_U(
  183. lpName,
  184. &FileName,
  185. &FilePart,
  186. &RelativeName
  187. );
  188. if ( !TranslationStatus ) {
  189. SetLastError(ERROR_PATH_NOT_FOUND);
  190. return INVALID_HANDLE_VALUE;
  191. }
  192. FreeBuffer = FileName.Buffer;
  193. if ( RelativeName.RelativeName.Length ) {
  194. FileName = *(PUNICODE_STRING)&RelativeName.RelativeName;
  195. }
  196. else {
  197. RelativeName.ContainingDirectory = NULL;
  198. }
  199. InitializeObjectAttributes(
  200. &Obja,
  201. &FileName,
  202. OBJ_CASE_INSENSITIVE,
  203. RelativeName.ContainingDirectory,
  204. NULL
  205. );
  206. if ( ARGUMENT_PRESENT(lpSecurityAttributes) ) {
  207. Obja.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
  208. if ( lpSecurityAttributes->bInheritHandle ) {
  209. Obja.Attributes |= OBJ_INHERIT;
  210. }
  211. }
  212. if (Obja.SecurityDescriptor == NULL) {
  213. //
  214. // Apply default security if none specified (bug 131090)
  215. //
  216. Status = RtlDefaultNpAcl( &DefaultAcl );
  217. if (NT_SUCCESS( Status )) {
  218. RtlCreateSecurityDescriptor( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
  219. RtlSetDaclSecurityDescriptor( &SecurityDescriptor, TRUE, DefaultAcl, FALSE );
  220. Obja.SecurityDescriptor = &SecurityDescriptor;
  221. } else {
  222. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  223. BaseSetLastNTError(Status);
  224. return INVALID_HANDLE_VALUE;
  225. }
  226. }
  227. // End of code common with fileopcr.c CreateFile()
  228. CreateFlags = (dwOpenMode & FILE_FLAG_WRITE_THROUGH ? FILE_WRITE_THROUGH : 0 );
  229. CreateFlags |= (dwOpenMode & FILE_FLAG_OVERLAPPED ? 0 : FILE_SYNCHRONOUS_IO_NONALERT);
  230. //
  231. // Determine the timeout. Convert from milliseconds to an Nt delta time
  232. //
  233. if ( nDefaultTimeOut ) {
  234. Timeout.QuadPart = - (LONGLONG)UInt32x32To64( 10 * 1000, nDefaultTimeOut );
  235. }
  236. else {
  237. // Default timeout is 50 Milliseconds
  238. Timeout.QuadPart = -10 * 1000 * 50;
  239. }
  240. // Check no reserved bits are set by mistake.
  241. if (( dwOpenMode & ~(PIPE_ACCESS_DUPLEX |
  242. FILE_FLAG_OVERLAPPED | FILE_FLAG_WRITE_THROUGH |
  243. FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC |
  244. WRITE_OWNER | ACCESS_SYSTEM_SECURITY ))||
  245. ( dwPipeMode & ~(PIPE_NOWAIT | PIPE_READMODE_MESSAGE |
  246. PIPE_TYPE_MESSAGE ))) {
  247. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  248. if (DefaultAcl != NULL) {
  249. RtlFreeHeap(RtlProcessHeap(),0,DefaultAcl);
  250. }
  251. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  252. return INVALID_HANDLE_VALUE;
  253. }
  254. //
  255. // Translate the open mode into a sharemode to restrict the clients access
  256. // and derive the appropriate local desired access.
  257. //
  258. switch ( dwOpenMode & PIPE_ACCESS_DUPLEX ) {
  259. case PIPE_ACCESS_INBOUND:
  260. ShareAccess = FILE_SHARE_WRITE;
  261. DesiredAccess = GENERIC_READ;
  262. break;
  263. case PIPE_ACCESS_OUTBOUND:
  264. ShareAccess = FILE_SHARE_READ;
  265. DesiredAccess = GENERIC_WRITE;
  266. break;
  267. case PIPE_ACCESS_DUPLEX:
  268. ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
  269. DesiredAccess = GENERIC_READ | GENERIC_WRITE;
  270. break;
  271. default:
  272. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  273. if (DefaultAcl != NULL) {
  274. RtlFreeHeap(RtlProcessHeap(),0,DefaultAcl);
  275. }
  276. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  277. return INVALID_HANDLE_VALUE;
  278. }
  279. DesiredAccess |= SYNCHRONIZE |
  280. ( dwOpenMode & (WRITE_DAC | WRITE_OWNER | ACCESS_SYSTEM_SECURITY ));
  281. Status = NtCreateNamedPipeFile (
  282. &Handle,
  283. DesiredAccess,
  284. &Obja,
  285. &IoStatusBlock,
  286. ShareAccess,
  287. (dwOpenMode & FILE_FLAG_FIRST_PIPE_INSTANCE) ?
  288. FILE_CREATE : FILE_OPEN_IF, // Create first instance or subsequent
  289. CreateFlags, // Create Options
  290. dwPipeMode & PIPE_TYPE_MESSAGE ?
  291. FILE_PIPE_MESSAGE_TYPE : FILE_PIPE_BYTE_STREAM_TYPE,
  292. dwPipeMode & PIPE_READMODE_MESSAGE ?
  293. FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE,
  294. dwPipeMode & PIPE_NOWAIT ?
  295. FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION,
  296. MaxInstances, // Max instances
  297. nInBufferSize, // Inbound quota
  298. nOutBufferSize, // Outbound quota
  299. (PLARGE_INTEGER)&Timeout
  300. );
  301. if ( Status == STATUS_NOT_SUPPORTED ||
  302. Status == STATUS_INVALID_DEVICE_REQUEST ) {
  303. //
  304. // The request must have been processed by some other device driver
  305. // (other than NPFS). Map the error to something reasonable.
  306. //
  307. Status = STATUS_OBJECT_NAME_INVALID;
  308. }
  309. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  310. if (DefaultAcl != NULL) {
  311. RtlFreeHeap(RtlProcessHeap(),0,DefaultAcl);
  312. }
  313. if ( !NT_SUCCESS(Status) ) {
  314. BaseSetLastNTError(Status);
  315. return INVALID_HANDLE_VALUE;
  316. }
  317. return Handle;
  318. }
  319. BOOL
  320. APIENTRY
  321. ConnectNamedPipe(
  322. HANDLE hNamedPipe,
  323. LPOVERLAPPED lpOverlapped
  324. )
  325. /*++
  326. Routine Description:
  327. The ConnectNamedPipe function is used by the server side of a named pipe
  328. to wait for a client to connect to the named pipe with a CreateFile
  329. request. The handle provided with the call to ConnectNamedPipe must have
  330. been previously returned by a successful call to CreateNamedPipe. The pipe
  331. must be in the disconnected, listening or connected states for
  332. ConnectNamedPipe to succeed.
  333. The behavior of this call depends on the blocking/nonblocking mode selected
  334. with the PIPE_WAIT/PIPE_NOWAIT flags when the server end of the pipe was
  335. created with CreateNamedPipe.
  336. If blocking mode is specified, ConnectNamedPipe will change the state from
  337. disconnected to listening and block. When a client connects with a
  338. CreateFile, the state will be changed from listening to connected and the
  339. ConnectNamedPipe returns TRUE. When the file handle is created with
  340. FILE_FLAG_OVERLAPPED on a blocking mode pipe, the lpOverlapped parameter
  341. can be specified. This allows the caller to continue processing while the
  342. ConnectNamedPipe API awaits a connection. When the pipe enters the
  343. signalled state the event is set to the signalled state.
  344. When nonblocking is specified ConnectNamedPipe will not block. On the
  345. first call the state will change from disconnected to listening. When a
  346. client connects with an Open the state will be changed from listening to
  347. connected. The ConnectNamedPipe will return FALSE (with GetLastError
  348. returning ERROR_PIPE_LISTENING) until the state is changed to the listening
  349. state.
  350. Arguments:
  351. hNamedPipe - Supplies a Handle to the server side of a named pipe.
  352. lpOverlapped - Supplies an overlap structure to be used with the request.
  353. If NULL then the API will not return until the operation completes. When
  354. FILE_FLAG_OVERLAPPED is specified when the handle was created,
  355. ConnectNamedPipe may return ERROR_IO_PENDING to allow the caller to
  356. continue processing while the operation completes. The event (or File
  357. handle if hEvent=NULL) will be set to the not signalled state before
  358. ERROR_IO_PENDING is returned. The event will be set to the signalled
  359. state upon completion of the request. GetOverlappedResult is used to
  360. determine the error status.
  361. Return Value:
  362. TRUE -- The operation was successful, the pipe is in the
  363. connected state.
  364. FALSE -- The operation failed. Extended error status is available using
  365. GetLastError.
  366. --*/
  367. {
  368. NTSTATUS Status;
  369. IO_STATUS_BLOCK Iosb;
  370. if ( lpOverlapped ) {
  371. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  372. }
  373. Status = NtFsControlFile(
  374. hNamedPipe,
  375. (lpOverlapped==NULL)? NULL : lpOverlapped->hEvent,
  376. NULL, // ApcRoutine
  377. lpOverlapped ? ((ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped) : NULL,
  378. (lpOverlapped==NULL) ? &Iosb : (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  379. FSCTL_PIPE_LISTEN,
  380. NULL, // InputBuffer
  381. 0, // InputBufferLength,
  382. NULL, // OutputBuffer
  383. 0 // OutputBufferLength
  384. );
  385. if ( lpOverlapped == NULL && Status == STATUS_PENDING) {
  386. // Operation must complete before return & Iosb destroyed
  387. Status = NtWaitForSingleObject( hNamedPipe, FALSE, NULL );
  388. if ( NT_SUCCESS(Status)) {
  389. Status = Iosb.Status;
  390. }
  391. }
  392. if (NT_SUCCESS( Status ) && Status != STATUS_PENDING ) {
  393. return TRUE;
  394. }
  395. else
  396. {
  397. BaseSetLastNTError(Status);
  398. return FALSE;
  399. }
  400. }
  401. BOOL
  402. APIENTRY
  403. DisconnectNamedPipe(
  404. HANDLE hNamedPipe
  405. )
  406. /*++
  407. Routine Description:
  408. The DisconnectNamedPipe function can be used by the server side of a named
  409. pipe to force the client side to close the client side's handle. (Note that
  410. the client side must still call CloseFile to do this.) The client will
  411. receive an error the next time it attempts to access the pipe. Disconnecting
  412. the pipe may cause data to be lost before the client reads it. (If the
  413. application wants to make sure that data is not lost, the serving side
  414. should call FlushFileBuffers before calling DisconnectNamedPipe.)
  415. Arguments:
  416. hNamedPipe - Supplies a Handle to the server side of a named pipe.
  417. Return Value:
  418. TRUE -- The operation was successful, the pipe is in the disconnected state.
  419. FALSE -- The operation failed. Extended error status is available using
  420. GetLastError.
  421. --*/
  422. {
  423. NTSTATUS Status;
  424. IO_STATUS_BLOCK Iosb;
  425. Status = NtFsControlFile(
  426. hNamedPipe,
  427. NULL,
  428. NULL, // ApcRoutine
  429. NULL, // ApcContext
  430. &Iosb,
  431. FSCTL_PIPE_DISCONNECT,
  432. NULL, // InputBuffer
  433. 0, // InputBufferLength,
  434. NULL, // OutputBuffer
  435. 0 // OutputBufferLength
  436. );
  437. if ( Status == STATUS_PENDING) {
  438. // Operation must complete before return & Iosb destroyed
  439. Status = NtWaitForSingleObject( hNamedPipe, FALSE, NULL );
  440. if ( NT_SUCCESS(Status)) {
  441. Status = Iosb.Status;
  442. }
  443. }
  444. if (NT_SUCCESS( Status )) {
  445. return TRUE;
  446. }
  447. else
  448. {
  449. BaseSetLastNTError(Status);
  450. return FALSE;
  451. }
  452. }
  453. BOOL
  454. APIENTRY
  455. GetNamedPipeHandleStateA(
  456. HANDLE hNamedPipe,
  457. LPDWORD lpState,
  458. LPDWORD lpCurInstances,
  459. LPDWORD lpMaxCollectionCount,
  460. LPDWORD lpCollectDataTimeout,
  461. LPSTR lpUserName,
  462. DWORD nMaxUserNameSize
  463. )
  464. /*++
  465. Routine Description:
  466. Ansi thunk to GetNamedPipeHandleStateW
  467. ---*/
  468. {
  469. if ( ARGUMENT_PRESENT( lpUserName ) ) {
  470. BOOL b;
  471. NTSTATUS Status;
  472. ANSI_STRING AnsiUserName;
  473. UNICODE_STRING UnicodeUserName;
  474. UnicodeUserName.MaximumLength = (USHORT)(nMaxUserNameSize << 1);
  475. UnicodeUserName.Buffer = RtlAllocateHeap(
  476. RtlProcessHeap(),MAKE_TAG( TMP_TAG ),
  477. UnicodeUserName.MaximumLength
  478. );
  479. AnsiUserName.Buffer = lpUserName;
  480. AnsiUserName.MaximumLength = (USHORT)nMaxUserNameSize;
  481. if ( !UnicodeUserName.Buffer ) {
  482. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  483. return FALSE;
  484. }
  485. b = GetNamedPipeHandleStateW(
  486. hNamedPipe,
  487. lpState,
  488. lpCurInstances,
  489. lpMaxCollectionCount,
  490. lpCollectDataTimeout,
  491. UnicodeUserName.Buffer,
  492. UnicodeUserName.MaximumLength/2);
  493. if ( b ) {
  494. // Set length correctly in UnicodeUserName
  495. RtlInitUnicodeString(
  496. &UnicodeUserName,
  497. UnicodeUserName.Buffer
  498. );
  499. Status = RtlUnicodeStringToAnsiString(
  500. &AnsiUserName,
  501. &UnicodeUserName,
  502. FALSE
  503. );
  504. if ( !NT_SUCCESS(Status) ) {
  505. BaseSetLastNTError(Status);
  506. b = FALSE;
  507. }
  508. }
  509. if ( UnicodeUserName.Buffer ) {
  510. RtlFreeHeap(RtlProcessHeap(),0,UnicodeUserName.Buffer);
  511. }
  512. return b;
  513. }
  514. else {
  515. return GetNamedPipeHandleStateW(
  516. hNamedPipe,
  517. lpState,
  518. lpCurInstances,
  519. lpMaxCollectionCount,
  520. lpCollectDataTimeout,
  521. NULL,
  522. 0);
  523. }
  524. }
  525. BOOL
  526. APIENTRY
  527. GetNamedPipeHandleStateW(
  528. HANDLE hNamedPipe,
  529. LPDWORD lpState,
  530. LPDWORD lpCurInstances,
  531. LPDWORD lpMaxCollectionCount,
  532. LPDWORD lpCollectDataTimeout,
  533. LPWSTR lpUserName,
  534. DWORD nMaxUserNameSize
  535. )
  536. /*++
  537. Routine Description:
  538. The GetNamedPipeHandleState function retrieves information about a given
  539. named pipe handle. The information returned by this function can vary during
  540. the lifetime of an instance of a named pipe. The handle must be created with
  541. the GENERIC_READ access rights.
  542. Arguments:
  543. hNamedPipe - Supplies the handle of an opened named pipe.
  544. lpState - An optional parameter that if non-null, points to a DWORD which
  545. will be set with flags indicating the current state of the handle.
  546. The following flags may be specified:
  547. PIPE_NOWAIT
  548. Nonblocking mode is to be used for this handle.
  549. PIPE_READMODE_MESSAGE
  550. Read the pipe as a message stream. If this flag is not set, the pipe is
  551. read as a byte stream.
  552. lpCurInstances - An optional parameter that if non-null, points to a DWORD
  553. which will be set with the number of current pipe instances.
  554. lpMaxCollectionCount - If non-null, this points to a DWORD which will be
  555. set to the maximum number of bytes that will be collected on the clients
  556. machine before transmission to the server. This parameter must be NULL
  557. on a handle to the server end of a named pipe or when client and
  558. server applications are on the same machine.
  559. lpCollectDataTimeout - If non-null, this points to a DWORD which will be
  560. set to the maximum time (in milliseconds) that can pass before a
  561. remote named pipe transfers information over the network. This parameter
  562. must be NULL if the handle is for the server end of a named pipe or
  563. when client and server applications are on the same machine.
  564. lpUserName - An optional parameter on the server end of a named pipe.
  565. Points to an area which will be filled-in with the null-terminated
  566. string containing the name of the username of the client application.
  567. This parameter is invalid if not NULL on a handle to a client end of
  568. a named pipe.
  569. nMaxUserNameSize - Size in characters of the memory allocated at lpUserName.
  570. Ignored if lpUserName is NULL.
  571. Return Value:
  572. TRUE -- The operation was successful.
  573. FALSE -- The operation failed. Extended error status is available using
  574. GetLastError.
  575. --*/
  576. {
  577. IO_STATUS_BLOCK Iosb;
  578. NTSTATUS Status;
  579. if ( ARGUMENT_PRESENT( lpState ) ){
  580. FILE_PIPE_INFORMATION Common;
  581. Status = NtQueryInformationFile(
  582. hNamedPipe,
  583. &Iosb,
  584. &Common,
  585. sizeof(FILE_PIPE_INFORMATION),
  586. FilePipeInformation );
  587. if ( !NT_SUCCESS(Status) ) {
  588. BaseSetLastNTError(Status);
  589. return FALSE;
  590. }
  591. *lpState = (Common.CompletionMode == FILE_PIPE_QUEUE_OPERATION) ?
  592. PIPE_WAIT : PIPE_NOWAIT;
  593. *lpState |= (Common.ReadMode == FILE_PIPE_BYTE_STREAM_MODE) ?
  594. PIPE_READMODE_BYTE : PIPE_READMODE_MESSAGE;
  595. }
  596. if (ARGUMENT_PRESENT( lpCurInstances ) ){
  597. FILE_PIPE_LOCAL_INFORMATION Local;
  598. Status = NtQueryInformationFile(
  599. hNamedPipe,
  600. &Iosb,
  601. &Local,
  602. sizeof(FILE_PIPE_LOCAL_INFORMATION),
  603. FilePipeLocalInformation );
  604. if ( !NT_SUCCESS(Status) ) {
  605. BaseSetLastNTError(Status);
  606. return FALSE;
  607. }
  608. if (Local.CurrentInstances >= PIPE_UNLIMITED_INSTANCES) {
  609. *lpCurInstances = PIPE_UNLIMITED_INSTANCES;
  610. }
  611. else {
  612. *lpCurInstances = Local.CurrentInstances;
  613. }
  614. }
  615. if (ARGUMENT_PRESENT( lpMaxCollectionCount ) ||
  616. ARGUMENT_PRESENT( lpCollectDataTimeout ) ) {
  617. FILE_PIPE_REMOTE_INFORMATION Remote;
  618. Status = NtQueryInformationFile(
  619. hNamedPipe,
  620. &Iosb,
  621. &Remote,
  622. sizeof(FILE_PIPE_REMOTE_INFORMATION),
  623. FilePipeRemoteInformation );
  624. if ( !NT_SUCCESS(Status) ) {
  625. BaseSetLastNTError(Status);
  626. return FALSE;
  627. }
  628. if (ARGUMENT_PRESENT( lpMaxCollectionCount ) ) {
  629. *lpMaxCollectionCount = Remote.MaximumCollectionCount;
  630. }
  631. if (ARGUMENT_PRESENT( lpCollectDataTimeout ) ) {
  632. LARGE_INTEGER TimeWorkspace;
  633. LARGE_INTEGER LiTemporary;
  634. // Convert delta NT LARGE_INTEGER to milliseconds delay
  635. LiTemporary.QuadPart = -Remote.CollectDataTime.QuadPart;
  636. TimeWorkspace = RtlExtendedLargeIntegerDivide (
  637. LiTemporary,
  638. 10000,
  639. NULL ); // Not interested in any remainder
  640. if ( TimeWorkspace.HighPart ) {
  641. //
  642. // Timeout larger than we can return- but not infinity.
  643. // Must have been set with the direct NT Interface.
  644. //
  645. *lpCollectDataTimeout = 0xfffffffe; // Maximum we can set
  646. }
  647. else {
  648. *lpCollectDataTimeout = TimeWorkspace.LowPart;
  649. }
  650. }
  651. }
  652. if ( ARGUMENT_PRESENT( lpUserName ) ) {
  653. return NpGetUserNamep(hNamedPipe, lpUserName, nMaxUserNameSize );
  654. }
  655. return TRUE;
  656. }
  657. BOOL
  658. NpGetUserNamep(
  659. HANDLE hNamedPipe,
  660. LPWSTR lpUserName,
  661. DWORD nMaxUserNameSize
  662. )
  663. /*++
  664. Routine Description:
  665. The NpGetUserNamep function retrieves user name for the client at the other
  666. end of the named pipe indicated by the handle.
  667. Arguments:
  668. hNamedPipe - Supplies the handle of an opened named pipe.
  669. lpUserName - Points to an area which will be filled-in with the null-terminated
  670. string containing the name of the username of the client application.
  671. This parameter is invalid if not NULL on a handle to a client end of
  672. a named pipe.
  673. nMaxUserNameSize - Size in characters of the memory allocated at lpUserName.
  674. Return Value:
  675. TRUE -- The operation was successful.
  676. FALSE -- The operation failed. Extended error status is available using
  677. GetLastError.
  678. --*/
  679. {
  680. HANDLE hToken;
  681. NTSTATUS Status;
  682. DWORD Size = nMaxUserNameSize;
  683. BOOL res;
  684. HANDLE advapi32;
  685. REVERTTOSELF RevertToSelfp;
  686. GETUSERNAMEW GetUserNameWp;
  687. IMPERSONATENAMEDPIPECLIENT ImpersonateNamedPipeClientp;
  688. advapi32 = LoadLibraryW(AdvapiDllString);
  689. if (advapi32 == NULL ) {
  690. return FALSE;
  691. }
  692. RevertToSelfp = (REVERTTOSELF)GetProcAddress(advapi32,"RevertToSelf");
  693. if ( RevertToSelfp == NULL) {
  694. FreeLibrary(advapi32);
  695. return FALSE;
  696. }
  697. GetUserNameWp = (GETUSERNAMEW)GetProcAddress(advapi32,"GetUserNameW");
  698. if ( GetUserNameWp == NULL) {
  699. FreeLibrary(advapi32);
  700. return FALSE;
  701. }
  702. ImpersonateNamedPipeClientp = (IMPERSONATENAMEDPIPECLIENT)GetProcAddress(advapi32,"ImpersonateNamedPipeClient");
  703. if ( ImpersonateNamedPipeClientp == NULL) {
  704. FreeLibrary(advapi32);
  705. return FALSE;
  706. }
  707. // Save whoever the thread is currently impersonating.
  708. Status = NtOpenThreadToken(
  709. NtCurrentThread(),
  710. TOKEN_IMPERSONATE,
  711. TRUE,
  712. &hToken
  713. );
  714. if (!(ImpersonateNamedPipeClientp)( hNamedPipe )) {
  715. if (NT_SUCCESS (Status)) {
  716. if (!CloseHandle (hToken)) {
  717. ASSERTMSG ("CloseHandle failed for previously opened token", 0);
  718. }
  719. }
  720. FreeLibrary(advapi32);
  721. return FALSE;
  722. }
  723. res = (GetUserNameWp)( lpUserName, &Size );
  724. if ( !NT_SUCCESS( Status ) ) {
  725. // We were not impersonating anyone
  726. (RevertToSelfp)();
  727. } else {
  728. //
  729. // Set thread back to whoever it was originally impersonating.
  730. // An error on this API overrides any error from GetUserNameW
  731. //
  732. Status = NtSetInformationThread(
  733. NtCurrentThread(),
  734. ThreadImpersonationToken,
  735. (PVOID)&hToken,
  736. (ULONG)sizeof(HANDLE)
  737. );
  738. if (!CloseHandle (hToken)) {
  739. ASSERTMSG ("CloseHandle failed for previously opened token", 0);
  740. }
  741. if ( !NT_SUCCESS(Status) ) {
  742. BaseSetLastNTError(Status);
  743. FreeLibrary(advapi32);
  744. return FALSE;
  745. }
  746. }
  747. FreeLibrary(advapi32);
  748. return res;
  749. }
  750. BOOL
  751. APIENTRY
  752. SetNamedPipeHandleState(
  753. HANDLE hNamedPipe,
  754. LPDWORD lpMode,
  755. LPDWORD lpMaxCollectionCount,
  756. LPDWORD lpCollectDataTimeout
  757. )
  758. /*++
  759. Routine Description:
  760. The SetNamedPipeHandleState function is used to set the read
  761. mode and the blocking mode of a named pipe. On the client end
  762. of a remote named pipe this function can also control local
  763. buffering. The handle must be created with the GENERIC_WRITE
  764. access rights.
  765. Arguments:
  766. hNamedPipe - Supplies a handle to a named pipe.
  767. lpMode - If non-null, this points to a DWORD which supplies the new
  768. mode. The mode is a combination of a read-mode flag and a wait flag.
  769. The following values may be used:
  770. PIPE_READMODE_BYTE
  771. Read pipe as a byte stream.
  772. PIPE_READMODE_MESSAGE
  773. Read pipe as a message stream.
  774. PIPE_WAIT
  775. Blocking mode is to be used for this handle.
  776. PIPE_NOWAIT
  777. Nonblocking mode is to be used for this handle.
  778. lpMaxCollectionCount - If non-null, this points to
  779. a DWORD which supplies the maximum number of
  780. bytes that will be collected on the client machine before
  781. transmission to the server. This parameter must be NULL on
  782. a handle to the server end of a named pipe or when client
  783. and server applications are on the same machine. This parameter
  784. is ignored if the client specified write through
  785. when the handle was created.
  786. lpCollectDataTimeout - If non-null, this points to a DWORD which
  787. supplies the maximum time (in milliseconds) that can pass before
  788. a remote named pipe transfers information over the network. This
  789. parameter must be NULL if the handle is for the server end of a
  790. named pipe or when client and server applications are on the same
  791. machine. This parameter is ignored if the client specified write
  792. through when the handle was created.
  793. Return Value:
  794. TRUE -- The operation was successful.
  795. FALSE -- The operation failed. Extended error status is available using
  796. GetLastError.
  797. --*/
  798. {
  799. IO_STATUS_BLOCK Iosb;
  800. NTSTATUS Status;
  801. if ( ARGUMENT_PRESENT( lpMode ) ){
  802. FILE_PIPE_INFORMATION Common;
  803. if (*lpMode & INVALID_PIPE_MODE_BITS) {
  804. SetLastError(ERROR_INVALID_PARAMETER);
  805. return FALSE;
  806. }
  807. Common.ReadMode = ( *lpMode & PIPE_READMODE_MESSAGE ) ?
  808. FILE_PIPE_MESSAGE_MODE: FILE_PIPE_BYTE_STREAM_MODE;
  809. Common.CompletionMode = ( *lpMode & PIPE_NOWAIT ) ?
  810. FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION;
  811. Status = NtSetInformationFile(
  812. hNamedPipe,
  813. &Iosb,
  814. &Common,
  815. sizeof(FILE_PIPE_INFORMATION),
  816. FilePipeInformation );
  817. if ( !NT_SUCCESS(Status) ) {
  818. BaseSetLastNTError(Status);
  819. return FALSE;
  820. }
  821. }
  822. if ( ARGUMENT_PRESENT( lpMaxCollectionCount ) ||
  823. ARGUMENT_PRESENT( lpCollectDataTimeout ) ){
  824. FILE_PIPE_REMOTE_INFORMATION Remote;
  825. if ( ( lpMaxCollectionCount == NULL ) ||
  826. ( lpCollectDataTimeout == NULL ) ){
  827. //
  828. // User is setting only one of the two parameters so read
  829. // the other value. There is a small window where another
  830. // thread using the same handle could set the other value.
  831. // in this case the setting would be lost.
  832. //
  833. Status = NtQueryInformationFile(
  834. hNamedPipe,
  835. &Iosb,
  836. &Remote,
  837. sizeof(FILE_PIPE_REMOTE_INFORMATION),
  838. FilePipeRemoteInformation );
  839. if ( !NT_SUCCESS(Status) ) {
  840. BaseSetLastNTError(Status);
  841. return FALSE;
  842. }
  843. }
  844. if (ARGUMENT_PRESENT( lpMaxCollectionCount ) ) {
  845. Remote.MaximumCollectionCount = *lpMaxCollectionCount;
  846. }
  847. if (ARGUMENT_PRESENT( lpCollectDataTimeout ) ) {
  848. //
  849. // Convert from milliseconds to an Nt delta time.
  850. //
  851. Remote.CollectDataTime.QuadPart =
  852. - (LONGLONG)UInt32x32To64( 10 * 1000, *lpCollectDataTimeout );
  853. }
  854. Status = NtSetInformationFile(
  855. hNamedPipe,
  856. &Iosb,
  857. &Remote,
  858. sizeof(FILE_PIPE_REMOTE_INFORMATION),
  859. FilePipeRemoteInformation );
  860. if ( !NT_SUCCESS(Status) ) {
  861. BaseSetLastNTError(Status);
  862. return FALSE;
  863. }
  864. }
  865. return TRUE;
  866. }
  867. BOOL
  868. APIENTRY
  869. GetNamedPipeInfo(
  870. HANDLE hNamedPipe,
  871. LPDWORD lpFlags,
  872. LPDWORD lpOutBufferSize,
  873. LPDWORD lpInBufferSize,
  874. LPDWORD lpMaxInstances
  875. )
  876. /*++
  877. Routine Description:
  878. The GetNamedPipeInfo function retrieves information about a named
  879. pipe. The information returned by this API is preserved the lifetime
  880. of an instance of a named pipe. The handle must be created with the
  881. GENERIC_READ access rights.
  882. Arguments:
  883. hNamedPipe - Supplies a handle to a named pipe.
  884. lpFlags - An optional parameter that if non-null, points to a DWORD
  885. which will be set with flags indicating the type of named pipe and handle.
  886. PIPE_END_SERVER
  887. The handle is the server end of a named pipe.
  888. PIPE_TYPE_MESSAGE
  889. The pipe is a message-stream pipe. If this flag is not set, the pipe is
  890. a byte-stream pipe.
  891. lpOutBufferSize - An optional parameter that if non-null, points to a
  892. DWORD which will be set with the size (in bytes) of the buffer for
  893. outgoing data. A return value of zero indicates the buffer is allocated
  894. as needed.
  895. lpInBufferSize - An optional parameter that if non-null, points to a DWORD
  896. which will be set with the size (in bytes) of the buffer for incoming
  897. data. A return
  898. value of zero indicates the buffer is allocated as needed.
  899. lpMaxInstances - An optional parameter that if non-null, points to a
  900. DWORD which will be set with the maximum number of pipe instances
  901. that can be created. Besides various numeric values, a special value
  902. may be returned for this.
  903. PIPE_UNLIMITED_INSTANCES
  904. Unlimited instances of the pipe can be created. This is an
  905. indicator that the maximum is requested; the value of the
  906. equate may be higher or lower than the actual implementation's limit,
  907. which may vary over time.
  908. Return Value:
  909. TRUE -- The operation was successful.
  910. FALSE -- The operation failed. Extended error status is available using
  911. GetLastError.
  912. --*/
  913. {
  914. IO_STATUS_BLOCK Iosb;
  915. NTSTATUS Status;
  916. FILE_PIPE_LOCAL_INFORMATION Local;
  917. Status = NtQueryInformationFile(
  918. hNamedPipe,
  919. &Iosb,
  920. &Local,
  921. sizeof(FILE_PIPE_LOCAL_INFORMATION),
  922. FilePipeLocalInformation );
  923. if ( !NT_SUCCESS(Status) ) {
  924. BaseSetLastNTError(Status);
  925. return FALSE;
  926. }
  927. if (ARGUMENT_PRESENT( lpFlags ) ) {
  928. *lpFlags = (Local.NamedPipeEnd == FILE_PIPE_CLIENT_END) ?
  929. PIPE_CLIENT_END : PIPE_SERVER_END;
  930. *lpFlags |= (Local.NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE) ?
  931. PIPE_TYPE_BYTE : PIPE_TYPE_MESSAGE;
  932. }
  933. if (ARGUMENT_PRESENT( lpOutBufferSize ) ) {
  934. *lpOutBufferSize = Local.OutboundQuota;
  935. }
  936. if (ARGUMENT_PRESENT( lpInBufferSize ) ) {
  937. *lpInBufferSize = Local.InboundQuota;
  938. }
  939. if (ARGUMENT_PRESENT( lpMaxInstances ) ) {
  940. if (Local.MaximumInstances >= PIPE_UNLIMITED_INSTANCES) {
  941. *lpMaxInstances = PIPE_UNLIMITED_INSTANCES;
  942. }
  943. else {
  944. *lpMaxInstances = Local.MaximumInstances;
  945. }
  946. }
  947. return TRUE;
  948. }
  949. BOOL
  950. APIENTRY
  951. PeekNamedPipe(
  952. HANDLE hNamedPipe,
  953. LPVOID lpBuffer,
  954. DWORD nBufferSize,
  955. LPDWORD lpBytesRead,
  956. LPDWORD lpTotalBytesAvail,
  957. LPDWORD lpBytesLeftThisMessage
  958. )
  959. /*++
  960. Routine Description:
  961. The PeekNamedPipe function copies a named pipe's data into a buffer for
  962. preview without removing it. The results of a PeekNamedPipe are similar to
  963. a ReadFile on the pipe except more information is returned, the function
  964. never blocks and if the pipe handle is reading in message mode, a partial
  965. message can be returned.
  966. A partial message peek'd on a message mode pipe will return TRUE.
  967. It is not an error if all of the pointers passed to this function are
  968. null. However, there is no reason for calling it this way.
  969. The NT peek call has the received data immediately after the state
  970. information so this routine needs to allocate an intermediate buffer
  971. large enough for the state information plus data.
  972. Arguments:
  973. hNamedPipe - Supplies a handle to a named pipe.
  974. lpBuffer - If non-null, pointer to buffer to read data into.
  975. nBufferSize - Size of input buffer, in bytes. (Ignored if lpBuffer
  976. is null.)
  977. lpBytesRead - If non-null, this points to a DWORD which will be set
  978. with the number of bytes actually read.
  979. lpTotalBytesAvail - If non-null, this points to a DWORD which receives
  980. a value giving the number of bytes that were available to be read.
  981. lpBytesLeftThisMessage - If non-null, this points to a DWORD which
  982. will be set to the number of bytes left in this message. (This will
  983. be zero for a byte-stream pipe.)
  984. Return Value:
  985. TRUE -- The operation was successful.
  986. FALSE -- The operation failed. Extended error status is available using
  987. GetLastError.
  988. --*/
  989. {
  990. IO_STATUS_BLOCK Iosb;
  991. NTSTATUS Status;
  992. PFILE_PIPE_PEEK_BUFFER PeekBuffer;
  993. DWORD IOLength;
  994. // Allocate enough for the users data and FILE_PIPE_PEEK_BUFFER
  995. IOLength = nBufferSize + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]);
  996. PeekBuffer = RtlAllocateHeap(RtlProcessHeap(),MAKE_TAG( TMP_TAG ), IOLength);
  997. if (PeekBuffer == NULL) {
  998. BaseSetLastNTError (STATUS_INSUFFICIENT_RESOURCES);
  999. return FALSE;
  1000. }
  1001. try {
  1002. Status = NtFsControlFile(hNamedPipe,
  1003. NULL,
  1004. NULL, // APC routine
  1005. NULL, // APC Context
  1006. &Iosb, // I/O Status block
  1007. FSCTL_PIPE_PEEK,// IoControlCode
  1008. NULL, // Buffer for data to the FS
  1009. 0, // Length.
  1010. PeekBuffer, // OutputBuffer for data from the FS
  1011. IOLength // OutputBuffer Length
  1012. );
  1013. if ( Status == STATUS_PENDING) {
  1014. // Operation must complete before return & IoStatusBlock destroyed
  1015. Status = NtWaitForSingleObject( hNamedPipe, FALSE, NULL );
  1016. if ( NT_SUCCESS(Status)) {
  1017. Status = Iosb.Status;
  1018. }
  1019. }
  1020. //
  1021. // Buffer overflow simply means that lpBytesLeftThisMessage != 0
  1022. //
  1023. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  1024. Status = STATUS_SUCCESS;
  1025. }
  1026. //
  1027. // Peek is complete, package up data for caller ensuring that
  1028. // the PeekBuffer is deleted even if an invalid pointer was given.
  1029. //
  1030. if ( NT_SUCCESS(Status)) {
  1031. try {
  1032. if ( ARGUMENT_PRESENT( lpTotalBytesAvail ) ) {
  1033. *lpTotalBytesAvail = PeekBuffer->ReadDataAvailable;
  1034. }
  1035. if ( ARGUMENT_PRESENT( lpBytesRead ) ) {
  1036. *lpBytesRead = (ULONG)(Iosb.Information - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
  1037. }
  1038. if ( ARGUMENT_PRESENT( lpBytesLeftThisMessage ) ) {
  1039. *lpBytesLeftThisMessage =
  1040. PeekBuffer->MessageLength -
  1041. (ULONG)(Iosb.Information - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
  1042. }
  1043. if ( ARGUMENT_PRESENT( lpBuffer ) ) {
  1044. RtlCopyMemory(
  1045. lpBuffer,
  1046. PeekBuffer->Data,
  1047. Iosb.Information - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
  1048. }
  1049. }
  1050. except (EXCEPTION_EXECUTE_HANDLER) {
  1051. Status = STATUS_ACCESS_VIOLATION;
  1052. }
  1053. }
  1054. }
  1055. finally {
  1056. if ( PeekBuffer != NULL ) {
  1057. RtlFreeHeap(RtlProcessHeap(),0,PeekBuffer);
  1058. }
  1059. }
  1060. if ( NT_SUCCESS(Status) ) {
  1061. return TRUE;
  1062. }
  1063. else {
  1064. BaseSetLastNTError(Status);
  1065. return FALSE;
  1066. }
  1067. }
  1068. BOOL
  1069. APIENTRY
  1070. TransactNamedPipe(
  1071. HANDLE hNamedPipe,
  1072. LPVOID lpInBuffer,
  1073. DWORD nInBufferSize,
  1074. LPVOID lpOutBuffer,
  1075. DWORD nOutBufferSize,
  1076. LPDWORD lpBytesRead,
  1077. LPOVERLAPPED lpOverlapped
  1078. )
  1079. /*++
  1080. Routine Description:
  1081. The TransactNamedPipe function writes data to and reads data from a named
  1082. pipe. This function fails if the named pipe contains any unread data or if
  1083. the named pipe is not in message mode. A named pipe's blocking state has no
  1084. effect on the TransactNamedPipe function. This API does not complete until
  1085. data is written into the InBuffer buffer. The lpOverlapped parameter is
  1086. available to allow an application to continue processing while the operation
  1087. takes place.
  1088. Arguments:
  1089. hNamedPipe - Supplies a handle to a named pipe.
  1090. lpInBuffer - Supplies the buffer containing the data that is written to
  1091. the pipe.
  1092. nInBufferSize - Supplies the size (in bytes) of the output buffer.
  1093. lpOutBuffer - Supplies the buffer that receives the data read from the pipe.
  1094. nOutBufferSize - Supplies the size (in bytes) of the input buffer.
  1095. lpBytesRead - Points to a DWORD that receives the number of bytes actually
  1096. read from the pipe.
  1097. lpOverlapped - An optional parameter that supplies an overlap structure to
  1098. be used with the request. If NULL or the handle was created without
  1099. FILE_FLAG_OVERLAPPED then the TransactNamedPipe will not return until
  1100. the operation completes.
  1101. When lpOverlapped is supplied and FILE_FLAG_OVERLAPPED was specified
  1102. when the handle was created, TransactNamedPipeFile may return
  1103. ERROR_IO_PENDING to allow the caller to continue processing while the
  1104. operation completes. The event (or File handle if hEvent == NULL) will
  1105. be set to the not signalled state before ERROR_IO_PENDING is
  1106. returned. The event will be set to the signalled state upon completion
  1107. of the request. GetOverlappedResult is used to determine the result
  1108. when ERROR_IO_PENDING is returned.
  1109. Return Value:
  1110. TRUE -- The operation was successful.
  1111. FALSE -- The operation failed. Extended error status is available using
  1112. GetLastError.
  1113. --*/
  1114. {
  1115. NTSTATUS Status;
  1116. if ( ARGUMENT_PRESENT( lpOverlapped ) ) {
  1117. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  1118. Status = NtFsControlFile(hNamedPipe,
  1119. lpOverlapped->hEvent,
  1120. NULL, // APC routine
  1121. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  1122. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  1123. FSCTL_PIPE_TRANSCEIVE,// IoControlCode
  1124. lpInBuffer, // Buffer for data to the FS
  1125. nInBufferSize,
  1126. lpOutBuffer, // OutputBuffer for data from the FS
  1127. nOutBufferSize // OutputBuffer Length
  1128. );
  1129. if ( NT_SUCCESS(Status) && Status != STATUS_PENDING) {
  1130. if ( ARGUMENT_PRESENT(lpBytesRead) ) {
  1131. try {
  1132. *lpBytesRead = (DWORD)lpOverlapped->InternalHigh;
  1133. }
  1134. except(EXCEPTION_EXECUTE_HANDLER) {
  1135. *lpBytesRead = 0;
  1136. }
  1137. }
  1138. return TRUE;
  1139. }
  1140. else {
  1141. if ( NT_WARNING(Status) ) {
  1142. if ( ARGUMENT_PRESENT(lpBytesRead) ) {
  1143. try {
  1144. *lpBytesRead = (DWORD)lpOverlapped->InternalHigh;
  1145. }
  1146. except(EXCEPTION_EXECUTE_HANDLER) {
  1147. *lpBytesRead = 0;
  1148. }
  1149. }
  1150. }
  1151. BaseSetLastNTError(Status);
  1152. return FALSE;
  1153. }
  1154. }
  1155. else
  1156. {
  1157. IO_STATUS_BLOCK Iosb;
  1158. Status = NtFsControlFile(hNamedPipe,
  1159. NULL,
  1160. NULL, // APC routine
  1161. NULL, // APC Context
  1162. &Iosb,
  1163. FSCTL_PIPE_TRANSCEIVE,// IoControlCode
  1164. lpInBuffer, // Buffer for data to the FS
  1165. nInBufferSize,
  1166. lpOutBuffer, // OutputBuffer for data from the FS
  1167. nOutBufferSize // OutputBuffer Length
  1168. );
  1169. if ( Status == STATUS_PENDING) {
  1170. // Operation must complete before return & Iosb destroyed
  1171. Status = NtWaitForSingleObject( hNamedPipe, FALSE, NULL );
  1172. if ( NT_SUCCESS(Status)) {
  1173. Status = Iosb.Status;
  1174. }
  1175. }
  1176. if ( NT_SUCCESS(Status) ) {
  1177. *lpBytesRead = (DWORD)Iosb.Information;
  1178. return TRUE;
  1179. }
  1180. else {
  1181. if ( NT_WARNING(Status) ) {
  1182. *lpBytesRead = (DWORD)Iosb.Information;
  1183. }
  1184. BaseSetLastNTError(Status);
  1185. return FALSE;
  1186. }
  1187. }
  1188. }
  1189. BOOL
  1190. APIENTRY
  1191. CallNamedPipeA(
  1192. LPCSTR lpNamedPipeName,
  1193. LPVOID lpInBuffer,
  1194. DWORD nInBufferSize,
  1195. LPVOID lpOutBuffer,
  1196. DWORD nOutBufferSize,
  1197. LPDWORD lpBytesRead,
  1198. DWORD nTimeOut
  1199. )
  1200. /*++
  1201. ANSI thunk to CallNamedPipeW
  1202. --*/
  1203. {
  1204. PUNICODE_STRING Unicode;
  1205. ANSI_STRING AnsiString;
  1206. NTSTATUS Status;
  1207. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  1208. RtlInitAnsiString(&AnsiString,lpNamedPipeName);
  1209. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  1210. if ( !NT_SUCCESS(Status) ) {
  1211. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  1212. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  1213. }
  1214. else {
  1215. BaseSetLastNTError(Status);
  1216. }
  1217. return FALSE;
  1218. }
  1219. return ( CallNamedPipeW( (LPCWSTR)Unicode->Buffer,
  1220. lpInBuffer,
  1221. nInBufferSize,
  1222. lpOutBuffer,
  1223. nOutBufferSize,
  1224. lpBytesRead,
  1225. nTimeOut)
  1226. );
  1227. }
  1228. BOOL
  1229. APIENTRY
  1230. CallNamedPipeW(
  1231. LPCWSTR lpNamedPipeName,
  1232. LPVOID lpInBuffer,
  1233. DWORD nInBufferSize,
  1234. LPVOID lpOutBuffer,
  1235. DWORD nOutBufferSize,
  1236. LPDWORD lpBytesRead,
  1237. DWORD nTimeOut
  1238. )
  1239. /*++
  1240. Routine Description:
  1241. CallNamedPipe is equivalent to a series of calls to CreateFile, perhaps
  1242. WaitNamedPipe (if CreateFile can't open the pipe immediately),
  1243. SetNamedPipeHandleState, TransactNamedPipe, and CloseFile. Refer to
  1244. the documentation for those APIs for more information.
  1245. Arguments:
  1246. lpNamedPipeName - Supplies the name of the named pipe.
  1247. lpInBuffer - Supplies the buffer containing the data that is written to
  1248. the pipe.
  1249. nInBufferSize - Supplies the size (in bytes) of the output buffer.
  1250. lpOutBuffer - Supplies the buffer that receives the data read from the pipe.
  1251. nOutBufferSize - Supplies the size (in bytes) of the input buffer.
  1252. lpBytesRead - Points to a DWORD that receives the number of bytes actually
  1253. read from the pipe.
  1254. nTimeOut - Gives a value (in milliseconds) that is the amount of time
  1255. this function should wait for the pipe to become available. (Note
  1256. that the function may take longer than that to execute, due to
  1257. various factors.)
  1258. Return Value:
  1259. TRUE -- The operation was successful.
  1260. FALSE -- The operation failed. Extended error status is available using
  1261. GetLastError.
  1262. --*/
  1263. {
  1264. HANDLE Pipe;
  1265. BOOL FirstChance = TRUE; // Allow only one chance at WaitNamedPipe
  1266. BOOL Result;
  1267. while ( 1 ) {
  1268. Pipe = CreateFileW(lpNamedPipeName,
  1269. GENERIC_READ | GENERIC_WRITE,
  1270. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1271. NULL, // Security Attributes
  1272. OPEN_EXISTING,
  1273. FILE_ATTRIBUTE_NORMAL,
  1274. NULL
  1275. );
  1276. if ( Pipe != INVALID_HANDLE_VALUE ) {
  1277. break; // Created a handle
  1278. }
  1279. if ( FirstChance == FALSE ) {
  1280. // Already called WaitNamedPipe once so give up.
  1281. return FALSE;
  1282. }
  1283. WaitNamedPipeW(lpNamedPipeName, nTimeOut);
  1284. FirstChance = FALSE;
  1285. }
  1286. try {
  1287. DWORD ReadMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
  1288. // Default open is readmode byte stream- change to message mode.
  1289. Result = SetNamedPipeHandleState( Pipe, &ReadMode, NULL, NULL);
  1290. if ( Result == TRUE ) {
  1291. Result = TransactNamedPipe(
  1292. Pipe,
  1293. lpInBuffer,
  1294. nInBufferSize,
  1295. lpOutBuffer,
  1296. nOutBufferSize,
  1297. lpBytesRead,
  1298. NULL);
  1299. }
  1300. }
  1301. finally {
  1302. CloseHandle( Pipe );
  1303. }
  1304. return Result;
  1305. }
  1306. BOOL
  1307. APIENTRY
  1308. WaitNamedPipeA(
  1309. LPCSTR lpNamedPipeName,
  1310. DWORD nTimeOut
  1311. )
  1312. /*++
  1313. Ansi thunk to WaitNamedPipeW
  1314. --*/
  1315. {
  1316. UNICODE_STRING UnicodeString;
  1317. BOOL b;
  1318. if (!Basep8BitStringToDynamicUnicodeString( &UnicodeString, lpNamedPipeName )) {
  1319. return FALSE;
  1320. }
  1321. b = WaitNamedPipeW( UnicodeString.Buffer, nTimeOut );
  1322. RtlFreeUnicodeString(&UnicodeString);
  1323. return b;
  1324. }
  1325. BOOL
  1326. APIENTRY
  1327. WaitNamedPipeW(
  1328. LPCWSTR lpNamedPipeName,
  1329. DWORD nTimeOut
  1330. )
  1331. /*++
  1332. Routine Description:
  1333. The WaitNamedPipe function waits for a named pipe to become available.
  1334. Arguments:
  1335. lpNamedPipeName - Supplies the name of the named pipe.
  1336. nTimeOut - Gives a value (in milliseconds) that is the amount of time
  1337. this function should wait for the pipe to become available. (Note
  1338. that the function may take longer than that to execute, due to
  1339. various factors.)
  1340. nTimeOut Special Values:
  1341. NMPWAIT_WAIT_FOREVER
  1342. No timeout.
  1343. NMPWAIT_USE_DEFAULT_WAIT
  1344. Use default timeout set in call to CreateNamedPipe.
  1345. Return Value:
  1346. TRUE -- The operation was successful.
  1347. FALSE -- The operation failed. Extended error status is available using
  1348. GetLastError.
  1349. --*/
  1350. {
  1351. IO_STATUS_BLOCK Iosb;
  1352. OBJECT_ATTRIBUTES Obja;
  1353. NTSTATUS Status;
  1354. RTL_PATH_TYPE PathType;
  1355. ULONG WaitPipeLength;
  1356. PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
  1357. PWSTR FreeBuffer;
  1358. UNICODE_STRING FileSystem;
  1359. UNICODE_STRING PipeName;
  1360. UNICODE_STRING OriginalPipeName;
  1361. UNICODE_STRING ValidUnicodePrefix;
  1362. HANDLE Handle;
  1363. IO_STATUS_BLOCK IoStatusBlock;
  1364. LPWSTR Pwc;
  1365. ULONG Index;
  1366. //
  1367. // Open a handle either to the redirector or the NPFS depending on
  1368. // the start of the pipe name. Split lpNamedPipeName into two
  1369. // halves as follows:
  1370. // \\.\pipe\pipename \\.\pipe\ and pipename
  1371. // \\server\pipe\pipename \\ and server\pipe\pipename
  1372. //
  1373. if (!RtlCreateUnicodeString( &OriginalPipeName, lpNamedPipeName)) {
  1374. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1375. return FALSE;
  1376. }
  1377. //
  1378. // Change all the forward slashes into backward slashes.
  1379. //
  1380. for ( Index =0; Index < (OriginalPipeName.Length/sizeof(WCHAR)); Index++ ) {
  1381. if (OriginalPipeName.Buffer[Index] == L'/') {
  1382. OriginalPipeName.Buffer[Index] = L'\\';
  1383. }
  1384. }
  1385. PipeName = OriginalPipeName;
  1386. PathType = RtlDetermineDosPathNameType_U(lpNamedPipeName);
  1387. FreeBuffer = NULL;
  1388. switch ( PathType ) {
  1389. case RtlPathTypeLocalDevice:
  1390. // Name should be of the form \\.\pipe\pipename (IgnoreCase)
  1391. RtlInitUnicodeString( &ValidUnicodePrefix, DOS_LOCAL_PIPE_PREFIX);
  1392. if (RtlPrefixString((PSTRING)&ValidUnicodePrefix,
  1393. (PSTRING)&PipeName,
  1394. TRUE) == FALSE) {
  1395. RtlFreeUnicodeString(&OriginalPipeName);
  1396. BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
  1397. return FALSE;
  1398. }
  1399. // Skip first 9 characters "\\.\pipe\"
  1400. PipeName.Buffer+=9;
  1401. PipeName.Length-=9*sizeof(WCHAR);
  1402. RtlInitUnicodeString( &FileSystem, DOS_LOCAL_PIPE);
  1403. break;
  1404. case RtlPathTypeUncAbsolute:
  1405. // Name is of the form \\server\pipe\pipename
  1406. // Find the pipe name.
  1407. for ( Pwc = &PipeName.Buffer[2]; *Pwc != 0; Pwc++) {
  1408. if ( *Pwc == L'\\') {
  1409. // Found backslash after servername
  1410. break;
  1411. }
  1412. }
  1413. if ( (*Pwc != 0) &&
  1414. ( _wcsnicmp( Pwc + 1, L"pipe\\", 5 ) == 0 ) ) {
  1415. // Temporarily, break this up into 2 strings
  1416. // string1 = \\server\pipe
  1417. // string2 = the-rest
  1418. Pwc += (sizeof (L"pipe\\") / sizeof( WCHAR ) ) - 1;
  1419. } else {
  1420. // This is not a valid remote path name.
  1421. RtlFreeUnicodeString(&OriginalPipeName);
  1422. BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
  1423. return FALSE;
  1424. }
  1425. // Pwc now points to the first path seperator after \\server\pipe.
  1426. // Attempt to open \DosDevices\Unc\Servername\Pipe.
  1427. PipeName.Buffer = &PipeName.Buffer[2];
  1428. PipeName.Length = (USHORT)((PCHAR)Pwc - (PCHAR)PipeName.Buffer);
  1429. PipeName.MaximumLength = PipeName.Length;
  1430. FileSystem.MaximumLength =
  1431. (USHORT)sizeof( DOS_REMOTE_PIPE ) +
  1432. PipeName.MaximumLength;
  1433. FileSystem.Buffer = RtlAllocateHeap(
  1434. RtlProcessHeap(),MAKE_TAG( TMP_TAG ),
  1435. FileSystem.MaximumLength
  1436. );
  1437. if ( !FileSystem.Buffer ) {
  1438. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1439. RtlFreeUnicodeString(&OriginalPipeName);
  1440. return FALSE;
  1441. }
  1442. FreeBuffer = FileSystem.Buffer;
  1443. RtlCopyMemory(
  1444. FileSystem.Buffer,
  1445. DOS_REMOTE_PIPE,
  1446. sizeof( DOS_REMOTE_PIPE ) - sizeof(WCHAR)
  1447. );
  1448. FileSystem.Length = sizeof( DOS_REMOTE_PIPE ) - sizeof(WCHAR);
  1449. RtlAppendUnicodeStringToString( &FileSystem, &PipeName );
  1450. // Set up pipe name, skip leading backslashes.
  1451. RtlInitUnicodeString( &PipeName, (PWCH)Pwc + 1 );
  1452. break;
  1453. default:
  1454. BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
  1455. RtlFreeUnicodeString(&OriginalPipeName);
  1456. return FALSE;
  1457. }
  1458. InitializeObjectAttributes(
  1459. &Obja,
  1460. &FileSystem,
  1461. OBJ_CASE_INSENSITIVE,
  1462. NULL,
  1463. NULL
  1464. );
  1465. Status = NtOpenFile(
  1466. &Handle,
  1467. (ACCESS_MASK)FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  1468. &Obja,
  1469. &IoStatusBlock,
  1470. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1471. FILE_SYNCHRONOUS_IO_NONALERT
  1472. );
  1473. if (FreeBuffer != NULL) {
  1474. RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
  1475. }
  1476. if ( !NT_SUCCESS(Status) ) {
  1477. RtlFreeUnicodeString(&OriginalPipeName);
  1478. BaseSetLastNTError(Status);
  1479. return FALSE;
  1480. }
  1481. WaitPipeLength =
  1482. FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) + PipeName.Length;
  1483. WaitPipe = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), WaitPipeLength);
  1484. if ( !WaitPipe ) {
  1485. RtlFreeUnicodeString(&OriginalPipeName);
  1486. NtClose(Handle);
  1487. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1488. return FALSE;
  1489. }
  1490. if ( nTimeOut == NMPWAIT_USE_DEFAULT_WAIT ) {
  1491. WaitPipe->TimeoutSpecified = FALSE;
  1492. }
  1493. else {
  1494. if ( nTimeOut == NMPWAIT_WAIT_FOREVER ) {
  1495. WaitPipe->Timeout.LowPart = 0;
  1496. WaitPipe->Timeout.HighPart =0x80000000;
  1497. }
  1498. else {
  1499. //
  1500. // Convert from milliseconds to an Nt delta time.
  1501. //
  1502. WaitPipe->Timeout.QuadPart =
  1503. - (LONGLONG)UInt32x32To64( 10 * 1000, nTimeOut );
  1504. }
  1505. WaitPipe->TimeoutSpecified = TRUE;
  1506. }
  1507. WaitPipe->NameLength = PipeName.Length;
  1508. RtlCopyMemory(
  1509. WaitPipe->Name,
  1510. PipeName.Buffer,
  1511. PipeName.Length
  1512. );
  1513. RtlFreeUnicodeString(&OriginalPipeName);
  1514. Status = NtFsControlFile(Handle,
  1515. NULL,
  1516. NULL, // APC routine
  1517. NULL, // APC Context
  1518. &Iosb,
  1519. FSCTL_PIPE_WAIT,// IoControlCode
  1520. WaitPipe, // Buffer for data to the FS
  1521. WaitPipeLength,
  1522. NULL, // OutputBuffer for data from the FS
  1523. 0 // OutputBuffer Length
  1524. );
  1525. RtlFreeHeap(RtlProcessHeap(),0,WaitPipe);
  1526. NtClose(Handle);
  1527. if (NT_SUCCESS( Status ) ) {
  1528. return TRUE;
  1529. }
  1530. else
  1531. {
  1532. BaseSetLastNTError(Status);
  1533. return FALSE;
  1534. }
  1535. }