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.

217 lines
8.0 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. //
  102. // Security: Limit the size of InBufSize and OutBufSize
  103. //
  104. if (InBufSize >= 4096) {
  105. return ERROR_INVALID_PARAMETER;
  106. }
  107. if (OutBufSize >= 16384) {
  108. return ERROR_INVALID_PARAMETER;
  109. }
  110. if( 0 == InBufSize ) return ERROR_INVALID_PARAMETER;
  111. InBuf = DhcpAllocateMemory(InBufSize);
  112. if( NULL == InBuf ) return ERROR_NOT_ENOUGH_MEMORY;
  113. RealOutBuf = DhcpAllocateMemory(2*sizeof(DWORD) + OutBufSize);
  114. if( NULL == RealOutBuf ) {
  115. DhcpFreeMemory(InBuf);
  116. return ERROR_NOT_ENOUGH_MEMORY;
  117. }
  118. OutBuf = RealOutBuf+sizeof(DWORD);
  119. Error = BlockReadFile(PipeHandle, InBuf, InBufSize, &BytesRead, Overlap);
  120. if( ERROR_SUCCESS != Error ) goto Cleanup;
  121. if( InBufSize != BytesRead ) {
  122. Error = ERROR_INVALID_PARAMETER;
  123. goto Cleanup;
  124. }
  125. Error = DhcpApiProcessBuffer(InBuf,InBufSize, OutBuf, &OutBufSize);
  126. ((DWORD UNALIGNED*)RealOutBuf)[0] = htonl(Error);
  127. ((DWORD UNALIGNED*)RealOutBuf)[1] = htonl(OutBufSize);
  128. if( ERROR_SUCCESS == Error ) OutBufSize += sizeof(DWORD)*2;
  129. else OutBufSize = sizeof(DWORD)*2;
  130. Error = BlockWriteFile(PipeHandle, RealOutBuf, OutBufSize, &BytesWritten, Overlap);
  131. if( ERROR_SUCCESS != Error ) goto Cleanup;
  132. DhcpAssert(OutBufSize == BytesWritten);
  133. Cleanup:
  134. DhcpAssert(InBuf);
  135. DhcpFreeMemory(InBuf);
  136. if( NULL != RealOutBuf) DhcpFreeMemory(RealOutBuf);
  137. return Error;
  138. }
  139. DWORD // error status
  140. ExecuteApiRequest( // execute an api request
  141. IN LPBYTE InBuffer, // buffer to process
  142. OUT LPBYTE OutBuffer, // place to copy the output data
  143. IN OUT LPDWORD OutBufSize // ip: how big can the outbuf be, o/p: how big it really is
  144. ) {
  145. LPBYTE xOutBuf;
  146. LPBYTE Tmp;
  147. DWORD xOutBufSize;
  148. DWORD BytesRead;
  149. BOOL Status;
  150. xOutBufSize = (*OutBufSize) + 2 * sizeof(DWORD); // the first two dwords are STATUS and reqd SIZE respectively
  151. xOutBuf = DhcpAllocateMemory(xOutBufSize);
  152. if( NULL == xOutBuf ) return ERROR_NOT_ENOUGH_MEMORY;
  153. Status = CallNamedPipe(
  154. DHCP_PIPE_NAME,
  155. InBuffer,
  156. ntohl(((DWORD UNALIGNED *)InBuffer)[1]) + 2*sizeof(DWORD),
  157. xOutBuf,
  158. xOutBufSize,
  159. &BytesRead,
  160. NMPWAIT_WAIT_FOREVER
  161. );
  162. if( FALSE == Status ) {
  163. Status = GetLastError();
  164. DhcpAssert(ERROR_MORE_DATA != Status);
  165. DhcpFreeMemory(xOutBuf);
  166. return Status;
  167. }
  168. DhcpAssert( BytesRead >= 2*sizeof(DWORD)); // expect to read STATUS and SIZE at the minimum..
  169. Status = *(DWORD UNALIGNED *)xOutBuf; Tmp = xOutBuf + sizeof(DWORD);
  170. xOutBufSize = *(DWORD UNALIGNED *)Tmp; Tmp += sizeof(DWORD);
  171. Status = ntohl(Status);
  172. xOutBufSize = ntohl(xOutBufSize);
  173. if (xOutBufSize > (*OutBufSize)) {
  174. Status = ERROR_MORE_DATA;
  175. }
  176. if( ERROR_SUCCESS == Status && 0 != xOutBufSize ) {
  177. memcpy(OutBuffer, Tmp, xOutBufSize);
  178. }
  179. (*OutBufSize) = xOutBufSize;
  180. DhcpFreeMemory(xOutBuf);
  181. return Status;
  182. }
  183. //================================================================================
  184. // end of file
  185. //================================================================================