diff --git a/reactos/doc/DIRS b/reactos/doc/DIRS new file mode 100644 index 00000000000..38f0f3ec735 --- /dev/null +++ b/reactos/doc/DIRS @@ -0,0 +1,22 @@ +DIRECTORIES + +system : compiled versions of the various system components and + libraries +ntoskrnl : kernel source +ntoskrnl/hal : hardware abstraction layer source +ntoskrnl/mm : memory managment subsystem source +ntoskrnl/io : IO manager subsystem source +ntoskrnl/ke : kernel source +include : win32 headers +include/internal : kernel private header files +include/ntdll : system library private header files +include/kernel32 : system library private header files +include/ddk : header files for modules +lib/ntdll : NT dll source +lib/kernel32 : kernel32 source +doc : documentation +loaders/dos : DOS based loader +loaders/boot : boot loader +services : various services (device drivers, filesystems etc) +services/dd : device drivers +services/fs : file systems diff --git a/reactos/doc/HACKING b/reactos/doc/HACKING new file mode 100644 index 00000000000..c6bab95dca2 --- /dev/null +++ b/reactos/doc/HACKING @@ -0,0 +1,130 @@ +* Introduction + +Having successfully built ReactOS and been amazed by what it does, you're +now desperate to fill in some of the omissions, this document shows you how. + +* Prerequisites + +A working knowledge of NT driver development is useful for understanding the +kernel and some of its abstractions. The NT4 ddk is available for free +download from http://www.microsoft.com/hwdev/. The Windows 98 and Windows +2000 DDKs are also available but the NT4 one is the most useful. See +Legal Stuff below however. + +There are a number of books on NT driver development, I would recommend +'Windows NT Device Driver Development' (http://www.osr.com/book/) since OSR +seem to know their stuff. There is only one book on NT filesystem +development 'Windows NT File System Internals'. Please don't buy any of +these books unless you need to, and can afford it. + +These mailing lists and newsgroups are useful for NT internals related +questions, + ntfsd@atria.com, ntdev@atria.com + (subscribe by email to majordomo@atria.com) + comp.os.???? + microsoft.public.???? + +* Style + +There is no coding style used for ReactOS, however the following guidelines +make things easier + + Include information at the top of a module about its purpose, contact + information for its programmer and any useful notes. + + Include a comment by each non-trival function describing its arguments, + purpose and any other notes. + + Update the documentation in this directory + +These guidelines are an ideal, no one manages to implement them all the +time, straightforward working code is probably just as good. + +* Debugging + +Debugging kernel-mode code is tricky, these are some snippets + + DbgPrint writes a message to the console using a printf style format + string. The DPRINT macro (defined in internal/debug.h) expands to + DbgPrint unless NDEBUG is defined, this is useful for having copious + output from a module only when a problem is being debugging. DPRINT + also prefixes the message with the file and line number to make it + easier to see where output is coming from. DbgPrint can be used at any + point including in interrupt handlers. + + There are options in ntoskrnl/hal/x86/printk.c for copying DbgPrint + output to a serial device (parallel support should also be added). This + can be useful if a lot of output is being generated. + + It should be possible to include support for debugging the kernel with + gdb over a serial line. Bochs (a shareware CPU emulator) is also useful + for debugging the kernel, I wrote some patches to allow capture of console + output from within bochs to file and for debugging a kernel running + under bochs with gdb. Contact me (welch@cwcom.net) if you're are + interested. + + If CPU reports an exception not handled by the kernel (any page fault + not part of virtual memory support or any other exception) the kernel + will display output like this and halt + + General Protection Fault Exception: 13(0) + CS:EIP xxxxxxxx:xxxxxxx + DS xxxx ES xxxx FS xxxx GS xxxxx + EAX: xxxx EBX: xxxx + .... + EDI: xxxx EFLAGS: xxxx ESP: xxxx + cr2: xxxx + Stack: xxxx xxxx xxxx ... + .... + Frames: xxxx xxxx xxxx ... + .... + + The fault type will usually be either 'General Protection' or + 'Page Fault', see your Intel manual for the more exotic types. The + 'EIP' number is the address of the faulting instruction. If the 'CS' + number is 0x20 then the exception occured in kernel mode, if it is 0x11 + then the exception occurred in user mode. 'cr2' is the address that the + faulting instruction was trying to access, if the exception was a page + fault. The number printed after 'Frames' are any addresses on the stack + that look like function addresses. + + + If the kernel detects a serious problem that it will bug check, displaying + output like this + + Bug detected (code x, param x x x x) + Frames: xxx xxxx xxxx + .... + + Again the numbers printed after 'Frames' are any addresses on the stack + that look like function addresss. Usually the kernel will also print a + message describing the problem in more detail, the bug check code isn't + very useful at the moment. + +* Contacts + + There is a mailing list for kernel development, + + ros-kernel@sid-dis.com + + The main developers use a cvs account to coordinate changes, ask + rex (rex@lvcablemodem.com) for an account if you are going to be adding + a lot of code. Smaller patches can go to the mailing list or to the + relevant developer (usually the comment at the top of a module will have + an email address). Regular snapshots are made available for download, + see the mailing list for announcements. + +* Legal stuff + + The ReactOS project is GPL'ed, please make sure any code submitted is + compatible with this. + + The NT4 ddk license agreement allows its usage for developing nt drivers + only. Legally therefore it can not be used to develop ReactOS, neither the + documentation or the sample code. I'm not a lawyer, but I doubt the + effiacy of 'shrinkwrap licenses' particularly on freely downloadable + software. The only precendent I know of, in a Scottish court, didn't + upload this type of license. + + Also the 'fair use' section of copyright law allows the 'quoting' of small + sections from copyrighted documents, e.g. Windows API or DDK documentation diff --git a/reactos/doc/INDEX b/reactos/doc/INDEX new file mode 100644 index 00000000000..2ec85492a03 --- /dev/null +++ b/reactos/doc/INDEX @@ -0,0 +1,6 @@ +HACKING: Some notes for adding code to ReactOS +DIRS: Explanation of directory layout +INTERNALS: Some notes on kernel internals +TODO: Bugs and omissions, big and little things that need to be done +NOTES: Unsorted material, some of it is redundant +BUGLIST: Known bugs, please update when you find one diff --git a/reactos/doc/INTERNALS b/reactos/doc/INTERNALS new file mode 100644 index 00000000000..e2947856dff --- /dev/null +++ b/reactos/doc/INTERNALS @@ -0,0 +1,43 @@ +A collection of articles on kernel internals, please add to this + +------------------------------------------------------------------------------ +IRQ level +------------------------------------------------------------------------------ + +IRQ level (IRQL) is a per-processor state in ReactOS used to coordinate +execution between ISRs and between threads. There are several levels + + PASSIVE_LEVEL, APC_LEVEL: The normal level for user mode and most + kernel mode code. At the moment APC_LEVEL is unused. + + DISPATCH_LEVEL: At this level all irqs are still allowed but thread + rescheduling on the current processor is disabled. This is used by + the spinlock synchronization primitive to implement its uniprocessor + semantics (multiprocessor is more complex). It is also used for some + other forms of synchronization, DPCs for example. Many APIs are + unavailable at this IRQL, usually those that might have to wait. It + is recommended that you don't spend too much time at this IRQL + otherwise system responsiveness will be reduced. + + > DISPATCH_LEVEL: Each irq is assigned a priority (which will be + greater than DISPATCH_LEVEL). At an irq's priority level that irq, + lower priority irqs and thread rescheduling are disabled. Higher + priority irqs can still run. Very few APIs are available at IRQLs + greater than DISPATCH_LEVEL. + + HIGH_LEVEL: All irqs are disabled. + +------------------------------------------------------------------------------- +DPCs +------------------------------------------------------------------------------- + +It is a design goal not to spend too much time in ISRs, for this reason +ISRs should postpone most processing till it can run at a lower IRQL. The +mechanism for this is a Delayed Procedure Call (DPC). When a DPC object is +created, it is associated with a function. The DPC object can then be inserted +in the DPC queue from an ISR. If the IRQL on return from the ISR is less than +DISPATCH_LEVEL the DPC queue will be drained, otherwise this will happen when +the IRQL level drops below DISPATCH_LEVEL or the processor becomes idle. When +the DPC queue is drained each DPC object is removed and the associated +function is called at DISPATCH_LEVEL. A DPC object can only be inserted once, +further insertions before it is removed will have no effect. diff --git a/reactos/doc/notes b/reactos/doc/notes new file mode 100644 index 00000000000..25900e924cd --- /dev/null +++ b/reactos/doc/notes @@ -0,0 +1,687 @@ +*** This file contains messages I've culled off the net as well +as previous discussions all of which have useful info on fixes +that need to be added to ReactOS. messages are between five +dashes on a line by themselves. If you implement the fix +reffered to in a message, feel free to delete it from the file. +Rex *** +----- +Yes with DPCs, KeDrainDpcQueue should go to HIGH_LEVEL because +it needs to synchronize with KeInsertDpcQueue. Also the idle thread +should run at DISPATCH_LEVEL and regularly drain the dpc queue, that +way if an irq happens and the dpc can't be executed immediately it +will be executed as soon as the processor is idle rather than +waiting for the next timer tick +----- +About the console driver, I think it might be quite useful to have a simple +way for apps to print to the screen for debugging. But when the kernel is more +stable, console handling should be moved to user level because console printing +needs 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 -0000 +From: Charles Bryant +Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode +References: 1, 2 , 3 , 4 + +In article , David C. 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 I +couldn't unload and reload a fixed version. While reading NTDDK.H I +found a suspicious constant and discovered that the Flags field in +the 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 that +this bit is set when you do 'net stop', so a driver can check it +periodically (e.g. from a timer DPC every ten seconds) and cancel all +queued IRPs if it is found to be set. + +Since this is not documented anywhere that I can find, it might be +unwise to rely on it for production code, but it is very useful for +debugging. Maybe someone with internals knowledge can comment on the +reliability of it. +----- +Subject: Re: Kernel bugs +Date: Fri, 23 Oct 1998 12:08:36 -0700 +From: rex +To: Jason Filby +References: 1 + +Jason 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 answering +this anyway. add an option to the +makefile for the module to generate a listing file with +symbol information. Then, on a boot test, note the +address that the module is loaded at, and subtract +this from the EIP value. add any offset used in the +module link specification (I dont think there currently +is one), and look for the last symbol with a lower +address offset. + +Brian, I have an idea on how to make this exception +dump information a little more useful. We should +have the load information for the load modules +in memory somewhere. Perhaps the exception +dump could check offending addresses to see if +they lie in the kernel or in a module, and if they +lie in a module the proper offset could be subtracted +and this number could be displayed seperately. If +I get a chance today, I'll make this change and send +it to ya. + +Rex. +----- +Subject: [ros-kernel] Pet peeve of the week +Resent-Date: Sun, 25 Oct 1998 11:57:40 -0600 +Resent-From: ros-kernel@sid-dis.com +Date: Sun, 25 Oct 1998 09:53:48 -0800 +From: rex +Reply-To: +To: ReactOS Kernel Forum + +Hi all, + +I guess it's about time to start another mailstorm +on the list. :) + +I have a suggestion for a change to the kernel. +It not a very big change, and I hope everyone +will agree that it makes sense. + +There is a structure used in many places in the +kernel called LARGE_INTEGER. the is also +a version called ULARGE_INTEGER, but it +is not used at all as far as I can tell. this structure +is equivalent to a long long int. You can literally +cast a pointer to a LARGE_INTEGER to a +long long int and all manipulation will work +seemlessly. My suggestion is that we replace the +use of this structure with long long ints. Even +microsoft, in their infinite wisdom, has made this +suggestion in the DDK documentation. If you're +wondering where, look at the RTL functions +that manipulate LARGE_INTEGER structs. + +Replacing LI's with long long ints will work +because they are binary compatable. All software +compiled to use LI's will manipulate long long ints +correctly and vice versa. There is one problem +with this suggestion: the LARGE_INTEGER type +is a structure containing 2 members. Any code +that accesses the structure by members will break. +I think the kernel side impact is minimal, and is +worth the change. However, the structure is used +in several of the Win32 API functions, and needs +to remain there. I think we build a conditionally +compiled version of the LARGE_INTEGER type. +In kernel mode code (the kernel proper and drivers) +the LARGE INTEGER will be the following: + +typedef long long int LARGE_INTEGER, + *PLARGE_INTEGER; +typedef unsigned long long int ULARGE_INTEGER, + *PULARGE_INTEGER; + +and in user mode code it will expand out to the +current definition (which by the way, is not +strictly correct, but can't be because it uses a +MS compiler extension). + +Brian, I would be willing to make the conversion +to those kernel modules that needed it, and of +course to the IDE driver if we want to go forward +with the change. + +Lastly, I'll mention what made me consider this. +I was fixing the timer routines, and two of the +three problems turned out to be related to LI +conversion problems. + +Rex. +----- +Subject: Re: [ros-kernel] Pet peeve of the week +Date: Thu, 29 Oct 1998 19:10:37 +0100 +From: Boudewijn +To: rex@lvcablemodem.com +References: 1 + +Hai Rex + + I think it is a good idea to wrap a makro around the member access +to large integers. +I haven't tested this, but do you think this is a good sugestion ? + +#ifdef COMPILER_LARGE_INTEGERS +#define GET_LARGE_INTEGER_HIGH_PART(LargeInteger) ( ( LargeInteger >> +32) ) +#define GET_LARGE_INTEGER_LOW_PART(LargeInteger) ( (LargeInteger & +0xFFFFFFFF) ) +#define SET_LARGE_INTEGER_HIGH_PART(LargeInteger,Signed_Long) ( +LargeInteger |= ( ((LARGE_INTEGER)Signed_Long) << 32 ) ) +#define SET_LARGE_INTEGER_LOW_PART(LargeInteger,Unsigned_Long) ( +LargeInteger |= Unsigned_Long ) +#else +#define GET_LARGE_INTEGER_HIGH_PART(LargeInteger) ( ( +LargeInteger.HighPart) ) +#define GET_LARGE_INTEGER_LOW_PART(LargeInteger) ( +(LargeInteger.LowPart) ) +#define SET_LARGE_INTEGER_HIGH_PART(LargeInteger,Signed_Long) ( +LargeInteger.HighPart= Signed_Long ) +#define SET_LARGE_INTEGER_LOW_PART(LargeInteger,Unsigned_Long) ( +LargeInteger.LowPart = Unsigned_Long ) +#endif + +Boudewijn +----- +Subject: Re: Question on "Sending buffers on the stack to asynchronous DeviceIoControl with buffered I/O" +Date: Mon, 16 Nov 1998 11:24:57 -0800 +From: "-Paul" +Organization: Microsoft Corp. +Newsgroups: microsoft.public.win32.programmer.kernel, comp.os.ms-windows.programmer.nt.kernel-mode +References: 1 + +Radu, I post the following information occassionally for questions such as +yours. I hope it helps. + +-Paul + +Here 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 byte +count + LPOVERLAPPED lpOverlapped // pointer to overlapped structure for +asynchronous operation + ); + +METHOD_BUFFERED + +user-mode perspective + +lpInBuffer - optional, contains data that is written to the driver +lpOutBuffer - optional, contains data that is read from the driver after +the call has completed + +lpInBuffer and lpOutBuffer can be two buffers or a single shared buffer. +If a shared buffer, lpInBuffer is overwritten by lpOutBuffer. + + +I/O Manager perspective + +examines nInBufferSize and nOutBufferSize. Allocates memory from non-paged +pool 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 two +bufferes. This buffer is accessible at any IRQL. + +copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength +copies nOutBufferSize to +irpSp->Parameters.DeviceIoControl.OutputBufferLength +copies contents of lpInBuffer to SystemBuffer allocated above +calls your driver + + + +Device Driver perspective + +you have one buffer, Irp->AssociatedIrp.SystemBuffer. You read input data +from this buffer and you write output data to the same buffer, overwriting +the 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 perspective + +looks at IoStatus block, if IoStatus.Status = STATUS_SUCCESS, copies the +number of bytes specified by IoStatus.Information from +Irp->AssociatedIrp.SystemBuffer into lpOutBuffer +completes the request + + + + + + +METHOD_IN_DIRECT + +user-mode perspective + +lpInBuffer - optional, contains data that is written to the driver. This +buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid +confusion, mentally rename this buffer to lpControlBuffer. This is +typically a small, optional buffer that might contain a control structure +with useful information for the device driver. This buffer is smal and is +double buffered. + +lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is read by +the driver. To avoid confusion, mentally rename this buffer to +lpDataTransferBuffer. This is physically the same buffer that the device +driver will read from. There is no double buffering. Technically, this +buffer is still optional, but since you are using this buffering method, +what would be the point??? + +I/O Manager perspective + +If lpInBuffer exists, allocates memory from non-paged pool and puts the +address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is +accessible at any IRQL. + +copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength +copies nOutBufferSize to +irpSp->Parameters.DeviceIoControl.OutputBufferLength +copies contents of lpInBuffer to SystemBuffer allocated above +So far this is completely identical to METHOD_BUFFERED. Most likely +lpInBuffer (mentally renamed to lpControlBuffer) is very small in size. + +For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is +allocated. lpOutBuffer is probed and locked into memory. Then, the user +buffer virtual addresses are checked to be sure they are readable in the +caller's access mode. + +The MDL is address is stored in Irp->MdlAddress. +Your driver is called. + + +Device Driver perspective + +The device driver can read the copy of lpOutBuffer via +Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to +this buffer is lost. The I/O Manager does not copy any data back to the +user-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 the +driver back to the caller is passed through an intermediate system-space +buffer" and page 177, "When the IOCTL IRP is completed, the contents of the +system 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, this +buffer is to be written to some mass storage media or some similar +operation. Since this is a large data transfer, assume a completion +routine is required. + +mark the Irp pending +queue it +return status pending + + + + +Device Driver Completion Routine perspective + +standard completion routine operations +set IoStatus.Status to an approriate NtStatus +IoStatus.Information is not needed +completete the request + + + + +I/O Manager Completion Routine perspective + +standard I/O Manager completion routine operations +unmap the pages +deallocate the Mdl +complete the request + + + + + +METHOD_OUT_DIRECT + +user-mode perspective + +lpInBuffer - optional, contains data that is written to the driver. This +buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid +confusion, mentally rename this buffer to lpControlBuffer. This is +typically a small, optional buffer that might contain a control structure +with useful information for the device driver. This buffer is smal and is +double buffered. + +lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is written +by the driver and read by the wer-mode application when the request is +completed. To avoid confusion, mentally rename this buffer to +lpDataTransferBuffer. This is physically the same buffer that the device +driver will write to. There is no double buffering. Technically, this +buffer is still optional, but since you are using this buffering method, +what would be the point??? + +I/O Manager perspective + +If lpInBuffer exists, allocates memory from non-paged pool and puts the +address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is +accessible at any IRQL. + +copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength +copies nOutBufferSize to +irpSp->Parameters.DeviceIoControl.OutputBufferLength +copies contents of lpInBuffer to SystemBuffer allocated above +So far this is completely identical to METHOD_BUFFERED. Most likely +lpInBuffer (mentally renamed to lpControlBuffer) is very small in size. + +For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is +allocated. lpOutBuffer is probed and locked into memory. Then the user +buffer's addresses are checked to make sure the caller could write to them +in the caller's access mode. + +The MDL is address is stored in Irp->MdlAddress. +Your driver is called. + + +Device Driver perspective + +The device driver can read the copy of lpOutBuffer via +Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to +this 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 similar +operation. Since this is a large data transfer, assume a completion +routine is required. + +mark the Irp pending +queue it +return status pending + + + + +Device Driver Completion Routine perspective + +standard completion routine operations +set IoStatus.Status to an approriate NtStatus +IoStatus.Information is not needed +completete the request + + + + +I/O Manager Completion Routine perspective + +standard I/O Manager completion routine operations +unmap the pages +deallocate the Mdl +complete the request + + + + +METHOD_NEITHER + +I/O Manager perspective + +Irp->UserBuffer = lpOutputBuffer; +IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = lpInputBuffer; + +No comments here. Don't use METHOD_DIRECT unless you know what you are +doing. Simple rule. + +If your IOCtl involves no data transfer buffers, then METHOD_NEITHER is the +fastest path through the I/O Manager that involves an Irp. + + + + +Final Comment + +Don't touch Irp->UserBuffer. This is a bookmark for the I/O Manager. Two +major problems can occur. 1 - page fault at high IRQL, or 2 - you write +something to Irp->UserBuffer and the I/O Manager overwrites you in its +completion routine. File systems access Irp->UserBuffer, but FSD writers +know 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 +> +>BOOL +Something( +> 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 aDataI +n 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 problem +Date: Fri, 20 Nov 1998 18:04:48 GMT +From: jeh@cmkrnl.com (Jamie Hanrahan) +Organization: Kernel Mode Systems, San Diego, CA +Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode +References: 1 + +On Thu, 19 Nov 1998 15:46:13 -0600, Eric Gardiner + 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 returned +CM_RESOURCE_LIST to find the vector, level, port addresses, etc., for +your 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 NT +NT 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 canceling +Date: Mon, 23 Nov 1998 09:05:47 -0500 +From: Walter Oney +Organization: Walter Oney Software +Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode +References: 1 + +Seol,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 standard +StartIo 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 that +evaluation of boolean operators short circuit when the result is known. +So, if StartIo discovers that the Irp it got as an argument is not the +same as CurrentIrp, it will not attempt to evaulate Irp->Cancel. + +Now, as to why this works: StartIo gets called either by IoStartPacket +or IoStartNextPacket. Each of them will grab the cancel spin lock and +set CurrentIrp, then release the spin lock and call StartIo. If someone +should sneak in on another CPU and cancel this very same IRP, your +cancel routine will immediately release the spin lock and call +IoStartNextPacket. One of two things will then happen. IoStartNextPacket +may succeed in getting the cancel spin lock, whereupon it will nullify +the CurrentIrp pointer. If another IRP is on the queue, it will remove +it from the queue, set CurrentIrp to point to this *new* IRP, release +the spin lock, and call StartIo. [You now have two instances of StartIo +running on two different CPUs for two different IRPs, but it's not a +problem because they won't be able to interfere with each other.] +Meanwhile, your original instance of StartIo gets the cancel spin lock +and sees that CurrentIrp is not equal to the IRP pointer it got as an +argument, so it gives up. + +The second way this could play out is that StartIo gets the cancel lock +before IoStartNextPacket does. In this case, CurrentIrp is still +pointing to the IRP that's in the process of being cancelled and that +StartIo got as an argument. But this IRP hasn't been completed yet (the +CPU that's running your cancel routine is spinning inside +IoStartNextPacket and therefore hasn't gotten to calling +IoCompleteRequest yet), so no-one will have been able to call IoFreeIrp +to make your pointer invalid. + +People may tell you that you should be using your own queues for IRPs so +you can avoid bottlenecking the system on the global cancel spin lock. +That's true enough, but doing it correctly with Plug and Play and Power +management things in the way is gigantically complicated. There's a +sample in the NT 5 beta-2 DDK called CANCEL that shows how to manage +your own queue if you don't worry about PNP and POWER. I hear tell of an +upcoming MSJ article by a Microsoft developer that may solve the +complete problem. +----- +Subject: ANNOUNCE: ALINK v1.5 +Date: 16 Nov 1998 16:36:05 GMT +From: anthony_w@my-dejanews.com +Organization: Deja News - The Leader in Internet Discussion +Newsgroups: comp.os.ms-windows.programmer.win32, comp.lang.asm.x86, comp.os.msdos.programmer + +ALINK is a freeware linker, creating MSDOS COM and EXE files and Win32 PE EXE +and DLL files from OMF format OBJ and LIB files, win32-COFF format OBJ files, +and win32 RES files. + +NEW for version 1.5: + +Win32 COFF object file support. + +Download it now from my home page. + +Anthony +-- +anthony_w@geocities.com +http://www.geocities.com/SiliconValley/Network/4311/index.html + +-----------== Posted via Deja News, The Discussion Network ==---------- +http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own +----- +