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.

622 lines
18 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. error.c
  5. Abstract:
  6. This module contains the Win32 error APIs.
  7. Author:
  8. Mark Lucovsky (markl) 24-Sep-1990
  9. Revision History:
  10. --*/
  11. #include "basedll.h"
  12. DWORD g_dwLastErrorToBreakOn = ERROR_SUCCESS;
  13. UINT
  14. GetErrorMode()
  15. {
  16. UINT PreviousMode;
  17. NTSTATUS Status;
  18. Status = NtQueryInformationProcess(
  19. NtCurrentProcess(),
  20. ProcessDefaultHardErrorMode,
  21. (PVOID) &PreviousMode,
  22. sizeof(PreviousMode),
  23. NULL
  24. );
  25. if ( !NT_SUCCESS(Status) ) {
  26. BaseSetLastNTError(Status);
  27. return 0;
  28. }
  29. if (PreviousMode & 1) {
  30. PreviousMode &= ~SEM_FAILCRITICALERRORS;
  31. }
  32. else {
  33. PreviousMode |= SEM_FAILCRITICALERRORS;
  34. }
  35. return PreviousMode;
  36. }
  37. UINT
  38. SetErrorMode(
  39. UINT uMode
  40. )
  41. {
  42. UINT PreviousMode;
  43. UINT NewMode;
  44. PreviousMode = GetErrorMode();
  45. NewMode = uMode;
  46. if (NewMode & SEM_FAILCRITICALERRORS ) {
  47. NewMode &= ~SEM_FAILCRITICALERRORS;
  48. }
  49. else {
  50. NewMode |= SEM_FAILCRITICALERRORS;
  51. }
  52. //
  53. // Once SEM_NOALIGNMENTFAULTEXCEPT has been enabled for a given
  54. // process, it cannot be disabled via this API.
  55. //
  56. NewMode |= (PreviousMode & SEM_NOALIGNMENTFAULTEXCEPT);
  57. if ( NT_SUCCESS(NtSetInformationProcess(
  58. NtCurrentProcess(),
  59. ProcessDefaultHardErrorMode,
  60. (PVOID) &NewMode,
  61. sizeof(NewMode)
  62. ) ) ){
  63. }
  64. return( PreviousMode );
  65. }
  66. DWORD
  67. GetLastError(
  68. VOID
  69. )
  70. /*++
  71. Routine Description:
  72. This function returns the most recent error code set by a Win32 API
  73. call. Applications should call this function immediately after a
  74. Win32 API call returns a failure indications (e.g. FALSE, NULL or
  75. -1) to determine the cause of the failure.
  76. The last error code value is a per thread field, so that multiple
  77. threads do not overwrite each other's last error code value.
  78. Arguments:
  79. None.
  80. Return Value:
  81. The return value is the most recent error code as set by a Win32 API
  82. call.
  83. --*/
  84. {
  85. return (DWORD)NtCurrentTeb()->LastErrorValue;
  86. }
  87. VOID
  88. SetLastError(
  89. DWORD dwErrCode
  90. )
  91. /*++
  92. Routine Description:
  93. This function set the most recent error code and error string in per
  94. thread storage. Win32 API functions call this function whenever
  95. they return a failure indication (e.g. FALSE, NULL or -1).
  96. This function
  97. is not called by Win32 API function calls that are successful, so
  98. that if three Win32 API function calls are made, and the first one
  99. fails and the second two succeed, the error code and string stored
  100. by the first one are still available after the second two succeed.
  101. Applications can retrieve the values saved by this function using
  102. GetLastError. The use of this function is optional, as an
  103. application need only call if it is interested in knowing the
  104. specific reason for an API function failure.
  105. The last error code value is kept in thread local storage so that
  106. multiple threads do not overwrite each other's values.
  107. Arguments:
  108. dwErrCode - Specifies the error code to store in per thread storage
  109. for the current thread.
  110. Return Value:
  111. return-value - Description of conditions needed to return value. - or -
  112. None.
  113. --*/
  114. {
  115. PTEB Teb = NtCurrentTeb();
  116. if ((g_dwLastErrorToBreakOn != ERROR_SUCCESS) &&
  117. (dwErrCode == g_dwLastErrorToBreakOn)) {
  118. DbgBreakPoint();
  119. }
  120. // make write breakpoints to this field more meaningful by only writing to it when
  121. // the value changes.
  122. if (Teb->LastErrorValue != dwErrCode) {
  123. Teb->LastErrorValue = dwErrCode;
  124. }
  125. }
  126. ULONG
  127. BaseSetLastNTError(
  128. IN NTSTATUS Status
  129. )
  130. /*++
  131. Routine Description:
  132. This API sets the "last error value" and the "last error string"
  133. based on the value of Status. For status codes that don't have
  134. a corresponding error string, the string is set to null.
  135. Arguments:
  136. Status - Supplies the status value to store as the last error value.
  137. Return Value:
  138. The corresponding Win32 error code that was stored in the
  139. "last error value" thread variable.
  140. --*/
  141. {
  142. ULONG dwErrorCode;
  143. dwErrorCode = RtlNtStatusToDosError( Status );
  144. SetLastError( dwErrorCode );
  145. return( dwErrorCode );
  146. }
  147. HANDLE
  148. WINAPI
  149. CreateIoCompletionPort(
  150. HANDLE FileHandle,
  151. HANDLE ExistingCompletionPort,
  152. ULONG_PTR CompletionKey,
  153. DWORD NumberOfConcurrentThreads
  154. )
  155. /*++
  156. Routine Description:
  157. This function creates an I/O completion port. Completion ports
  158. provide another mechanism that can be used to to recive I/O
  159. completion notification.
  160. Completion ports act as a queue. The Win32 I/O system can be
  161. instructed to queue I/O completion notification packets to
  162. completion ports. This API provides this mechanism. If a file
  163. handle is created for overlapped I/O completion
  164. (FILE_FLAG_OVERLAPPED) , a completion port can be associated with
  165. the file handle. When I/O operations are done on a file handle that
  166. has an associated completion port, the I/O system will queue a
  167. completion packet when the I/O operation completes. The
  168. GetQueuedCompletionStatus is used to pick up these queued I/O
  169. completion packets.
  170. This API can be used to create a completion port and associate it
  171. with a file. If you supply a completion port, it can be used to
  172. associate the specified file with the specified completion port.
  173. Arguments:
  174. FileHandle - Supplies a handle to a file opened for overlapped I/O
  175. completion. This file is associated with either the specified
  176. completion port, or a new completion port is created, and the
  177. file is associated with that port. Once associated with a
  178. completion port, the file handle may not be used in ReadFileEx
  179. or WriteFileEx operations. It is not advisable to share an
  180. associated file handle through either handle inheritence or
  181. through DuplicateHandle. I/O operations done on these
  182. duplicates will also generate a completion notification.
  183. ExistingCompletionPort - If this parameter is specified, it supplies
  184. an existing completion port that is to be associated with the
  185. specified file handle. Otherwise, a new completion port is
  186. created and associated with the specified file handle.
  187. CompletionKey - Supplies a per-file completion key that is part of
  188. every I/O completion packet for this file.
  189. NumberOfConcurrentThreads - This is the number of threads that are
  190. alowed to be concurrently active and can be used to avoid
  191. spurious context switches, e.g., context switches that would
  192. occur simply because of quantum end. Up to the number of
  193. threads specified are allowed to execute concurrently. If one
  194. of the threads enters a wait state, then another thread is
  195. allowed to procede. There may be times when more then the
  196. specified number of threads are active, but this will be quickly
  197. throttled. A value of 0 tells the system to allow the same
  198. number of threads as there are processors to run.
  199. Return Value:
  200. Not NULL - Returns the completion port handle associated with the file.
  201. NULL - The operation failed. Extended error status is available
  202. using GetLastError.
  203. --*/
  204. {
  205. NTSTATUS Status;
  206. HANDLE Port;
  207. IO_STATUS_BLOCK IoSb;
  208. FILE_COMPLETION_INFORMATION CompletionInfo;
  209. Port = ExistingCompletionPort;
  210. if ( !ARGUMENT_PRESENT(ExistingCompletionPort) ) {
  211. Status = NtCreateIoCompletion (
  212. &Port,
  213. IO_COMPLETION_ALL_ACCESS,
  214. NULL,
  215. NumberOfConcurrentThreads
  216. );
  217. if ( !NT_SUCCESS(Status) ) {
  218. BaseSetLastNTError(Status);
  219. return NULL;
  220. }
  221. }
  222. if ( FileHandle != INVALID_HANDLE_VALUE ) {
  223. CompletionInfo.Port = Port;
  224. CompletionInfo.Key = (PVOID)CompletionKey;
  225. Status = NtSetInformationFile(
  226. FileHandle,
  227. &IoSb,
  228. &CompletionInfo,
  229. sizeof(CompletionInfo),
  230. FileCompletionInformation
  231. );
  232. if ( !NT_SUCCESS(Status) ) {
  233. BaseSetLastNTError(Status);
  234. if ( !ARGUMENT_PRESENT(ExistingCompletionPort) ) {
  235. NtClose(Port);
  236. }
  237. return NULL;
  238. }
  239. }
  240. else {
  241. //
  242. // file handle is INVALID_HANDLE_VALUE. Usually this is
  243. // used to create a new unassociated completion port.
  244. //
  245. // Special case here to see if existing completion port was
  246. // specified and fail if it is
  247. //
  248. if ( ARGUMENT_PRESENT(ExistingCompletionPort) ) {
  249. Port = NULL;
  250. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  251. }
  252. }
  253. return Port;
  254. }
  255. BOOL
  256. WINAPI
  257. PostQueuedCompletionStatus(
  258. HANDLE CompletionPort,
  259. DWORD dwNumberOfBytesTransferred,
  260. ULONG_PTR dwCompletionKey,
  261. LPOVERLAPPED lpOverlapped
  262. )
  263. /*++
  264. Routine Description:
  265. This function allows the caller to post an I/O completion packet to
  266. a completion port. This packet will satisfy an outstanding call to
  267. GetQueuedCompletionStatus and will provide that caller with the three values
  268. normally returned from that call.
  269. Arguments:
  270. CompletionPort - Supplies a handle to a completion port that the caller wants to
  271. post a completion packet to.
  272. dwNumberOfBytesTransferred - Supplies the value that is to be
  273. returned through the lpNumberOfBytesTransfered parameter of the
  274. GetQueuedCompletionStatus API.
  275. dwCompletionKey - Supplies the value that is to be returned through
  276. the lpCompletionKey parameter of the GetQueuedCompletionStatus
  277. API.
  278. lpOverlapped - Supplies the value that is to be returned through the
  279. lpOverlapped parameter of the GetQueuedCompletionStatus API.
  280. Return Value:
  281. TRUE - The operation was successful
  282. FALSE - The operation failed, use GetLastError to get detailed error information
  283. --*/
  284. {
  285. NTSTATUS Status;
  286. BOOL rv;
  287. rv = TRUE;
  288. Status = NtSetIoCompletion(
  289. CompletionPort,
  290. (PVOID)dwCompletionKey,
  291. (PVOID)lpOverlapped,
  292. STATUS_SUCCESS,
  293. dwNumberOfBytesTransferred
  294. );
  295. if ( !NT_SUCCESS(Status) ) {
  296. BaseSetLastNTError(Status);
  297. rv = FALSE;
  298. }
  299. return rv;
  300. }
  301. BOOL
  302. WINAPI
  303. GetQueuedCompletionStatus(
  304. HANDLE CompletionPort,
  305. LPDWORD lpNumberOfBytesTransferred,
  306. PULONG_PTR lpCompletionKey,
  307. LPOVERLAPPED *lpOverlapped,
  308. DWORD dwMilliseconds
  309. )
  310. /*++
  311. Routine Description:
  312. This function waits for pending I/O operations associated with the
  313. specified completion port to complete. Server applications may have
  314. several threads issuing this call on the same completion port. As
  315. I/O operations complete, they are queued to this port. If threads
  316. are actively waiting in this call, queued requests complete their
  317. call.
  318. This API returns a boolean value.
  319. A value of TRUE means that a pending I/O completed successfully.
  320. The the number of bytes transfered during the I/O, the completion
  321. key that indicates which file the I/O occured on, and the overlapped
  322. structure address used in the original I/O are all returned.
  323. A value of FALSE indicates one ow two things:
  324. If *lpOverlapped is NULL, no I/O operation was dequeued. This
  325. typically means that an error occured while processing the
  326. parameters to this call, or that the CompletionPort handle has been
  327. closed or is otherwise invalid. GetLastError() may be used to
  328. further isolate this.
  329. If *lpOverlapped is non-NULL, an I/O completion packet was dequeud,
  330. but the I/O operation resulted in an error. GetLastError() can be
  331. used to further isolate the I/O error. The the number of bytes
  332. transfered during the I/O, the completion key that indicates which
  333. file the I/O occured on, and the overlapped structure address used
  334. in the original I/O are all returned.
  335. Arguments:
  336. CompletionPort - Supplies a handle to a completion port to wait on.
  337. lpNumberOfBytesTransferred - Returns the number of bytes transfered during the
  338. I/O operation whose completion is being reported.
  339. lpCompletionKey - Returns a completion key value specified during
  340. CreateIoCompletionPort. This is a per-file key that can be used
  341. to tall the caller the file that an I/O operation completed on.
  342. lpOverlapped - Returns the address of the overlapped structure that
  343. was specified when the I/O was issued. The following APIs may
  344. complete using completion ports. This ONLY occurs if the file
  345. handle is associated with with a completion port AND an
  346. overlapped structure was passed to the API.
  347. LockFileEx
  348. WriteFile
  349. ReadFile
  350. DeviceIoControl
  351. WaitCommEvent
  352. ConnectNamedPipe
  353. TransactNamedPipe
  354. dwMilliseconds - Supplies an optional timeout value that specifies
  355. how long the caller is willing to wait for an I/O completion
  356. packet.
  357. Return Value:
  358. TRUE - An I/O operation completed successfully.
  359. lpNumberOfBytesTransferred, lpCompletionKey, and lpOverlapped
  360. are all valid.
  361. FALSE - If lpOverlapped is NULL, the operation failed and no I/O
  362. completion data is retured. GetLastError() can be used to
  363. further isolate the cause of the error (bad parameters, invalid
  364. completion port handle). Otherwise, a pending I/O operation
  365. completed, but it completed with an error. GetLastError() can
  366. be used to further isolate the I/O error.
  367. lpNumberOfBytesTransferred, lpCompletionKey, and lpOverlapped
  368. are all valid.
  369. --*/
  370. {
  371. LARGE_INTEGER TimeOut;
  372. PLARGE_INTEGER pTimeOut;
  373. IO_STATUS_BLOCK IoSb;
  374. NTSTATUS Status;
  375. LPOVERLAPPED LocalOverlapped;
  376. BOOL rv;
  377. pTimeOut = BaseFormatTimeOut(&TimeOut,dwMilliseconds);
  378. Status = NtRemoveIoCompletion(
  379. CompletionPort,
  380. (PVOID *)lpCompletionKey,
  381. (PVOID *)&LocalOverlapped,
  382. &IoSb,
  383. pTimeOut
  384. );
  385. if ( !NT_SUCCESS(Status) || Status == STATUS_TIMEOUT ) {
  386. *lpOverlapped = NULL;
  387. if ( Status == STATUS_TIMEOUT ) {
  388. SetLastError(WAIT_TIMEOUT);
  389. }
  390. else {
  391. BaseSetLastNTError(Status);
  392. }
  393. rv = FALSE;
  394. }
  395. else {
  396. *lpOverlapped = LocalOverlapped;
  397. *lpNumberOfBytesTransferred = (DWORD)IoSb.Information;
  398. if ( !NT_SUCCESS(IoSb.Status) ){
  399. BaseSetLastNTError( IoSb.Status );
  400. rv = FALSE;
  401. }
  402. else {
  403. rv = TRUE;
  404. }
  405. }
  406. return rv;
  407. }
  408. BOOL
  409. WINAPI
  410. GetOverlappedResult(
  411. HANDLE hFile,
  412. LPOVERLAPPED lpOverlapped,
  413. LPDWORD lpNumberOfBytesTransferred,
  414. BOOL bWait
  415. )
  416. /*++
  417. Routine Description:
  418. The GetOverlappedResult function returns the result of the last
  419. operation that used lpOverlapped and returned ERROR_IO_PENDING.
  420. Arguments:
  421. hFile - Supplies the open handle to the file that the overlapped
  422. structure lpOverlapped was supplied to ReadFile, WriteFile,
  423. ConnectNamedPipe, WaitNamedPipe or TransactNamedPipe.
  424. lpOverlapped - Points to an OVERLAPPED structure previously supplied to
  425. ReadFile, WriteFile, ConnectNamedPipe, WaitNamedPipe or
  426. TransactNamedPipe.
  427. lpNumberOfBytesTransferred - Returns the number of bytes transferred
  428. by the operation.
  429. bWait - A boolean value that affects the behavior when the operation
  430. is still in progress. If TRUE and the operation is still in progress,
  431. GetOverlappedResult will wait for the operation to complete before
  432. returning. If FALSE and the operation is incomplete,
  433. GetOverlappedResult will return FALSE. In this case the extended
  434. error information available from the GetLastError function will be
  435. set to ERROR_IO_INCOMPLETE.
  436. Return Value:
  437. TRUE -- The operation was successful, the pipe is in the
  438. connected state.
  439. FALSE -- The operation failed. Extended error status is available using
  440. GetLastError.
  441. --*/
  442. {
  443. DWORD WaitReturn;
  444. //
  445. // Did caller specify an event to the original operation or was the
  446. // default (file handle) used?
  447. //
  448. if (lpOverlapped->Internal == (DWORD)STATUS_PENDING ) {
  449. if ( bWait ) {
  450. WaitReturn = WaitForSingleObject(
  451. ( lpOverlapped->hEvent != NULL ) ?
  452. lpOverlapped->hEvent : hFile,
  453. INFINITE
  454. );
  455. }
  456. else {
  457. WaitReturn = WAIT_TIMEOUT;
  458. }
  459. if ( WaitReturn == WAIT_TIMEOUT ) {
  460. // !bWait and event in not signalled state
  461. SetLastError( ERROR_IO_INCOMPLETE );
  462. return FALSE;
  463. }
  464. if ( WaitReturn != 0 ) {
  465. return FALSE; // WaitForSingleObject calls BaseSetLastError
  466. }
  467. }
  468. *lpNumberOfBytesTransferred = (DWORD)lpOverlapped->InternalHigh;
  469. if ( NT_SUCCESS((NTSTATUS)lpOverlapped->Internal) ){
  470. return TRUE;
  471. }
  472. else {
  473. BaseSetLastNTError( (NTSTATUS)lpOverlapped->Internal );
  474. return FALSE;
  475. }
  476. }