Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571*** This file contains messages I've culled off the net as wellas previous discussions all of which have useful info on fixesthat need to be added to ReactOS. messages are between fivedashes on a line by themselves. If you implement the fixreffered to in a message, feel free to delete it from the file.Rex ***-----Subject: [ros-kernel] Inside the Boot ProcessDate: Mon, 22 Mar 1999 22:05:47 +0100From: Emanuele Aliberti <ea@iol.it>For those working on the boot loader: in WinNt Magazine november 1998issue (http://www.winntmag.com/) there is a detailed description, byMark Russinovich, of the r�le the MBR, NTLDR, boot.ini, ntdetect.com...play in the boot process ("Inside the Boot Process, Part 1").-----Yes with DPCs, KeDrainDpcQueue should go to HIGH_LEVEL becauseit needs to synchronize with KeInsertDpcQueue. Also the idle threadshould run at DISPATCH_LEVEL and regularly drain the dpc queue, thatway if an irq happens and the dpc can't be executed immediately itwill be executed as soon as the processor is idle rather thanwaiting for the next timer tick-----About the console driver, I think it might be quite useful to have a simpleway for apps to print to the screen for debugging. But when the kernel is morestable, console handling should be moved to user level because console printingneeds to know about windows and so on which can only be done at user level.-----Subject: Re: IMSAMP-how to avoid rebooting?Date: 9 Nov 1998 00:40:32 -0000From: Charles Bryant <n51190709.ch@chch.demon.co.uk>Newsgroups: comp.os.ms-windows.programmer.nt.kernel-modeReferences: 1, 2 , 3 , 4In article <un264wzle.fsf@xxx.yyy.zzz>, David C. <qqqq@xxx.yyy.zzz> wrote:>The reason it won't unload when something is bound to it is the same>reason you can't unload any other driver that has an open client. If>you install any driver, and have a user program (or another driver) open>a handle to it, and then give the "net stop" command to unload it,>you'll find that the unload will be delayed until the user program>closes its handle.When developing a driver I found this to be a considerable nuisance.Frequently a bug would leave an IRP stuck in the driver and Icouldn't unload and reload a fixed version. While reading NTDDK.H Ifound a suspicious constant and discovered that the Flags field inthe device (the one which you OR in DO_BUFFERED_IO or DO_DIRECT_IO)has a bit called DO_UNLOAD_PENDING. By experiment I confirmed thatthis bit is set when you do 'net stop', so a driver can check itperiodically (e.g. from a timer DPC every ten seconds) and cancel allqueued IRPs if it is found to be set.Since this is not documented anywhere that I can find, it might beunwise to rely on it for production code, but it is very useful fordebugging. Maybe someone with internals knowledge can comment on thereliability of it.-----Subject: Re: Kernel bugsDate: Fri, 23 Oct 1998 12:08:36 -0700From: rex <rex@lvcablemodem.com>To: Jason Filby <jasonfilby@yahoo.com>References: 1Jason Filby wrote:> Hi,>> Ok -- here's most of what I get when I press a key:>> Page fault detected at address 1fd4 with eip c042f794> Recursive page fault detected> Exception 14(2)> CS:EIP 20:c042f794>> Rex -- do you know of anyway to find out which function in what file> is causing the exception? I know that for problems in the kernel, you> just look in the ntoskrnl\kernel.sym file and find the EIP value which> matches the one given in the exception debug text. But what about> modules? How can we track exceptions that occur in functions in modules?>I know this is a little belated, but I thought I'd take astab at answeringthis anyway. add an option to themakefile for the module to generate a listing file withsymbol information. Then, on a boot test, note theaddress that the module is loaded at, and subtractthis from the EIP value. add any offset used in themodule link specification (I dont think there currentlyis one), and look for the last symbol with a loweraddress offset.Brian, I have an idea on how to make this exceptiondump information a little more useful. We shouldhave the load information for the load modulesin memory somewhere. Perhaps the exceptiondump could check offending addresses to see ifthey lie in the kernel or in a module, and if theylie in a module the proper offset could be subtractedand this number could be displayed seperately. IfI get a chance today, I'll make this change and sendit to ya.Rex.-----Subject: Re: Question on "Sending buffers on the stack to asynchronous DeviceIoControl with buffered I/O"Date: Mon, 16 Nov 1998 11:24:57 -0800From: "-Paul" <paulsan@microsoftSPAM.com>Organization: Microsoft Corp.Newsgroups: microsoft.public.win32.programmer.kernel, comp.os.ms-windows.programmer.nt.kernel-modeReferences: 1Radu, I post the following information occassionally for questions such asyours. I hope it helps.-PaulHere is an explanation of buffers and DeviceIoControl.First, here are the parameters,BOOL DeviceIoControl( HANDLE hDevice, // handle to device of interest DWORD dwIoControlCode, // control code of operation to perform LPVOID lpInBuffer, // pointer to buffer to supply input data DWORD nInBufferSize, // size of input buffer LPVOID lpOutBuffer, // pointer to buffer to receive output data DWORD nOutBufferSize, // size of output buffer LPDWORD lpBytesReturned, // pointer to variable to receive output bytecount LPOVERLAPPED lpOverlapped // pointer to overlapped structure forasynchronous operation );METHOD_BUFFEREDuser-mode perspectivelpInBuffer - optional, contains data that is written to the driverlpOutBuffer - optional, contains data that is read from the driver afterthe call has completedlpInBuffer and lpOutBuffer can be two buffers or a single shared buffer.If a shared buffer, lpInBuffer is overwritten by lpOutBuffer.I/O Manager perspectiveexamines nInBufferSize and nOutBufferSize. Allocates memory from non-pagedpool and puts the address of this pool in Irp->AssociatedIrp.SystemBuffer.The size of this buffer is equal to the size of the larger of the twobufferes. This buffer is accessible at any IRQL.copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLengthcopies nOutBufferSize toirpSp->Parameters.DeviceIoControl.OutputBufferLengthcopies contents of lpInBuffer to SystemBuffer allocated abovecalls your driverDevice Driver perspectiveyou have one buffer, Irp->AssociatedIrp.SystemBuffer. You read input datafrom this buffer and you write output data to the same buffer, overwritingthe input data.Before calling IoCompleteRequest, you must- set IoStatus.Status to an approriate NtStatus- if IoStatus.Status == STATUS_SUCCESS set IoStatus.Information to the number of bytes you want copied from the SystemBuffer back into lpOutBuffer.I/O Manager Completion Routine perspectivelooks at IoStatus block, if IoStatus.Status = STATUS_SUCCESS, copies thenumber of bytes specified by IoStatus.Information fromIrp->AssociatedIrp.SystemBuffer into lpOutBuffercompletes the requestMETHOD_IN_DIRECTuser-mode perspectivelpInBuffer - optional, contains data that is written to the driver. Thisbuffer is used in the exact same fashion as METHOD_BUFFERED. To avoidconfusion, mentally rename this buffer to lpControlBuffer. This istypically a small, optional buffer that might contain a control structurewith useful information for the device driver. This buffer is smal and isdouble buffered.lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is read bythe driver. To avoid confusion, mentally rename this buffer tolpDataTransferBuffer. This is physically the same buffer that the devicedriver will read from. There is no double buffering. Technically, thisbuffer is still optional, but since you are using this buffering method,what would be the point???I/O Manager perspectiveIf lpInBuffer exists, allocates memory from non-paged pool and puts theaddress of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer isaccessible at any IRQL.copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLengthcopies nOutBufferSize toirpSp->Parameters.DeviceIoControl.OutputBufferLengthcopies contents of lpInBuffer to SystemBuffer allocated aboveSo far this is completely identical to METHOD_BUFFERED. Most likelylpInBuffer (mentally renamed to lpControlBuffer) is very small in size.For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL isallocated. lpOutBuffer is probed and locked into memory. Then, the userbuffer virtual addresses are checked to be sure they are readable in thecaller's access mode.The MDL is address is stored in Irp->MdlAddress.Your driver is called.Device Driver perspectiveThe device driver can read the copy of lpOutBuffer viaIrp->AssociatedIrp.SystemBuffer. Anything written by the device driver tothis buffer is lost. The I/O Manager does not copy any data back to theuser-mode buffers as it did in the completion routine for METHOD_BUFFERED.Art Baker's book is wrong in this respect (page 168, "data going from thedriver back to the caller is passed through an intermediate system-spacebuffer" and page 177, "When the IOCTL IRP is completed, the contents of thesystem buffer will be copied back into the callers original output buffer".The device driver accesses the Win32 buffer directly via Irp->MdlAddress.The driver uses whatever Mdl API's to read the buffer. Usually, thisbuffer is to be written to some mass storage media or some similaroperation. Since this is a large data transfer, assume a completionroutine is required.mark the Irp pendingqueue itreturn status pendingDevice Driver Completion Routine perspectivestandard completion routine operationsset IoStatus.Status to an approriate NtStatusIoStatus.Information is not neededcompletete the requestI/O Manager Completion Routine perspectivestandard I/O Manager completion routine operationsunmap the pagesdeallocate the Mdlcomplete the requestMETHOD_OUT_DIRECTuser-mode perspectivelpInBuffer - optional, contains data that is written to the driver. Thisbuffer is used in the exact same fashion as METHOD_BUFFERED. To avoidconfusion, mentally rename this buffer to lpControlBuffer. This istypically a small, optional buffer that might contain a control structurewith useful information for the device driver. This buffer is smal and isdouble buffered.lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is writtenby the driver and read by the wer-mode application when the request iscompleted. To avoid confusion, mentally rename this buffer tolpDataTransferBuffer. This is physically the same buffer that the devicedriver will write to. There is no double buffering. Technically, thisbuffer is still optional, but since you are using this buffering method,what would be the point???I/O Manager perspectiveIf lpInBuffer exists, allocates memory from non-paged pool and puts theaddress of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer isaccessible at any IRQL.copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLengthcopies nOutBufferSize toirpSp->Parameters.DeviceIoControl.OutputBufferLengthcopies contents of lpInBuffer to SystemBuffer allocated aboveSo far this is completely identical to METHOD_BUFFERED. Most likelylpInBuffer (mentally renamed to lpControlBuffer) is very small in size.For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL isallocated. lpOutBuffer is probed and locked into memory. Then the userbuffer's addresses are checked to make sure the caller could write to themin the caller's access mode.The MDL is address is stored in Irp->MdlAddress.Your driver is called.Device Driver perspectiveThe device driver can read the copy of lpOutBuffer viaIrp->AssociatedIrp.SystemBuffer. Anything written by the device driver tothis buffer is lost.The device driver accesses the Win32 buffer directly via Irp->MdlAddress.The driver uses whatever Mdl API's to write data to the buffer. Usually,this buffer is to be read from some mass storage media or some similaroperation. Since this is a large data transfer, assume a completionroutine is required.mark the Irp pendingqueue itreturn status pendingDevice Driver Completion Routine perspectivestandard completion routine operationsset IoStatus.Status to an approriate NtStatusIoStatus.Information is not neededcompletete the requestI/O Manager Completion Routine perspectivestandard I/O Manager completion routine operationsunmap the pagesdeallocate the Mdlcomplete the requestMETHOD_NEITHERI/O Manager perspectiveIrp->UserBuffer = lpOutputBuffer;IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = lpInputBuffer;No comments here. Don't use METHOD_DIRECT unless you know what you aredoing. Simple rule.If your IOCtl involves no data transfer buffers, then METHOD_NEITHER is thefastest path through the I/O Manager that involves an Irp.Final CommentDon't touch Irp->UserBuffer. This is a bookmark for the I/O Manager. Twomajor problems can occur. 1 - page fault at high IRQL, or 2 - you writesomething to Irp->UserBuffer and the I/O Manager overwrites you in itscompletion routine. File systems access Irp->UserBuffer, but FSD writersknow all of the above and know when it is safe to touch Irp->UserBuffer.Radu Woinaroski wrote in message <364F8F6E.2434B010@scitec.com.au>...>Hello,>>I have a kernel-mode device driver that accepts a number of IoControl>commands that use buffered data transfer (METHOD_BUFFERED).>>A user mode API provides a higher level access then the DeviceIoControl>function.>>The function is implemented like that>>BOOLSomething(> HANDLE hDevice ,> int param1,> int param2,> DWORD * pReturn,> LPOVERLAPPED pOverlapped)>{> // here a data buffer on the stack sent to asynchronous DeviceIoControl>call> int aDataIn[2];> aDataIn[0] = param1;> aDataIn[1] = param2;>> return DeviceIoControl(> hDevice,> DO_SOMETHING_IO,> aDataIn,> sizeof(int)*2,> pReturn,> sizeof(DWORD),> pOverlapped);>}>>The aDataIn buffer will not exist after DeviceIoControl returns (and>when the I/O operation terminates). I know that for buffered IO the>input data buffer is copyed by de IOManager to a nonpaged-pool area>before passing the request to driver dispatch routine (DeviceControl).>At the point of calling the dispatch routine (DeviceControl) the driver>runs in the context of the calling thread so DeviceIoControl hasn't>returned yet (?? or so I think) so aDataIn will still be valid at the>time IOManager copyes it to its buffer. So, this apears to work ok (at>least in my opinion).>>Does I/O Manager use the Input buffer from the call to the Win32>DeviceIoControl any where else after the first copy ?>>Is there any reason why this approach (passing a buffer on the stack to>a asynchronous DeviceIoControl that uses buffered I/O) wouldn't work ?>>Allocating buffers from heap and deleting them on IO completion while>managing asynchronous IO seems too much work ;-) .>>Thanks in advance for your opinions>Radu W.>>-->Radu Woinaroski>Scitec>Sydney, Australia>Radu.Woinaroski@scitec.com.au-----Subject: Re: PCI ISR problemDate: Fri, 20 Nov 1998 18:04:48 GMTFrom: jeh@cmkrnl.com (Jamie Hanrahan)Organization: Kernel Mode Systems, San Diego, CANewsgroups: comp.os.ms-windows.programmer.nt.kernel-modeReferences: 1On Thu, 19 Nov 1998 15:46:13 -0600, Eric Gardiner<eric.gardiner@natinst.com> wrote:>I'm having problems with NT4 not hooking the interrupt line indicated by>a PCI device. Here's what I'm doing:>>1) Enumerating the PCI buses on the system (using HalGetBusData) until>I find my device.>2) Once my device is found, I read the "Interrupt Line Register" in the>device's PCI config space to determine what interrupt level to pass to>HalGetInterruptVector.Whups! No. Call HalAssignSlotResources and look at the returnedCM_RESOURCE_LIST to find the vector, level, port addresses, etc., foryour device. (Then pass the returned CM_RESOURCE_LIST to ExFreePool.)See Knowledge Base article Q152044. --- Jamie Hanrahan, Kernel Mode Systems, San Diego CA (jeh@cmkrnl.com)Drivers, internals, networks, applications, and training for VMS and Windows NTNT kernel driver FAQ, links, and other information: http://www.cmkrnl.com/Please post replies, followups, questions, etc., in news, not via e-mail.-----Subject: Re: IRP cancelingDate: Mon, 23 Nov 1998 09:05:47 -0500From: Walter Oney <waltoney@oneysoft.com>Organization: Walter Oney SoftwareNewsgroups: comp.os.ms-windows.programmer.nt.kernel-modeReferences: 1Seol,Keun Seok wrote:> But, if the IRP was the CurrentIrp of the Device Object,> the Driver's Start I/O routine will try to process the IRP.> In the DDK help, the Start I/O routine MUST check the current IRP's> Cancel bit.> If set, Start I/O routine must just return.>> But I think that the IRP already completed should not be accessed.You're absolutely right. I recommend the following code in a standardStartIo routine to avoid the problem you point out:VOID StartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp) { KIRQL oldirql; IoAcquireCancelSpinLock(&oldirql); if (Irp != DeviceObject->CurrentIrp || Irp->Cancel) { IoReleaseCancelSpinLock(oldirql); return; } else { IoSetCancelRoutine(Irp, NULL); IoReleaseCancelSpinLock(oldirql); } . . . }This dovetails with a standard cancel routine:VOID CancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp) { if (DeviceObject->CurrentIrp == Irp) { IoReleaseCancelSpinLock(Irp->CancelIrql); IoStartNextPacket(DeviceObject, TRUE); } else { KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue, &Irp->Tail.Overlay.DeviceQueueEntry); IoReleaseCancelSpinLock(Irp->CancelIrql); } Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); }You need to remember that the C language specification requires thatevaluation of boolean operators short circuit when the result is known.So, if StartIo discovers that the Irp it got as an argument is not thesame as CurrentIrp, it will not attempt to evaulate Irp->Cancel.Now, as to why this works: StartIo gets called either by IoStartPacketor IoStartNextPacket. Each of them will grab the cancel spin lock andset CurrentIrp, then release the spin lock and call StartIo. If someoneshould sneak in on another CPU and cancel this very same IRP, yourcancel routine will immediately release the spin lock and callIoStartNextPacket. One of two things will then happen. IoStartNextPacketmay succeed in getting the cancel spin lock, whereupon it will nullifythe CurrentIrp pointer. If another IRP is on the queue, it will removeit from the queue, set CurrentIrp to point to this *new* IRP, releasethe spin lock, and call StartIo. [You now have two instances of StartIorunning on two different CPUs for two different IRPs, but it's not aproblem because they won't be able to interfere with each other.]Meanwhile, your original instance of StartIo gets the cancel spin lockand sees that CurrentIrp is not equal to the IRP pointer it got as anargument, so it gives up.The second way this could play out is that StartIo gets the cancel lockbefore IoStartNextPacket does. In this case, CurrentIrp is stillpointing to the IRP that's in the process of being cancelled and thatStartIo got as an argument. But this IRP hasn't been completed yet (theCPU that's running your cancel routine is spinning insideIoStartNextPacket and therefore hasn't gotten to callingIoCompleteRequest yet), so no-one will have been able to call IoFreeIrpto make your pointer invalid.People may tell you that you should be using your own queues for IRPs soyou can avoid bottlenecking the system on the global cancel spin lock.That's true enough, but doing it correctly with Plug and Play and Powermanagement things in the way is gigantically complicated. There's asample in the NT 5 beta-2 DDK called CANCEL that shows how to manageyour own queue if you don't worry about PNP and POWER. I hear tell of anupcoming MSJ article by a Microsoft developer that may solve thecomplete problem.-----The END.