⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 error.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
                        if (NT_SUCCESS(Status))
                        {
                            /* Success, update the information */
                            ObjectNameInfo->Name.Length =
                                100 - (USHORT)DriverNameLength;
                        }
                    }
                }
            }
        }
        else
        {
            /* No device object, setup an empty name */
            ObjectNameInfo->Name.Length = 0;
            ObjectNameInfo->Name.Buffer = L"";
        }

        /*
         * Now make sure that the device name fits in our buffer, minus 2
         * NULL chars, and copy the name in our string buffer
         */
        DeviceNameLength = min(ObjectNameInfo->Name.Length,
                               RemainingLength - 2 * sizeof(UNICODE_NULL));
        RtlCopyMemory(StringBuffer,
                      ObjectNameInfo->Name.Buffer,
                      DeviceNameLength);

        /* Null-terminate the device name */
        *((PWSTR)(StringBuffer + DeviceNameLength)) = L'\0';
        DeviceNameLength += sizeof(WCHAR);

        /* Free the buffer if we had one */
        if (PoolObjectNameInfo) ExFreePool(PoolObjectNameInfo);

        /* Go to the next string buffer position */
        ErrorMessage->EntryData.NumberOfStrings++;
        StringBuffer += DeviceNameLength;
        RemainingLength -= DeviceNameLength;

        /* Check if we have any extra strings */
        if (Packet->NumberOfStrings)
        {
            /* Find out the size of the extra strings */
            ExtraStringLength = LogEntry->Size -
                                sizeof(ERROR_LOG_ENTRY) -
                                Packet->StringOffset;

            /* Make sure that the extra strings fit in our buffer */
            if (ExtraStringLength > (RemainingLength - sizeof(UNICODE_NULL)))
            {
                /* They wouldn't, so set normalize the length */
                MessageLength -= ExtraStringLength - RemainingLength;
                ExtraStringLength = RemainingLength - sizeof(UNICODE_NULL);
            }

            /* Now copy the extra strings */
            RtlCopyMemory(StringBuffer,
                          (PCHAR)Packet + Packet->StringOffset,
                          ExtraStringLength);

            /* Null-terminate them */
            *((PWSTR)(StringBuffer + ExtraStringLength)) = L'\0';
        }

        /* Set the driver name length */
        ErrorMessage->DriverNameLength = (USHORT)DriverNameLength;

        /* Update the message length to include the device and driver names */
        MessageLength += DeviceNameLength + DriverNameLength;
        ErrorMessage->Size = (USHORT)MessageLength;

        /* Now update it again, internally, for the size of the actual LPC */
        MessageLength += (FIELD_OFFSET(ELF_API_MSG, IoErrorMessage) -
                          FIELD_OFFSET(ELF_API_MSG, Unknown[0]));

        /* Set the total and data lengths */
        Message->h.u1.s1.TotalLength = (USHORT)(sizeof(PORT_MESSAGE) +
                                                MessageLength);
        Message->h.u1.s1.DataLength = (USHORT)(MessageLength);

        /* Send the message */
        Status = NtRequestPort(IopLogPort, (PPORT_MESSAGE)Message);
        if (!NT_SUCCESS(Status))
        {
            /* Requeue log message and restart the worker */
            ExInterlockedInsertTailList(&IopErrorLogListHead,
                                        &LogEntry->ListEntry,
                                        &IopLogListLock);
            IopLogWorkerRunning = FALSE;
            IopRestartLogWorker();
            break;
        }

        /* Derefernece the device object */
        if (LogEntry->DeviceObject) ObDereferenceObject(LogEntry->DeviceObject);
        if (DriverObject) ObDereferenceObject(LogEntry->DriverObject);

        /* Update size */
        InterlockedExchangeAdd(&IopTotalLogSize,
                               -(LONG)(LogEntry->Size -
                                       sizeof(ERROR_LOG_ENTRY)));
    }

    /* Free the LPC Message */
    ExFreePool(Message);
}

VOID
NTAPI
IopFreeApc(IN PKAPC Apc,
           IN PKNORMAL_ROUTINE *NormalRoutine,
           IN PVOID *NormalContext,
           IN PVOID *SystemArgument1,
           IN PVOID *SystemArgument2)
{
    /* Free the APC */
    ExFreePool(Apc);
}

VOID
NTAPI
IopRaiseHardError(IN PKAPC Apc,
                  IN PKNORMAL_ROUTINE *NormalRoutine,
                  IN PVOID *NormalContext,
                  IN PVOID *SystemArgument1,
                  IN PVOID *SystemArgument2)
{
    PIRP Irp = (PIRP)NormalContext;
    //PVPB Vpb = (PVPB)SystemArgument1;
    //PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)SystemArgument2;

    /* FIXME: UNIMPLEMENTED */
    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
}

/* PUBLIC FUNCTIONS **********************************************************/

/*
 * @implemented
 */
