Leaked source code of windows server 2003
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.

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