Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenerror.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/io/error.c 00005 * PURPOSE: I/O Error Functions and Error Log Support 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Eric Kohl 00008 */ 00009 /* INCLUDES *****************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* TYPES *********************************************************************/ 00016 00017 typedef struct _IOP_ERROR_LOG_WORKER_DPC 00018 { 00019 KDPC Dpc; 00020 KTIMER Timer; 00021 } IOP_ERROR_LOG_WORKER_DPC, *PIOP_ERROR_LOG_WORKER_DPC; 00022 00023 /* GLOBALS *******************************************************************/ 00024 00025 LONG IopTotalLogSize; 00026 LIST_ENTRY IopErrorLogListHead; 00027 KSPIN_LOCK IopLogListLock; 00028 00029 BOOLEAN IopLogWorkerRunning; 00030 BOOLEAN IopLogPortConnected; 00031 HANDLE IopLogPort; 00032 WORK_QUEUE_ITEM IopErrorLogWorkItem; 00033 00034 PDEVICE_OBJECT IopErrorLogObject; 00035 00036 /* PRIVATE FUNCTIONS *********************************************************/ 00037 00038 VOID 00039 NTAPI 00040 IopLogDpcRoutine(IN PKDPC Dpc, 00041 IN PVOID DeferredContext, 00042 IN PVOID SystemArgument1, 00043 IN PVOID SystemArgument2) 00044 { 00045 /* If we have a DPC, free it */ 00046 if (Dpc) ExFreePool(Dpc); 00047 00048 /* Initialize and queue the work item */ 00049 ExInitializeWorkItem(&IopErrorLogWorkItem, IopLogWorker, NULL); 00050 ExQueueWorkItem(&IopErrorLogWorkItem, DelayedWorkQueue); 00051 } 00052 00053 PLIST_ENTRY 00054 NTAPI 00055 IopGetErrorLogEntry(VOID) 00056 { 00057 KIRQL OldIrql; 00058 PLIST_ENTRY ListEntry; 00059 00060 /* Acquire the lock and check if the list is empty */ 00061 KeAcquireSpinLock(&IopLogListLock, &OldIrql); 00062 if (IsListEmpty(&IopErrorLogListHead)) 00063 { 00064 /* List is empty, disable the worker and return NULL */ 00065 IopLogWorkerRunning = FALSE; 00066 ListEntry = NULL; 00067 } 00068 else 00069 { 00070 /* Otherwise, remove an entry */ 00071 ListEntry = RemoveHeadList(&IopErrorLogListHead); 00072 } 00073 00074 /* Release the lock and return the entry */ 00075 KeReleaseSpinLock(&IopLogListLock, OldIrql); 00076 return ListEntry; 00077 } 00078 00079 VOID 00080 NTAPI 00081 IopRestartLogWorker(VOID) 00082 { 00083 PIOP_ERROR_LOG_WORKER_DPC WorkerDpc; 00084 LARGE_INTEGER Timeout; 00085 00086 /* Allocate a DPC Context */ 00087 WorkerDpc = ExAllocatePool(NonPagedPool, sizeof(IOP_ERROR_LOG_WORKER_DPC)); 00088 if (!WorkerDpc) 00089 { 00090 /* Fail */ 00091 IopLogWorkerRunning = FALSE; 00092 return; 00093 } 00094 00095 /* Initialize DPC and Timer */ 00096 KeInitializeDpc(&WorkerDpc->Dpc, IopLogDpcRoutine, WorkerDpc); 00097 KeInitializeTimer(&WorkerDpc->Timer); 00098 00099 /* Restart after 30 seconds */ 00100 Timeout.QuadPart = (LONGLONG)-300000000; 00101 KeSetTimer(&WorkerDpc->Timer, Timeout, &WorkerDpc->Dpc); 00102 } 00103 00104 BOOLEAN 00105 NTAPI 00106 IopConnectLogPort(VOID) 00107 { 00108 UNICODE_STRING PortName = RTL_CONSTANT_STRING(L"\\ErrorLogPort"); 00109 NTSTATUS Status; 00110 00111 /* Make sure we're not already connected */ 00112 if (IopLogPortConnected) return TRUE; 00113 00114 /* Connect the port */ 00115 Status = ZwConnectPort(&IopLogPort, 00116 &PortName, 00117 NULL, 00118 NULL, 00119 NULL, 00120 NULL, 00121 NULL, 00122 NULL); 00123 if (NT_SUCCESS(Status)) 00124 { 00125 /* Remember we're connected */ 00126 IopLogPortConnected = TRUE; 00127 return TRUE; 00128 } 00129 00130 /* We failed, try again */ 00131 IopRestartLogWorker(); 00132 return FALSE; 00133 } 00134 00135 VOID 00136 NTAPI 00137 IopLogWorker(IN PVOID Parameter) 00138 { 00139 PELF_API_MSG Message; 00140 PIO_ERROR_LOG_MESSAGE ErrorMessage; 00141 PLIST_ENTRY ListEntry; 00142 PERROR_LOG_ENTRY LogEntry; 00143 PIO_ERROR_LOG_PACKET Packet; 00144 PCHAR StringBuffer; 00145 ULONG RemainingLength; 00146 PDRIVER_OBJECT DriverObject; 00147 ULONG DriverNameLength = 0, DeviceNameLength; 00148 UNICODE_STRING DriverNameString; 00149 NTSTATUS Status; 00150 UCHAR Buffer[256]; 00151 POBJECT_NAME_INFORMATION ObjectNameInfo = (POBJECT_NAME_INFORMATION)&Buffer; 00152 POBJECT_NAME_INFORMATION PoolObjectNameInfo = NULL; 00153 ULONG ReturnedLength, MessageLength; 00154 PWCHAR p; 00155 ULONG ExtraStringLength; 00156 PAGED_CODE(); 00157 00158 /* Connect to the port */ 00159 if (!IopConnectLogPort()) return; 00160 00161 /* Allocate the message */ 00162 Message = ExAllocatePool(PagedPool, IO_ERROR_LOG_MESSAGE_LENGTH); 00163 if (!Message) 00164 { 00165 /* Couldn't allocate, try again */ 00166 IopRestartLogWorker(); 00167 return; 00168 } 00169 00170 /* Copy the message */ 00171 RtlZeroMemory(Message, sizeof(ELF_API_MSG)); 00172 00173 /* Get the actual I/O Structure */ 00174 ErrorMessage = &Message->IoErrorMessage; 00175 00176 /* Start loop */ 00177 while (TRUE) 00178 { 00179 /* Get an entry */ 00180 ListEntry = IopGetErrorLogEntry(); 00181 if (!ListEntry) break; 00182 LogEntry = CONTAINING_RECORD(ListEntry, ERROR_LOG_ENTRY, ListEntry); 00183 00184 /* Get pointer to the log packet */ 00185 Packet = (PIO_ERROR_LOG_PACKET)((ULONG_PTR)LogEntry + 00186 sizeof(ERROR_LOG_ENTRY)); 00187 00188 /* Calculate the total length of the message only */ 00189 MessageLength = sizeof(IO_ERROR_LOG_MESSAGE) - 00190 sizeof(ERROR_LOG_ENTRY) - 00191 sizeof(IO_ERROR_LOG_PACKET) + 00192 LogEntry->Size; 00193 00194 /* Copy the packet */ 00195 RtlCopyMemory(&ErrorMessage->EntryData, 00196 Packet, 00197 LogEntry->Size - sizeof(ERROR_LOG_ENTRY)); 00198 00199 /* Set the timestamp and time */ 00200 ErrorMessage->TimeStamp = LogEntry->TimeStamp; 00201 ErrorMessage->Type = IO_TYPE_ERROR_MESSAGE; 00202 00203 /* Check if this message has any strings */ 00204 if (Packet->NumberOfStrings) 00205 { 00206 /* String buffer is after the current strings */ 00207 StringBuffer = (PCHAR)&ErrorMessage->EntryData + 00208 Packet->StringOffset; 00209 } 00210 else 00211 { 00212 /* Otherwise, string buffer is at the end */ 00213 StringBuffer = (PCHAR)ErrorMessage + MessageLength; 00214 } 00215 00216 /* Align the buffer */ 00217 StringBuffer = ALIGN_UP_POINTER(StringBuffer, WCHAR); 00218 00219 /* Set the offset for the driver's name to the current buffer */ 00220 ErrorMessage->DriverNameOffset = (ULONG)(StringBuffer - 00221 (PCHAR)ErrorMessage); 00222 00223 /* Check how much space we have left for the device string */ 00224 RemainingLength = (ULONG)((ULONG_PTR)Message + 00225 IO_ERROR_LOG_MESSAGE_LENGTH - 00226 (ULONG_PTR)StringBuffer); 00227 00228 /* Now check if there is a driver object */ 00229 DriverObject = LogEntry->DriverObject; 00230 if (DriverObject) 00231 { 00232 /* Check if the driver has a name */ 00233 if (DriverObject->DriverName.Buffer) 00234 { 00235 /* Use its name */ 00236 DriverNameString.Buffer = DriverObject->DriverName.Buffer; 00237 DriverNameLength = DriverObject->DriverName.Length; 00238 } 00239 else 00240 DriverNameString.Buffer = NULL; 00241 00242 /* Check if there isn't a valid name*/ 00243 if (!DriverNameLength) 00244 { 00245 /* Query the name directly */ 00246 Status = ObQueryNameString(DriverObject, 00247 ObjectNameInfo, 00248 sizeof(Buffer), 00249 &ReturnedLength); 00250 if (!(NT_SUCCESS(Status)) || !(ObjectNameInfo->Name.Length)) 00251 { 00252 /* We don't have a name */ 00253 DriverNameLength = 0; 00254 } 00255 } 00256 } 00257 else 00258 { 00259 /* Use default name */ 00260 DriverNameString.Buffer = L"Application Popup"; 00261 DriverNameLength = (ULONG)wcslen(DriverNameString.Buffer) * sizeof(WCHAR); 00262 } 00263 00264 /* Check if we have a driver name by here */ 00265 if (DriverNameLength) 00266 { 00267 /* Skip to the end of the driver's name */ 00268 p = &DriverNameString.Buffer[DriverNameLength / sizeof(WCHAR)]; 00269 00270 /* Now we'll walk backwards and assume the minimum size */ 00271 DriverNameLength = sizeof(WCHAR); 00272 p--; 00273 while ((*p != L'\\') && (p != DriverNameString.Buffer)) 00274 { 00275 /* No backslash found, keep going */ 00276 p--; 00277 DriverNameLength += sizeof(WCHAR); 00278 } 00279 00280 /* Now we probably hit the backslash itself, skip past it */ 00281 if (*p == L'\\') 00282 { 00283 p++; 00284 DriverNameLength -= sizeof(WCHAR); 00285 } 00286 00287 /* 00288 * Now make sure that the driver name fits in our buffer, minus 3 00289 * NULL chars, and copy the name in our string buffer 00290 */ 00291 DriverNameLength = min(DriverNameLength, 00292 RemainingLength - 3 * sizeof(UNICODE_NULL)); 00293 RtlCopyMemory(StringBuffer, p, DriverNameLength); 00294 } 00295 00296 /* Null-terminate the driver name */ 00297 *((PWSTR)(StringBuffer + DriverNameLength)) = L'\0'; 00298 DriverNameLength += sizeof(WCHAR); 00299 00300 /* Go to the next string buffer position */ 00301 StringBuffer += DriverNameLength; 00302 RemainingLength -= DriverNameLength; 00303 00304 /* Update the string offset and check if we have a device object */ 00305 ErrorMessage->EntryData.StringOffset = (USHORT) 00306 ((ULONG_PTR)StringBuffer - 00307 (ULONG_PTR)ErrorMessage); 00308 if (LogEntry->DeviceObject) 00309 { 00310 /* We do, query its name */ 00311 Status = ObQueryNameString(LogEntry->DeviceObject, 00312 ObjectNameInfo, 00313 sizeof(OBJECT_NAME_INFORMATION) + 00314 100 - 00315 DriverNameLength, 00316 &ReturnedLength); 00317 if ((!NT_SUCCESS(Status)) || !(ObjectNameInfo->Name.Length)) 00318 { 00319 /* Setup an empty name */ 00320 ObjectNameInfo->Name.Length = 0; 00321 ObjectNameInfo->Name.Buffer = L""; 00322 00323 /* Check if we failed because our buffer wasn't large enough */ 00324 if (Status == STATUS_INFO_LENGTH_MISMATCH) 00325 { 00326 /* Then we'll allocate one... we really want this name! */ 00327 PoolObjectNameInfo = ExAllocatePoolWithTag(PagedPool, 00328 ReturnedLength, 00329 TAG_IO); 00330 if (PoolObjectNameInfo) 00331 { 00332 /* Query it again */ 00333 ObjectNameInfo = PoolObjectNameInfo; 00334 Status = ObQueryNameString(LogEntry->DeviceObject, 00335 ObjectNameInfo, 00336 ReturnedLength, 00337 &ReturnedLength); 00338 if (NT_SUCCESS(Status)) 00339 { 00340 /* Success, update the information */ 00341 ObjectNameInfo->Name.Length = 00342 100 - (USHORT)DriverNameLength; 00343 } 00344 } 00345 } 00346 } 00347 } 00348 else 00349 { 00350 /* No device object, setup an empty name */ 00351 ObjectNameInfo->Name.Length = 0; 00352 ObjectNameInfo->Name.Buffer = L""; 00353 } 00354 00355 /* 00356 * Now make sure that the device name fits in our buffer, minus 2 00357 * NULL chars, and copy the name in our string buffer 00358 */ 00359 DeviceNameLength = min(ObjectNameInfo->Name.Length, 00360 RemainingLength - 2 * sizeof(UNICODE_NULL)); 00361 RtlCopyMemory(StringBuffer, 00362 ObjectNameInfo->Name.Buffer, 00363 DeviceNameLength); 00364 00365 /* Null-terminate the device name */ 00366 *((PWSTR)(StringBuffer + DeviceNameLength)) = L'\0'; 00367 DeviceNameLength += sizeof(WCHAR); 00368 00369 /* Free the buffer if we had one */ 00370 if (PoolObjectNameInfo) ExFreePool(PoolObjectNameInfo); 00371 00372 /* Go to the next string buffer position */ 00373 ErrorMessage->EntryData.NumberOfStrings++; 00374 StringBuffer += DeviceNameLength; 00375 RemainingLength -= DeviceNameLength; 00376 00377 /* Check if we have any extra strings */ 00378 if (Packet->NumberOfStrings) 00379 { 00380 /* Find out the size of the extra strings */ 00381 ExtraStringLength = LogEntry->Size - 00382 sizeof(ERROR_LOG_ENTRY) - 00383 Packet->StringOffset; 00384 00385 /* Make sure that the extra strings fit in our buffer */ 00386 if (ExtraStringLength > (RemainingLength - sizeof(UNICODE_NULL))) 00387 { 00388 /* They wouldn't, so set normalize the length */ 00389 MessageLength -= ExtraStringLength - RemainingLength; 00390 ExtraStringLength = RemainingLength - sizeof(UNICODE_NULL); 00391 } 00392 00393 /* Now copy the extra strings */ 00394 RtlCopyMemory(StringBuffer, 00395 (PCHAR)Packet + Packet->StringOffset, 00396 ExtraStringLength); 00397 00398 /* Null-terminate them */ 00399 *((PWSTR)(StringBuffer + ExtraStringLength)) = L'\0'; 00400 } 00401 00402 /* Set the driver name length */ 00403 ErrorMessage->DriverNameLength = (USHORT)DriverNameLength; 00404 00405 /* Update the message length to include the device and driver names */ 00406 MessageLength += DeviceNameLength + DriverNameLength; 00407 ErrorMessage->Size = (USHORT)MessageLength; 00408 00409 /* Now update it again, internally, for the size of the actual LPC */ 00410 MessageLength += (FIELD_OFFSET(ELF_API_MSG, IoErrorMessage) - 00411 FIELD_OFFSET(ELF_API_MSG, Unknown[0])); 00412 00413 /* Set the total and data lengths */ 00414 Message->h.u1.s1.TotalLength = (USHORT)(sizeof(PORT_MESSAGE) + 00415 MessageLength); 00416 Message->h.u1.s1.DataLength = (USHORT)(MessageLength); 00417 00418 /* Send the message */ 00419 Status = NtRequestPort(IopLogPort, (PPORT_MESSAGE)Message); 00420 if (!NT_SUCCESS(Status)) 00421 { 00422 /* Requeue log message and restart the worker */ 00423 ExInterlockedInsertTailList(&IopErrorLogListHead, 00424 &LogEntry->ListEntry, 00425 &IopLogListLock); 00426 IopLogWorkerRunning = FALSE; 00427 IopRestartLogWorker(); 00428 break; 00429 } 00430 00431 /* Derefernece the device object */ 00432 if (LogEntry->DeviceObject) ObDereferenceObject(LogEntry->DeviceObject); 00433 if (DriverObject) ObDereferenceObject(LogEntry->DriverObject); 00434 00435 /* Update size */ 00436 InterlockedExchangeAdd(&IopTotalLogSize, 00437 -(LONG)(LogEntry->Size - 00438 sizeof(ERROR_LOG_ENTRY))); 00439 } 00440 00441 /* Free the LPC Message */ 00442 ExFreePool(Message); 00443 } 00444 00445 VOID 00446 NTAPI 00447 IopFreeApc(IN PKAPC Apc, 00448 IN PKNORMAL_ROUTINE *NormalRoutine, 00449 IN PVOID *NormalContext, 00450 IN PVOID *SystemArgument1, 00451 IN PVOID *SystemArgument2) 00452 { 00453 /* Free the APC */ 00454 ExFreePool(Apc); 00455 } 00456 00457 VOID 00458 NTAPI 00459 IopRaiseHardError(IN PKAPC Apc, 00460 IN PKNORMAL_ROUTINE *NormalRoutine, 00461 IN PVOID *NormalContext, 00462 IN PVOID *SystemArgument1, 00463 IN PVOID *SystemArgument2) 00464 { 00465 PIRP Irp = (PIRP)NormalContext; 00466 //PVPB Vpb = (PVPB)SystemArgument1; 00467 //PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)SystemArgument2; 00468 00469 UNIMPLEMENTED; 00470 00471 /* FIXME: UNIMPLEMENTED */ 00472 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; 00473 Irp->IoStatus.Information = 0; 00474 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 00475 } 00476 00477 /* PUBLIC FUNCTIONS **********************************************************/ 00478 00479 /* 00480 * @implemented 00481 */ 00482 PVOID 00483 NTAPI 00484 IoAllocateErrorLogEntry(IN PVOID IoObject, 00485 IN UCHAR EntrySize) 00486 { 00487 PERROR_LOG_ENTRY LogEntry; 00488 ULONG LogEntrySize; 00489 PDRIVER_OBJECT DriverObject; 00490 PDEVICE_OBJECT DeviceObject; 00491 00492 /* Make sure we have an object */ 00493 if (!IoObject) return NULL; 00494 00495 /* Check if we're past our buffer */ 00496 if (IopTotalLogSize > PAGE_SIZE) return NULL; 00497 00498 /* Calculate the total size and allocate it */ 00499 LogEntrySize = sizeof(ERROR_LOG_ENTRY) + EntrySize; 00500 LogEntry = ExAllocatePoolWithTag(NonPagedPool, 00501 LogEntrySize, 00502 TAG_ERROR_LOG); 00503 if (!LogEntry) return NULL; 00504 00505 /* Check if this is a device object or driver object */ 00506 if (((PDEVICE_OBJECT)IoObject)->Type == IO_TYPE_DEVICE) 00507 { 00508 /* It's a device, get the driver */ 00509 DeviceObject = (PDEVICE_OBJECT)IoObject; 00510 DriverObject = DeviceObject->DriverObject; 00511 } 00512 else if (((PDEVICE_OBJECT)IoObject)->Type == IO_TYPE_DRIVER) 00513 { 00514 /* It's a driver, so we don' thave a device */ 00515 DeviceObject = NULL; 00516 DriverObject = IoObject; 00517 } 00518 else 00519 { 00520 /* Fail */ 00521 return NULL; 00522 } 00523 00524 /* Reference the Objects */ 00525 if (DeviceObject) ObReferenceObject(DeviceObject); 00526 if (DriverObject) ObReferenceObject(DriverObject); 00527 00528 /* Update log size */ 00529 InterlockedExchangeAdd(&IopTotalLogSize, EntrySize); 00530 00531 /* Clear the entry and set it up */ 00532 RtlZeroMemory(LogEntry, EntrySize); 00533 LogEntry->Type = IO_TYPE_ERROR_LOG; 00534 LogEntry->Size = EntrySize; 00535 LogEntry->DeviceObject = DeviceObject; 00536 LogEntry->DriverObject = DriverObject; 00537 00538 /* Return the entry data */ 00539 return (PVOID)((ULONG_PTR)LogEntry + sizeof(ERROR_LOG_ENTRY)); 00540 } 00541 00542 /* 00543 * @implemented 00544 */ 00545 VOID 00546 NTAPI 00547 IoFreeErrorLogEntry(IN PVOID ElEntry) 00548 { 00549 PERROR_LOG_ENTRY LogEntry; 00550 00551 /* Make sure there's an entry */ 00552 if (!ElEntry) return; 00553 00554 /* Get the actual header */ 00555 LogEntry = (PERROR_LOG_ENTRY)((ULONG_PTR)ElEntry - sizeof(ERROR_LOG_ENTRY)); 00556 00557 /* Dereference both objects */ 00558 if (LogEntry->DeviceObject) ObDereferenceObject(LogEntry->DeviceObject); 00559 if (LogEntry->DriverObject) ObDereferenceObject(LogEntry->DriverObject); 00560 00561 /* Decrease total allocation size and free the entry */ 00562 InterlockedExchangeAdd(&IopTotalLogSize, 00563 -(LONG)(LogEntry->Size - sizeof(ERROR_LOG_ENTRY))); 00564 ExFreePool(LogEntry); 00565 } 00566 00567 /* 00568 * @implemented 00569 */ 00570 VOID 00571 NTAPI 00572 IoWriteErrorLogEntry(IN PVOID ElEntry) 00573 { 00574 PERROR_LOG_ENTRY LogEntry; 00575 KIRQL Irql; 00576 00577 /* Get the main header */ 00578 LogEntry = (PERROR_LOG_ENTRY)((ULONG_PTR)ElEntry - 00579 sizeof(ERROR_LOG_ENTRY)); 00580 00581 /* Get time stamp */ 00582 KeQuerySystemTime(&LogEntry->TimeStamp); 00583 00584 /* Acquire the lock and insert this write in the list */ 00585 KeAcquireSpinLock(&IopLogListLock, &Irql); 00586 InsertHeadList(&IopErrorLogListHead, &LogEntry->ListEntry); 00587 00588 /* Check if the worker is running */ 00589 if (!IopLogWorkerRunning) 00590 { 00591 #if 0 00592 /* It's not, initialize it and queue it */ 00593 ExInitializeWorkItem(&IopErrorLogWorkItem, 00594 IopLogWorker, 00595 &IopErrorLogWorkItem); 00596 ExQueueWorkItem(&IopErrorLogWorkItem, DelayedWorkQueue); 00597 IopLogWorkerRunning = TRUE; 00598 #endif 00599 } 00600 00601 /* Release the lock and return */ 00602 KeReleaseSpinLock(&IopLogListLock, Irql); 00603 } 00604 00605 /* 00606 * @implemented 00607 */ 00608 VOID 00609 NTAPI 00610 IoRaiseHardError(IN PIRP Irp, 00611 IN PVPB Vpb, 00612 IN PDEVICE_OBJECT RealDeviceObject) 00613 { 00614 PETHREAD Thread = (PETHREAD)&Irp->Tail.Overlay.Thread; 00615 PKAPC ErrorApc; 00616 00617 /* Don't do anything if hard errors are disabled on the thread */ 00618 if (Thread->HardErrorsAreDisabled) 00619 { 00620 /* Complete the request */ 00621 Irp->IoStatus.Information = 0; 00622 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 00623 return; 00624 } 00625 00626 /* Setup an APC */ 00627 ErrorApc = ExAllocatePoolWithTag(NonPagedPool, 00628 sizeof(KAPC), 00629 TAG_APC); 00630 KeInitializeApc(ErrorApc, 00631 &Thread->Tcb, 00632 Irp->ApcEnvironment, 00633 NULL, 00634 (PKRUNDOWN_ROUTINE)IopFreeApc, 00635 (PKNORMAL_ROUTINE)IopRaiseHardError, 00636 KernelMode, 00637 Irp); 00638 00639 /* Queue an APC to deal with the error (see osr documentation) */ 00640 KeInsertQueueApc(ErrorApc, Vpb, RealDeviceObject, 0); 00641 } 00642 00643 /* 00644 * @unimplemented 00645 */ 00646 BOOLEAN 00647 NTAPI 00648 IoRaiseInformationalHardError(IN NTSTATUS ErrorStatus, 00649 IN PUNICODE_STRING String, 00650 IN PKTHREAD Thread) 00651 { 00652 UNIMPLEMENTED; 00653 return FALSE; 00654 } 00655 00656 /* 00657 * @implemented 00658 */ 00659 BOOLEAN 00660 NTAPI 00661 IoSetThreadHardErrorMode(IN BOOLEAN HardErrorEnabled) 00662 { 00663 PETHREAD Thread = PsGetCurrentThread(); 00664 BOOLEAN OldMode; 00665 00666 /* Get the current value */ 00667 OldMode = !Thread->HardErrorsAreDisabled; 00668 00669 /* Set the new one and return the old */ 00670 Thread->HardErrorsAreDisabled = !HardErrorEnabled; 00671 return OldMode; 00672 } Generated on Fri May 25 2012 04:15:46 for ReactOS by
1.7.6.1
|