PVOID
NTAPI
IoAllocateErrorLogEntry(IN PVOID IoObject,
                        IN UCHAR EntrySize)
{
    PERROR_LOG_ENTRY LogEntry;
    ULONG LogEntrySize;
    PDRIVER_OBJECT DriverObject;
    PDEVICE_OBJECT DeviceObject;

    /* Make sure we have an object */
    if (!IoObject) return NULL;

    /* Check if we're past our buffer */
    if (IopTotalLogSize > PAGE_SIZE) return NULL;

    /* Calculate the total size and allocate it */
    LogEntrySize = sizeof(ERROR_LOG_ENTRY) + EntrySize;
    LogEntry = ExAllocatePoolWithTag(NonPagedPool,
                                     LogEntrySize,
                                     TAG_ERROR_LOG);
    if (!LogEntry) return NULL;

    /* Check if this is a device object or driver object */
    if (((PDEVICE_OBJECT)IoObject)->Type == IO_TYPE_DEVICE)
    {
        /* It's a device, get the driver */
        DeviceObject = (PDEVICE_OBJECT)IoObject;
        DriverObject = DeviceObject->DriverObject;
    }
    else if (((PDEVICE_OBJECT)IoObject)->Type == IO_TYPE_DRIVER)
    {
        /* It's a driver, so we don' thave a device */
        DeviceObject = NULL;
        DriverObject = IoObject;
    }
    else
    {
        /* Fail */
        return NULL;
    }

    /* Reference the Objects */
    if (DeviceObject) ObReferenceObject(DeviceObject);
    if (DriverObject) ObReferenceObject(DriverObject);

    /* Update log size */
    InterlockedExchangeAdd(&IopTotalLogSize, EntrySize);

    /* Clear the entry and set it up */
    RtlZeroMemory(LogEntry, EntrySize);
    LogEntry->Type = IO_TYPE_ERROR_LOG;
    LogEntry->Size = EntrySize;
    LogEntry->DeviceObject = DeviceObject;
    LogEntry->DriverObject = DriverObject;

    /* Return the entry data */
    return (PVOID)((ULONG_PTR)LogEntry + sizeof(ERROR_LOG_ENTRY));
}

/*
 * @implemented
 */
VOID
NTAPI
IoFreeErrorLogEntry(IN PVOID ElEntry)
{
    PERROR_LOG_ENTRY LogEntry;

    /* Make sure there's an entry */
    if (!ElEntry) return;

    /* Get the actual header */
    LogEntry = (PERROR_LOG_ENTRY)((ULONG_PTR)ElEntry - sizeof(ERROR_LOG_ENTRY));

    /* Dereference both objects */
    if (LogEntry->DeviceObject) ObDereferenceObject(LogEntry->DeviceObject);
    if (LogEntry->DriverObject) ObDereferenceObject(LogEntry->DriverObject);

    /* Decrease total allocation size and free the entry */
    InterlockedExchangeAdd(&IopTotalLogSize,
                           -(LONG)(LogEntry->Size - sizeof(ERROR_LOG_ENTRY)));
    ExFreePool(LogEntry);
}

/*
 * @implemented
 */
VOID
NTAPI
IoWriteErrorLogEntry(IN PVOID ElEntry)
{
    PERROR_LOG_ENTRY LogEntry;
    KIRQL Irql;

    /* Get the main header */
    LogEntry = (PERROR_LOG_ENTRY)((ULONG_PTR)ElEntry -
                                  sizeof(ERROR_LOG_ENTRY));

    /* Get time stamp */
    KeQuerySystemTime(&LogEntry->TimeStamp);

    /* Acquire the lock and insert this write in the list */
    KeAcquireSpinLock(&IopLogListLock, &Irql);
    InsertHeadList(&IopErrorLogListHead, &LogEntry->ListEntry);

    /* Check if the worker is runnign */
    if (!IopLogWorkerRunning)
    {
#if 0
        /* It's not, initialize it and queue it */
        ExInitializeWorkItem(&IopErrorLogWorkItem,
                             IopLogWorker,
                             &IopErrorLogWorkItem);
        ExQueueWorkItem(&IopErrorLogWorkItem, DelayedWorkQueue);
        IopLogWorkerRunning = TRUE;
#endif
    }

    /* Release the lock and return */
    KeReleaseSpinLock(&IopLogListLock, Irql);
}

/*
 * @implemented
 */
VOID
NTAPI
IoRaiseHardError(IN PIRP Irp,
                 IN PVPB Vpb,
                 IN PDEVICE_OBJECT RealDeviceObject)
{
    PETHREAD Thread = (PETHREAD)&Irp->Tail.Overlay.Thread;
    PKAPC ErrorApc;

    /* Don't do anything if hard errors are disabled on the thread */
    if (Thread->HardErrorsAreDisabled)
    {
        /* Complete the request */
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
        return;
    }

    /* Setup an APC */
    ErrorApc = ExAllocatePoolWithTag(NonPagedPool,
                                     sizeof(KAPC),
                                     TAG_APC);
    KeInitializeApc(ErrorApc,
                    &Thread->Tcb,
                    Irp->ApcEnvironment,
                    NULL,
                    (PKRUNDOWN_ROUTINE)IopFreeApc,
                    (PKNORMAL_ROUTINE)IopRaiseHardError,
                    KernelMode,
                    Irp);

    /* Queue an APC to deal with the error (see osr documentation) */
    KeInsertQueueApc(ErrorApc, Vpb, RealDeviceObject, 0);
}

/*
 * @unimplemented
 */
BOOLEAN
NTAPI
IoRaiseInformationalHardError(IN NTSTATUS ErrorStatus,
                              IN PUNICODE_STRING String,
                              IN PKTHREAD Thread)
{
    UNIMPLEMENTED;
    return(FALSE);
}

/*
 * @implemented
 */
BOOLEAN
NTAPI
IoSetThreadHardErrorMode(IN BOOLEAN HardErrorEnabled)
{
    PETHREAD Thread = PsGetCurrentThread();
    BOOLEAN Old;

    /* Get the current value */
    Old = !Thread->HardErrorsAreDisabled;

    /* Set the new one and return the old */
    Thread->HardErrorsAreDisabled = !HardErrorEnabled;
    return Old;
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -