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.

203 lines
7.5 KiB

  1. //================================================================================
  2. // Copyright (C) 1997 Microsoft Corporation
  3. // Author: RamesV
  4. // description: implements the API stuff for a named pipe.
  5. //================================================================================
  6. #include "precomp.h"
  7. #include <apistub.h>
  8. #include <apiimpl.h>
  9. typedef
  10. BOOL (*PFILE_OP_FN) (HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
  11. #define DEFAULT_SERVER_TIMEOUT (2*60*1000) // two minutes.
  12. DWORD INLINE // win32 status
  13. BlockFileOp( // synchronous read/write file
  14. IN HANDLE Handle, // handle to read/write on
  15. IN OUT LPBYTE Buffer, // buffer to read/write into
  16. IN DWORD BufSize, // o/p buffer size
  17. OUT LPDWORD nBytes, // the # of bytes read/written
  18. IN LPOVERLAPPED Overlap,
  19. IN PFILE_OP_FN FileOp // file operation, ReadFile or WriteFile
  20. ) {
  21. BOOL Success;
  22. DWORD Error;
  23. BOOL fCancelled = FALSE;
  24. Success = FileOp(Handle, Buffer, BufSize, nBytes, Overlap);
  25. if( Success ) return ERROR_SUCCESS;
  26. Error = GetLastError();
  27. if( ERROR_MORE_DATA == Error ) {
  28. (*nBytes) = BufSize;
  29. return ERROR_SUCCESS;
  30. }
  31. if( ERROR_IO_PENDING != Error ) return Error;
  32. /*
  33. if( (PFILE_OP_FN)WriteFile == FileOp ) {
  34. Success = FlushFileBuffers(Handle);
  35. if( !Success ) return GetLastError();
  36. }
  37. */
  38. Error = WaitForSingleObject(Overlap->hEvent, DEFAULT_SERVER_TIMEOUT );
  39. if( WAIT_TIMEOUT == Error ) {
  40. //
  41. // Waited too long?
  42. //
  43. DhcpPrint((DEBUG_ERRORS, "Waited too long on pipe. Cancelling IO\n"));
  44. fCancelled = CancelIo(Handle);
  45. if( 0 == Error ) DhcpAssert( 0 == GetLastError());
  46. //
  47. // Hopefully, even if we cancel, get Overlapped result would return..
  48. //
  49. }
  50. Success = GetOverlappedResult(Handle, Overlap, nBytes, TRUE);
  51. if( Success ) return ERROR_SUCCESS;
  52. Error = GetLastError();
  53. if( ERROR_MORE_DATA == Error ) {
  54. (*nBytes) = BufSize;
  55. return ERROR_SUCCESS;
  56. }
  57. if( fCancelled ) DhcpAssert( ERROR_OPERATION_ABORTED == Error);
  58. return Error;
  59. }
  60. DWORD INLINE // win32 status
  61. BlockReadFile( // synchronous read/write file
  62. IN HANDLE Handle, // handle to read on
  63. IN OUT LPBYTE OutBuffer, // buffer to read into
  64. IN DWORD OutBufSize, // o/p buffer size
  65. OUT LPDWORD nBytesRead, // the # of bytes read
  66. IN LPOVERLAPPED Overlap
  67. ) {
  68. return BlockFileOp(Handle,OutBuffer, OutBufSize, nBytesRead, Overlap, ReadFile);
  69. }
  70. DWORD INLINE // win32 status
  71. BlockWriteFile( // synchronous read/write file
  72. IN HANDLE Handle, // handle to write on
  73. IN OUT LPBYTE InBuffer, // buffer to writeinto
  74. IN DWORD InBufSize, // i/p buffer size
  75. OUT LPDWORD nBytesWritten, // the # of bytes written
  76. IN LPOVERLAPPED Overlap
  77. ) {
  78. return BlockFileOp(Handle, InBuffer, InBufSize, nBytesWritten, Overlap, WriteFile);
  79. }
  80. DWORD
  81. ProcessApiRequest( // win32 status
  82. IN HANDLE PipeHandle, // input pipe to read from
  83. IN LPOVERLAPPED Overlap // overlap buffer to use for this
  84. ) {
  85. DWORD Tmp[2];
  86. DWORD OutBufSize;
  87. DWORD InBufSize;
  88. DWORD Error;
  89. DWORD BytesRead;
  90. DWORD BytesWritten;
  91. LPBYTE InBuf;
  92. LPBYTE OutBuf;
  93. LPBYTE RealOutBuf;
  94. BOOL Success;
  95. ResetEvent(Overlap->hEvent);
  96. Error = BlockReadFile(PipeHandle, (LPBYTE)Tmp, sizeof(Tmp), &BytesRead, Overlap);
  97. if( ERROR_SUCCESS != Error ) return Error;
  98. if( sizeof(Tmp) != BytesRead ) return ERROR_INVALID_PARAMETER;
  99. InBufSize = ntohl(Tmp[1]);
  100. OutBufSize = ntohl(Tmp[0]);
  101. if( 0 == InBufSize ) return ERROR_INVALID_PARAMETER;
  102. InBuf = DhcpAllocateMemory(InBufSize);
  103. if( NULL == InBuf ) return ERROR_NOT_ENOUGH_MEMORY;
  104. RealOutBuf = DhcpAllocateMemory(2*sizeof(DWORD) + OutBufSize);
  105. if( NULL == RealOutBuf ) {
  106. DhcpFreeMemory(InBuf);
  107. return ERROR_NOT_ENOUGH_MEMORY;
  108. }
  109. OutBuf = RealOutBuf+sizeof(DWORD);
  110. Error = BlockReadFile(PipeHandle, InBuf, InBufSize, &BytesRead, Overlap);
  111. if( ERROR_SUCCESS != Error ) goto Cleanup;
  112. if( InBufSize != BytesRead ) {
  113. Error = ERROR_INVALID_PARAMETER;
  114. goto Cleanup;
  115. }
  116. Error = DhcpApiProcessBuffer(InBuf,InBufSize, OutBuf, &OutBufSize);
  117. ((DWORD UNALIGNED*)RealOutBuf)[0] = htonl(Error);
  118. ((DWORD UNALIGNED*)RealOutBuf)[1] = htonl(OutBufSize);
  119. if( ERROR_SUCCESS == Error ) OutBufSize += sizeof(DWORD)*2;
  120. else OutBufSize = sizeof(DWORD)*2;
  121. Error = BlockWriteFile(PipeHandle, RealOutBuf, OutBufSize, &BytesWritten, Overlap);
  122. if( ERROR_SUCCESS != Error ) goto Cleanup;
  123. DhcpAssert(OutBufSize == BytesWritten);
  124. Cleanup:
  125. DhcpAssert(InBuf);
  126. DhcpFreeMemory(InBuf);
  127. if( NULL != RealOutBuf) DhcpFreeMemory(RealOutBuf);
  128. return Error;
  129. }
  130. DWORD // error status
  131. ExecuteApiRequest( // execute an api request
  132. IN LPBYTE InBuffer, // buffer to process
  133. OUT LPBYTE OutBuffer, // place to copy the output data
  134. IN OUT LPDWORD OutBufSize // ip: how big can the outbuf be, o/p: how big it really is
  135. ) {
  136. LPBYTE xOutBuf;
  137. LPBYTE Tmp;
  138. DWORD xOutBufSize;
  139. DWORD BytesRead;
  140. BOOL Status;
  141. xOutBufSize = (*OutBufSize) + 2 * sizeof(DWORD); // the first two dwords are STATUS and reqd SIZE respectively
  142. xOutBuf = DhcpAllocateMemory(xOutBufSize);
  143. if( NULL == xOutBuf ) return ERROR_NOT_ENOUGH_MEMORY;
  144. Status = CallNamedPipe(
  145. DHCP_PIPE_NAME,
  146. InBuffer,
  147. ntohl(((DWORD UNALIGNED *)InBuffer)[1]) + 2*sizeof(DWORD),
  148. xOutBuf,
  149. xOutBufSize,
  150. &BytesRead,
  151. NMPWAIT_WAIT_FOREVER
  152. );
  153. if( FALSE == Status ) {
  154. Status = GetLastError();
  155. DhcpAssert(ERROR_MORE_DATA != Status);
  156. DhcpFreeMemory(xOutBuf);
  157. return Status;
  158. }
  159. DhcpAssert( BytesRead >= 2*sizeof(DWORD)); // expect to read STATUS and SIZE at the minimum..
  160. Status = *(DWORD UNALIGNED *)xOutBuf; Tmp = xOutBuf + sizeof(DWORD);
  161. xOutBufSize = *(DWORD UNALIGNED *)Tmp; Tmp += sizeof(DWORD);
  162. Status = ntohl(Status);
  163. xOutBufSize = ntohl(xOutBufSize);
  164. if( ERROR_SUCCESS == Status && 0 != xOutBufSize ) {
  165. memcpy(OutBuffer, Tmp, xOutBufSize);
  166. }
  167. (*OutBufSize) = xOutBufSize;
  168. DhcpFreeMemory(xOutBuf);
  169. return Status;
  170. }
  171. //================================================================================
  172. // end of file
  173. //================================================================================