ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

error.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.