Added .o -> .sys rule to simplify driver makefiles
[reactos.git] / reactos / doc / notes
1 *** This file contains messages I've culled off the net as well
2 as previous discussions all of which have useful info on fixes
3 that need to be added to ReactOS. messages are between five
4 dashes on a line by themselves. If you implement the fix
5 reffered to in a message, feel free to delete it from the file.
6 Rex ***
7 -----
8 Subject: [ros-kernel] Inside the Boot Process
9 Date: Mon, 22 Mar 1999 22:05:47 +0100
10 From: Emanuele Aliberti <ea@iol.it>
11
12 For those working on the boot loader: in WinNt Magazine november 1998
13 issue (http://www.winntmag.com/) there is a detailed description, by
14 Mark Russinovich, of the rĂ´le the MBR, NTLDR, boot.ini, ntdetect.com...
15 play in the boot process ("Inside the Boot Process, Part 1").
16 -----
17 Yes with DPCs, KeDrainDpcQueue should go to HIGH_LEVEL because
18 it needs to synchronize with KeInsertDpcQueue. Also the idle thread
19 should run at DISPATCH_LEVEL and regularly drain the dpc queue, that
20 way if an irq happens and the dpc can't be executed immediately it
21 will be executed as soon as the processor is idle rather than
22 waiting for the next timer tick
23 -----
24 About the console driver, I think it might be quite useful to have a simple
25 way for apps to print to the screen for debugging. But when the kernel is more
26 stable, console handling should be moved to user level because console printing
27 needs to know about windows and so on which can only be done at user level.
28 -----
29 Subject: Re: IMSAMP-how to avoid rebooting?
30 Date: 9 Nov 1998 00:40:32 -0000
31 From: Charles Bryant <n51190709.ch@chch.demon.co.uk>
32 Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
33 References: 1, 2 , 3 , 4
34
35 In article <un264wzle.fsf@xxx.yyy.zzz>, David C. <qqqq@xxx.yyy.zzz> wrote:
36 >The reason it won't unload when something is bound to it is the same
37 >reason you can't unload any other driver that has an open client. If
38 >you install any driver, and have a user program (or another driver) open
39 >a handle to it, and then give the "net stop" command to unload it,
40 >you'll find that the unload will be delayed until the user program
41 >closes its handle.
42
43 When developing a driver I found this to be a considerable nuisance.
44 Frequently a bug would leave an IRP stuck in the driver and I
45 couldn't unload and reload a fixed version. While reading NTDDK.H I
46 found a suspicious constant and discovered that the Flags field in
47 the device (the one which you OR in DO_BUFFERED_IO or DO_DIRECT_IO)
48 has a bit called DO_UNLOAD_PENDING. By experiment I confirmed that
49 this bit is set when you do 'net stop', so a driver can check it
50 periodically (e.g. from a timer DPC every ten seconds) and cancel all
51 queued IRPs if it is found to be set.
52
53 Since this is not documented anywhere that I can find, it might be
54 unwise to rely on it for production code, but it is very useful for
55 debugging. Maybe someone with internals knowledge can comment on the
56 reliability of it.
57 -----
58 Subject: Re: Kernel bugs
59 Date: Fri, 23 Oct 1998 12:08:36 -0700
60 From: rex <rex@lvcablemodem.com>
61 To: Jason Filby <jasonfilby@yahoo.com>
62 References: 1
63
64 Jason Filby wrote:
65
66 > Hi,
67 >
68 > Ok -- here's most of what I get when I press a key:
69 >
70 > Page fault detected at address 1fd4 with eip c042f794
71 > Recursive page fault detected
72 > Exception 14(2)
73 > CS:EIP 20:c042f794
74 >
75 > Rex -- do you know of anyway to find out which function in what file
76 > is causing the exception? I know that for problems in the kernel, you
77 > just look in the ntoskrnl\kernel.sym file and find the EIP value which
78 > matches the one given in the exception debug text. But what about
79 > modules? How can we track exceptions that occur in functions in modules?
80 >
81
82 I know this is a little belated, but I thought I'd take astab at answering
83 this anyway. add an option to the
84 makefile for the module to generate a listing file with
85 symbol information. Then, on a boot test, note the
86 address that the module is loaded at, and subtract
87 this from the EIP value. add any offset used in the
88 module link specification (I dont think there currently
89 is one), and look for the last symbol with a lower
90 address offset.
91
92 Brian, I have an idea on how to make this exception
93 dump information a little more useful. We should
94 have the load information for the load modules
95 in memory somewhere. Perhaps the exception
96 dump could check offending addresses to see if
97 they lie in the kernel or in a module, and if they
98 lie in a module the proper offset could be subtracted
99 and this number could be displayed seperately. If
100 I get a chance today, I'll make this change and send
101 it to ya.
102
103 Rex.
104 -----
105 Subject: [ros-kernel] Pet peeve of the week
106 Resent-Date: Sun, 25 Oct 1998 11:57:40 -0600
107 Resent-From: ros-kernel@sid-dis.com
108 Date: Sun, 25 Oct 1998 09:53:48 -0800
109 From: rex <rex@lvcablemodem.com>
110 Reply-To: <ros-kernel@sid-dis.com>
111 To: ReactOS Kernel Forum <ros-kernel@sid-dis.com>
112
113 Hi all,
114
115 I guess it's about time to start another mailstorm
116 on the list. :)
117
118 I have a suggestion for a change to the kernel.
119 It not a very big change, and I hope everyone
120 will agree that it makes sense.
121
122 There is a structure used in many places in the
123 kernel called LARGE_INTEGER. the is also
124 a version called ULARGE_INTEGER, but it
125 is not used at all as far as I can tell. this structure
126 is equivalent to a long long int. You can literally
127 cast a pointer to a LARGE_INTEGER to a
128 long long int and all manipulation will work
129 seemlessly. My suggestion is that we replace the
130 use of this structure with long long ints. Even
131 microsoft, in their infinite wisdom, has made this
132 suggestion in the DDK documentation. If you're
133 wondering where, look at the RTL functions
134 that manipulate LARGE_INTEGER structs.
135
136 Replacing LI's with long long ints will work
137 because they are binary compatable. All software
138 compiled to use LI's will manipulate long long ints
139 correctly and vice versa. There is one problem
140 with this suggestion: the LARGE_INTEGER type
141 is a structure containing 2 members. Any code
142 that accesses the structure by members will break.
143 I think the kernel side impact is minimal, and is
144 worth the change. However, the structure is used
145 in several of the Win32 API functions, and needs
146 to remain there. I think we build a conditionally
147 compiled version of the LARGE_INTEGER type.
148 In kernel mode code (the kernel proper and drivers)
149 the LARGE INTEGER will be the following:
150
151 typedef long long int LARGE_INTEGER,
152 *PLARGE_INTEGER;
153 typedef unsigned long long int ULARGE_INTEGER,
154 *PULARGE_INTEGER;
155
156 and in user mode code it will expand out to the
157 current definition (which by the way, is not
158 strictly correct, but can't be because it uses a
159 MS compiler extension).
160
161 Brian, I would be willing to make the conversion
162 to those kernel modules that needed it, and of
163 course to the IDE driver if we want to go forward
164 with the change.
165
166 Lastly, I'll mention what made me consider this.
167 I was fixing the timer routines, and two of the
168 three problems turned out to be related to LI
169 conversion problems.
170
171 Rex.
172 -----
173 Subject: Re: [ros-kernel] Pet peeve of the week
174 Date: Thu, 29 Oct 1998 19:10:37 +0100
175 From: Boudewijn <ariadne@xs4all.nl>
176 To: rex@lvcablemodem.com
177 References: 1
178
179 Hai Rex
180
181 I think it is a good idea to wrap a makro around the member access
182 to large integers.
183 I haven't tested this, but do you think this is a good sugestion ?
184
185 #ifdef COMPILER_LARGE_INTEGERS
186 #define GET_LARGE_INTEGER_HIGH_PART(LargeInteger) ( ( LargeInteger >>
187 32) )
188 #define GET_LARGE_INTEGER_LOW_PART(LargeInteger) ( (LargeInteger &
189 0xFFFFFFFF) )
190 #define SET_LARGE_INTEGER_HIGH_PART(LargeInteger,Signed_Long) (
191 LargeInteger |= ( ((LARGE_INTEGER)Signed_Long) << 32 ) )
192 #define SET_LARGE_INTEGER_LOW_PART(LargeInteger,Unsigned_Long) (
193 LargeInteger |= Unsigned_Long )
194 #else
195 #define GET_LARGE_INTEGER_HIGH_PART(LargeInteger) ( (
196 LargeInteger.HighPart) )
197 #define GET_LARGE_INTEGER_LOW_PART(LargeInteger) (
198 (LargeInteger.LowPart) )
199 #define SET_LARGE_INTEGER_HIGH_PART(LargeInteger,Signed_Long) (
200 LargeInteger.HighPart= Signed_Long )
201 #define SET_LARGE_INTEGER_LOW_PART(LargeInteger,Unsigned_Long) (
202 LargeInteger.LowPart = Unsigned_Long )
203 #endif
204
205 Boudewijn
206 -----
207 Subject: Re: Question on "Sending buffers on the stack to asynchronous DeviceIoControl with buffered I/O"
208 Date: Mon, 16 Nov 1998 11:24:57 -0800
209 From: "-Paul" <paulsan@microsoftSPAM.com>
210 Organization: Microsoft Corp.
211 Newsgroups: microsoft.public.win32.programmer.kernel, comp.os.ms-windows.programmer.nt.kernel-mode
212 References: 1
213
214 Radu, I post the following information occassionally for questions such as
215 yours. I hope it helps.
216
217 -Paul
218
219 Here is an explanation of buffers and DeviceIoControl.
220
221 First, here are the parameters,
222
223 BOOL DeviceIoControl(
224 HANDLE hDevice, // handle to device of interest
225 DWORD dwIoControlCode, // control code of operation to perform
226 LPVOID lpInBuffer, // pointer to buffer to supply input data
227 DWORD nInBufferSize, // size of input buffer
228 LPVOID lpOutBuffer, // pointer to buffer to receive output data
229 DWORD nOutBufferSize, // size of output buffer
230 LPDWORD lpBytesReturned, // pointer to variable to receive output byte
231 count
232 LPOVERLAPPED lpOverlapped // pointer to overlapped structure for
233 asynchronous operation
234 );
235
236 METHOD_BUFFERED
237
238 user-mode perspective
239
240 lpInBuffer - optional, contains data that is written to the driver
241 lpOutBuffer - optional, contains data that is read from the driver after
242 the call has completed
243
244 lpInBuffer and lpOutBuffer can be two buffers or a single shared buffer.
245 If a shared buffer, lpInBuffer is overwritten by lpOutBuffer.
246
247
248 I/O Manager perspective
249
250 examines nInBufferSize and nOutBufferSize. Allocates memory from non-paged
251 pool and puts the address of this pool in Irp->AssociatedIrp.SystemBuffer.
252 The size of this buffer is equal to the size of the larger of the two
253 bufferes. This buffer is accessible at any IRQL.
254
255 copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
256 copies nOutBufferSize to
257 irpSp->Parameters.DeviceIoControl.OutputBufferLength
258 copies contents of lpInBuffer to SystemBuffer allocated above
259 calls your driver
260
261
262
263 Device Driver perspective
264
265 you have one buffer, Irp->AssociatedIrp.SystemBuffer. You read input data
266 from this buffer and you write output data to the same buffer, overwriting
267 the input data.
268
269 Before calling IoCompleteRequest, you must
270 - set IoStatus.Status to an approriate NtStatus
271 - if IoStatus.Status == STATUS_SUCCESS
272 set IoStatus.Information to the
273 number of bytes you want copied
274 from the SystemBuffer back into
275 lpOutBuffer.
276
277
278 I/O Manager Completion Routine perspective
279
280 looks at IoStatus block, if IoStatus.Status = STATUS_SUCCESS, copies the
281 number of bytes specified by IoStatus.Information from
282 Irp->AssociatedIrp.SystemBuffer into lpOutBuffer
283 completes the request
284
285
286
287
288
289
290 METHOD_IN_DIRECT
291
292 user-mode perspective
293
294 lpInBuffer - optional, contains data that is written to the driver. This
295 buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid
296 confusion, mentally rename this buffer to lpControlBuffer. This is
297 typically a small, optional buffer that might contain a control structure
298 with useful information for the device driver. This buffer is smal and is
299 double buffered.
300
301 lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is read by
302 the driver. To avoid confusion, mentally rename this buffer to
303 lpDataTransferBuffer. This is physically the same buffer that the device
304 driver will read from. There is no double buffering. Technically, this
305 buffer is still optional, but since you are using this buffering method,
306 what would be the point???
307
308 I/O Manager perspective
309
310 If lpInBuffer exists, allocates memory from non-paged pool and puts the
311 address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is
312 accessible at any IRQL.
313
314 copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
315 copies nOutBufferSize to
316 irpSp->Parameters.DeviceIoControl.OutputBufferLength
317 copies contents of lpInBuffer to SystemBuffer allocated above
318 So far this is completely identical to METHOD_BUFFERED. Most likely
319 lpInBuffer (mentally renamed to lpControlBuffer) is very small in size.
320
321 For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is
322 allocated. lpOutBuffer is probed and locked into memory. Then, the user
323 buffer virtual addresses are checked to be sure they are readable in the
324 caller's access mode.
325
326 The MDL is address is stored in Irp->MdlAddress.
327 Your driver is called.
328
329
330 Device Driver perspective
331
332 The device driver can read the copy of lpOutBuffer via
333 Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to
334 this buffer is lost. The I/O Manager does not copy any data back to the
335 user-mode buffers as it did in the completion routine for METHOD_BUFFERED.
336 Art Baker's book is wrong in this respect (page 168, "data going from the
337 driver back to the caller is passed through an intermediate system-space
338 buffer" and page 177, "When the IOCTL IRP is completed, the contents of the
339 system buffer will be copied back into the callers original output buffer".
340
341 The device driver accesses the Win32 buffer directly via Irp->MdlAddress.
342 The driver uses whatever Mdl API's to read the buffer. Usually, this
343 buffer is to be written to some mass storage media or some similar
344 operation. Since this is a large data transfer, assume a completion
345 routine is required.
346
347 mark the Irp pending
348 queue it
349 return status pending
350
351
352
353
354 Device Driver Completion Routine perspective
355
356 standard completion routine operations
357 set IoStatus.Status to an approriate NtStatus
358 IoStatus.Information is not needed
359 completete the request
360
361
362
363
364 I/O Manager Completion Routine perspective
365
366 standard I/O Manager completion routine operations
367 unmap the pages
368 deallocate the Mdl
369 complete the request
370
371
372
373
374
375 METHOD_OUT_DIRECT
376
377 user-mode perspective
378
379 lpInBuffer - optional, contains data that is written to the driver. This
380 buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid
381 confusion, mentally rename this buffer to lpControlBuffer. This is
382 typically a small, optional buffer that might contain a control structure
383 with useful information for the device driver. This buffer is smal and is
384 double buffered.
385
386 lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is written
387 by the driver and read by the wer-mode application when the request is
388 completed. To avoid confusion, mentally rename this buffer to
389 lpDataTransferBuffer. This is physically the same buffer that the device
390 driver will write to. There is no double buffering. Technically, this
391 buffer is still optional, but since you are using this buffering method,
392 what would be the point???
393
394 I/O Manager perspective
395
396 If lpInBuffer exists, allocates memory from non-paged pool and puts the
397 address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is
398 accessible at any IRQL.
399
400 copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
401 copies nOutBufferSize to
402 irpSp->Parameters.DeviceIoControl.OutputBufferLength
403 copies contents of lpInBuffer to SystemBuffer allocated above
404 So far this is completely identical to METHOD_BUFFERED. Most likely
405 lpInBuffer (mentally renamed to lpControlBuffer) is very small in size.
406
407 For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is
408 allocated. lpOutBuffer is probed and locked into memory. Then the user
409 buffer's addresses are checked to make sure the caller could write to them
410 in the caller's access mode.
411
412 The MDL is address is stored in Irp->MdlAddress.
413 Your driver is called.
414
415
416 Device Driver perspective
417
418 The device driver can read the copy of lpOutBuffer via
419 Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to
420 this buffer is lost.
421
422 The device driver accesses the Win32 buffer directly via Irp->MdlAddress.
423 The driver uses whatever Mdl API's to write data to the buffer. Usually,
424 this buffer is to be read from some mass storage media or some similar
425 operation. Since this is a large data transfer, assume a completion
426 routine is required.
427
428 mark the Irp pending
429 queue it
430 return status pending
431
432
433
434
435 Device Driver Completion Routine perspective
436
437 standard completion routine operations
438 set IoStatus.Status to an approriate NtStatus
439 IoStatus.Information is not needed
440 completete the request
441
442
443
444
445 I/O Manager Completion Routine perspective
446
447 standard I/O Manager completion routine operations
448 unmap the pages
449 deallocate the Mdl
450 complete the request
451
452
453
454
455 METHOD_NEITHER
456
457 I/O Manager perspective
458
459 Irp->UserBuffer = lpOutputBuffer;
460 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = lpInputBuffer;
461
462 No comments here. Don't use METHOD_DIRECT unless you know what you are
463 doing. Simple rule.
464
465 If your IOCtl involves no data transfer buffers, then METHOD_NEITHER is the
466 fastest path through the I/O Manager that involves an Irp.
467
468
469
470
471 Final Comment
472
473 Don't touch Irp->UserBuffer. This is a bookmark for the I/O Manager. Two
474 major problems can occur. 1 - page fault at high IRQL, or 2 - you write
475 something to Irp->UserBuffer and the I/O Manager overwrites you in its
476 completion routine. File systems access Irp->UserBuffer, but FSD writers
477 know all of the above and know when it is safe to touch Irp->UserBuffer.
478
479
480
481 Radu Woinaroski wrote in message <364F8F6E.2434B010@scitec.com.au>...
482 >Hello,
483 >
484 >I have a kernel-mode device driver that accepts a number of IoControl
485 >commands that use buffered data transfer (METHOD_BUFFERED).
486 >
487 >A user mode API provides a higher level access then the DeviceIoControl
488 >function.
489 >
490 >The function is implemented like that
491 >
492 >BOOL
493 Something(
494 > HANDLE hDevice ,
495 > int param1,
496 > int param2,
497 > DWORD * pReturn,
498 > LPOVERLAPPED pOverlapped)
499 >{
500 > // here a data buffer on the stack sent to asynchronous DeviceIoControl
501 >call
502 > int aDataIn[2];
503 > aDataIn[0] = param1;
504 > aDataIn[1] = param2;
505 >
506 > return DeviceIoControl(
507 > hDevice,
508 > DO_SOMETHING_IO,
509 > aDataIn,
510 > sizeof(int)*2,
511 > pReturn,
512 > sizeof(DWORD),
513 > pOverlapped);
514 >}
515 >
516 >The aDataIn buffer will not exist after DeviceIoControl returns (and
517 >when the I/O operation terminates). I know that for buffered IO the
518 >input data buffer is copyed by de IOManager to a nonpaged-pool area
519 >before passing the request to driver dispatch routine (DeviceControl).
520 >At the point of calling the dispatch routine (DeviceControl) the driver
521 >runs in the context of the calling thread so DeviceIoControl hasn't
522 >returned yet (?? or so I think) so aDataI
523 n will still be valid at the
524 >time IOManager copyes it to its buffer. So, this apears to work ok (at
525 >least in my opinion).
526 >
527 >Does I/O Manager use the Input buffer from the call to the Win32
528 >DeviceIoControl any where else after the first copy ?
529 >
530 >Is there any reason why this approach (passing a buffer on the stack to
531 >a asynchronous DeviceIoControl that uses buffered I/O) wouldn't work ?
532 >
533 >Allocating buffers from heap and deleting them on IO completion while
534 >managing asynchronous IO seems too much work ;-) .
535 >
536 >Thanks in advance for your opinions
537 >Radu W.
538 >
539 >--
540 >Radu Woinaroski
541 >Scitec
542 >Sydney, Australia
543 >Radu.Woinaroski@scitec.com.au
544 -----
545 Subject: Re: PCI ISR problem
546 Date: Fri, 20 Nov 1998 18:04:48 GMT
547 From: jeh@cmkrnl.com (Jamie Hanrahan)
548 Organization: Kernel Mode Systems, San Diego, CA
549 Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
550 References: 1
551
552 On Thu, 19 Nov 1998 15:46:13 -0600, Eric Gardiner
553 <eric.gardiner@natinst.com> wrote:
554
555 >I'm having problems with NT4 not hooking the interrupt line indicated by
556 >a PCI device. Here's what I'm doing:
557 >
558 >1) Enumerating the PCI buses on the system (using HalGetBusData) until
559 >I find my device.
560 >2) Once my device is found, I read the "Interrupt Line Register" in the
561 >device's PCI config space to determine what interrupt level to pass to
562 >HalGetInterruptVector.
563
564 Whups! No. Call HalAssignSlotResources and look at the returned
565 CM_RESOURCE_LIST to find the vector, level, port addresses, etc., for
566 your device. (Then pass the returned CM_RESOURCE_LIST to ExFreePool.)
567
568
569 See Knowledge Base article Q152044.
570
571 --- Jamie Hanrahan, Kernel Mode Systems, San Diego CA (jeh@cmkrnl.com)
572 Drivers, internals, networks, applications, and training for VMS and Windows NT
573 NT kernel driver FAQ, links, and other information: http://www.cmkrnl.com/
574
575 Please post replies, followups, questions, etc., in news, not via e-mail.
576 -----
577 Subject: Re: IRP canceling
578 Date: Mon, 23 Nov 1998 09:05:47 -0500
579 From: Walter Oney <waltoney@oneysoft.com>
580 Organization: Walter Oney Software
581 Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
582 References: 1
583
584 Seol,Keun Seok wrote:
585 > But, if the IRP was the CurrentIrp of the Device Object,
586 > the Driver's Start I/O routine will try to process the IRP.
587 > In the DDK help, the Start I/O routine MUST check the current IRP's
588 > Cancel bit.
589 > If set, Start I/O routine must just return.
590 >
591 > But I think that the IRP already completed should not be accessed.
592
593 You're absolutely right. I recommend the following code in a standard
594 StartIo routine to avoid the problem you point out:
595
596 VOID StartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
597 {
598 KIRQL oldirql;
599 IoAcquireCancelSpinLock(&oldirql);
600 if (Irp != DeviceObject->CurrentIrp || Irp->Cancel)
601 {
602 IoReleaseCancelSpinLock(oldirql);
603 return;
604 }
605 else
606 {
607 IoSetCancelRoutine(Irp, NULL);
608 IoReleaseCancelSpinLock(oldirql);
609 }
610 . . .
611 }
612
613 This dovetails with a standard cancel routine:
614
615 VOID CancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp)
616 {
617 if (DeviceObject->CurrentIrp == Irp)
618 {
619 IoReleaseCancelSpinLock(Irp->CancelIrql);
620 IoStartNextPacket(DeviceObject, TRUE);
621 }
622 else
623 {
624 KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue,
625 &Irp->Tail.Overlay.DeviceQueueEntry);
626 IoReleaseCancelSpinLock(Irp->CancelIrql);
627 }
628 Irp->IoStatus.Status = STATUS_CANCELLED;
629 Irp->IoStatus.Information = 0;
630 IoCompleteRequest(Irp, IO_NO_INCREMENT);
631 }
632
633 You need to remember that the C language specification requires that
634 evaluation of boolean operators short circuit when the result is known.
635 So, if StartIo discovers that the Irp it got as an argument is not the
636 same as CurrentIrp, it will not attempt to evaulate Irp->Cancel.
637
638 Now, as to why this works: StartIo gets called either by IoStartPacket
639 or IoStartNextPacket. Each of them will grab the cancel spin lock and
640 set CurrentIrp, then release the spin lock and call StartIo. If someone
641 should sneak in on another CPU and cancel this very same IRP, your
642 cancel routine will immediately release the spin lock and call
643 IoStartNextPacket. One of two things will then happen. IoStartNextPacket
644 may succeed in getting the cancel spin lock, whereupon it will nullify
645 the CurrentIrp pointer. If another IRP is on the queue, it will remove
646 it from the queue, set CurrentIrp to point to this *new* IRP, release
647 the spin lock, and call StartIo. [You now have two instances of StartIo
648 running on two different CPUs for two different IRPs, but it's not a
649 problem because they won't be able to interfere with each other.]
650 Meanwhile, your original instance of StartIo gets the cancel spin lock
651 and sees that CurrentIrp is not equal to the IRP pointer it got as an
652 argument, so it gives up.
653
654 The second way this could play out is that StartIo gets the cancel lock
655 before IoStartNextPacket does. In this case, CurrentIrp is still
656 pointing to the IRP that's in the process of being cancelled and that
657 StartIo got as an argument. But this IRP hasn't been completed yet (the
658 CPU that's running your cancel routine is spinning inside
659 IoStartNextPacket and therefore hasn't gotten to calling
660 IoCompleteRequest yet), so no-one will have been able to call IoFreeIrp
661 to make your pointer invalid.
662
663 People may tell you that you should be using your own queues for IRPs so
664 you can avoid bottlenecking the system on the global cancel spin lock.
665 That's true enough, but doing it correctly with Plug and Play and Power
666 management things in the way is gigantically complicated. There's a
667 sample in the NT 5 beta-2 DDK called CANCEL that shows how to manage
668 your own queue if you don't worry about PNP and POWER. I hear tell of an
669 upcoming MSJ article by a Microsoft developer that may solve the
670 complete problem.
671 -----
672 Subject: ANNOUNCE: ALINK v1.5
673 Date: 16 Nov 1998 16:36:05 GMT
674 From: anthony_w@my-dejanews.com
675 Organization: Deja News - The Leader in Internet Discussion
676 Newsgroups: comp.os.ms-windows.programmer.win32, comp.lang.asm.x86, comp.os.msdos.programmer
677
678 ALINK is a freeware linker, creating MSDOS COM and EXE files and Win32 PE EXE
679 and DLL files from OMF format OBJ and LIB files, win32-COFF format OBJ files,
680 and win32 RES files.
681
682 NEW for version 1.5:
683
684 Win32 COFF object file support.
685
686 Download it now from my home page.
687
688 Anthony
689 --
690 anthony_w@geocities.com
691 http://www.geocities.com/SiliconValley/Network/4311/index.html
692
693 -----------== Posted via Deja News, The Discussion Network ==----------
694 http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
695 -----
696