Continue of MSVC-compiling changes....
[reactos.git] / reactos / ntoskrnl / cc / copy.c
1 /* $Id: copy.c,v 1.20 2003/12/30 18:52:03 fireball Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/cc/copy.c
6 * PURPOSE: Implements cache managers copy interface
7 * PROGRAMMER: Hartmut Birr
8 * UPDATE HISTORY:
9 * Created 05.10.2001
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <ddk/ntifs.h>
16 #include <internal/mm.h>
17 #include <internal/cc.h>
18 #include <internal/pool.h>
19 #include <internal/io.h>
20 #include <ntos/minmax.h>
21
22 #define NDEBUG
23 #include <internal/debug.h>
24
25 /* GLOBALS *******************************************************************/
26
27 #define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
28
29 #if defined(__GNUC__)
30 static PHYSICAL_ADDRESS CcZeroPage = (PHYSICAL_ADDRESS)0LL;
31 #else
32 static PHYSICAL_ADDRESS CcZeroPage = { 0 };
33 #endif
34
35 /* FUNCTIONS *****************************************************************/
36
37 VOID
38 CcInitCacheZeroPage(VOID)
39 {
40 NTSTATUS Status;
41
42 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &CcZeroPage);
43 if (!NT_SUCCESS(Status))
44 {
45 DbgPrint("Can't allocate CcZeroPage.\n");
46 KEBUGCHECK(0);
47 }
48 Status = MiZeroPage(CcZeroPage);
49 if (!NT_SUCCESS(Status))
50 {
51 DbgPrint("Can't zero out CcZeroPage.\n");
52 KEBUGCHECK(0);
53 }
54 }
55
56 NTSTATUS
57 ReadCacheSegmentChain(PBCB Bcb, ULONG ReadOffset, ULONG Length,
58 PVOID Buffer)
59 {
60 PCACHE_SEGMENT head;
61 PCACHE_SEGMENT current;
62 PCACHE_SEGMENT previous;
63 IO_STATUS_BLOCK Iosb;
64 LARGE_INTEGER SegOffset;
65 NTSTATUS Status;
66 ULONG TempLength;
67 KEVENT Event;
68
69 Status = CcRosGetCacheSegmentChain(Bcb, ReadOffset, Length, &head);
70 if (!NT_SUCCESS(Status))
71 {
72 return(Status);
73 }
74 current = head;
75 while (current != NULL)
76 {
77 /*
78 * If the current segment is valid then copy it into the
79 * user buffer.
80 */
81 if (current->Valid)
82 {
83 TempLength = min(Bcb->CacheSegmentSize, Length);
84 memcpy(Buffer, current->BaseAddress, TempLength);
85 #if defined(__GNUC__)
86 Buffer += TempLength;
87 #else
88 {
89 char* pTemp = Buffer;
90 pTemp += TempLength;
91 Buffer = pTemp;
92 }
93 #endif
94 Length = Length - TempLength;
95 previous = current;
96 current = current->NextInChain;
97 CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
98 }
99 /*
100 * Otherwise read in as much as we can.
101 */
102 else
103 {
104 PCACHE_SEGMENT current2;
105 ULONG current_size;
106 PMDL Mdl;
107 ULONG i;
108 ULONG offset;
109
110 /*
111 * Count the maximum number of bytes we could read starting
112 * from the current segment.
113 */
114 current2 = current;
115 current_size = 0;
116 while (current2 != NULL && !current2->Valid)
117 {
118 current2 = current2->NextInChain;
119 current_size += Bcb->CacheSegmentSize;
120 }
121
122 /*
123 * Create an MDL which contains all their pages.
124 */
125 Mdl = MmCreateMdl(NULL, NULL, current_size);
126 Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
127 current2 = current;
128 offset = 0;
129 while (current2 != NULL && !current2->Valid)
130 {
131 for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE); i++)
132 {
133 PVOID address;
134 PHYSICAL_ADDRESS page;
135 address = (char*)current2->BaseAddress + (i * PAGE_SIZE);
136 page = MmGetPhysicalAddressForProcess(NULL, address);
137 ((PULONG)(Mdl + 1))[offset] = page.u.LowPart;
138 offset++;
139 }
140 current2 = current2->NextInChain;
141 }
142
143 /*
144 * Read in the information.
145 */
146 SegOffset.QuadPart = current->FileOffset;
147 KeInitializeEvent(&Event, NotificationEvent, FALSE);
148 Status = IoPageRead(Bcb->FileObject,
149 Mdl,
150 &SegOffset,
151 &Event,
152 &Iosb);
153 if (Status == STATUS_PENDING)
154 {
155 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
156 Status = Iosb.Status;
157 }
158 if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
159 {
160 while (current != NULL)
161 {
162 previous = current;
163 current = current->NextInChain;
164 CcRosReleaseCacheSegment(Bcb, previous, FALSE, FALSE, FALSE);
165 }
166 return(Status);
167 }
168 while (current != NULL && !current->Valid)
169 {
170 previous = current;
171 current = current->NextInChain;
172 TempLength = min(Bcb->CacheSegmentSize, Length);
173 memcpy(Buffer, previous->BaseAddress, TempLength);
174 #if defined(__GNUC__)
175 Buffer += TempLength;
176 #else
177 {
178 char* pTemp = Buffer;
179 pTemp += TempLength;
180 Buffer = pTemp;
181 }
182 #endif
183 Length = Length - TempLength;
184 CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
185 }
186 }
187 }
188 return(STATUS_SUCCESS);
189 }
190
191 NTSTATUS
192 ReadCacheSegment(PCACHE_SEGMENT CacheSeg)
193 {
194 ULONG Size;
195 PMDL Mdl;
196 NTSTATUS Status;
197 LARGE_INTEGER SegOffset;
198 IO_STATUS_BLOCK IoStatus;
199 KEVENT Event;
200
201 SegOffset.QuadPart = CacheSeg->FileOffset;
202 Size = (ULONG)(CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset);
203 if (Size > CacheSeg->Bcb->CacheSegmentSize)
204 {
205 Size = CacheSeg->Bcb->CacheSegmentSize;
206 }
207 Mdl = MmCreateMdl(NULL, CacheSeg->BaseAddress, Size);
208 MmBuildMdlForNonPagedPool(Mdl);
209 KeInitializeEvent(&Event, NotificationEvent, FALSE);
210 Status = IoPageRead(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, & Event, &IoStatus);
211 if (Status == STATUS_PENDING)
212 {
213 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
214 Status = IoStatus.Status;
215 }
216
217 if (!NT_SUCCESS(Status) && Status != STATUS_END_OF_FILE)
218 {
219 DPRINT1("IoPageRead failed, Status %x\n", Status);
220 return Status;
221 }
222 if (CacheSeg->Bcb->CacheSegmentSize > Size)
223 {
224 memset ((char*)CacheSeg->BaseAddress + Size, 0,
225 CacheSeg->Bcb->CacheSegmentSize - Size);
226 }
227 return STATUS_SUCCESS;
228 }
229
230 NTSTATUS
231 WriteCacheSegment(PCACHE_SEGMENT CacheSeg)
232 {
233 ULONG Size;
234 PMDL Mdl;
235 NTSTATUS Status;
236 IO_STATUS_BLOCK IoStatus;
237 LARGE_INTEGER SegOffset;
238 KEVENT Event;
239
240 CacheSeg->Dirty = FALSE;
241 SegOffset.QuadPart = CacheSeg->FileOffset;
242 Size = (ULONG)(CacheSeg->Bcb->AllocationSize.QuadPart - CacheSeg->FileOffset);
243 if (Size > CacheSeg->Bcb->CacheSegmentSize)
244 {
245 Size = CacheSeg->Bcb->CacheSegmentSize;
246 }
247 Mdl = MmCreateMdl(NULL, CacheSeg->BaseAddress, Size);
248 MmBuildMdlForNonPagedPool(Mdl);
249 KeInitializeEvent(&Event, NotificationEvent, FALSE);
250 Status = IoPageWrite(CacheSeg->Bcb->FileObject, Mdl, &SegOffset, &Event, &IoStatus);
251 if (Status == STATUS_PENDING)
252 {
253 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
254 Status = IoStatus.Status;
255 }
256 if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
257 {
258 DPRINT1("IoPageWrite failed, Status %x\n", Status);
259 CacheSeg->Dirty = TRUE;
260 return(Status);
261 }
262 return(STATUS_SUCCESS);
263 }
264
265 /*
266 * @implemented
267 */
268 BOOLEAN STDCALL
269 CcCopyRead (IN PFILE_OBJECT FileObject,
270 IN PLARGE_INTEGER FileOffset,
271 IN ULONG Length,
272 IN BOOLEAN Wait,
273 OUT PVOID Buffer,
274 OUT PIO_STATUS_BLOCK IoStatus)
275 {
276 ULONG ReadOffset;
277 ULONG TempLength;
278 NTSTATUS Status = STATUS_SUCCESS;
279 PVOID BaseAddress;
280 PCACHE_SEGMENT CacheSeg;
281 BOOLEAN Valid;
282 ULONG ReadLength = 0;
283 PBCB Bcb;
284 KIRQL oldirql;
285 PLIST_ENTRY current_entry;
286 PCACHE_SEGMENT current;
287
288 DPRINT("CcCopyRead(FileObject %x, FileOffset %x, "
289 "Length %d, Wait %d, Buffer %x, IoStatus %x)\n",
290 FileObject, (ULONG)FileOffset->QuadPart, Length, Wait,
291 Buffer, IoStatus);
292
293 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
294 ReadOffset = (ULONG)FileOffset->QuadPart;
295
296 DPRINT("AllocationSize %d, FileSize %d\n",
297 (ULONG)Bcb->AllocationSize.QuadPart,
298 (ULONG)Bcb->FileSize.QuadPart);
299
300 /*
301 * Check for the nowait case that all the cache segments that would
302 * cover this read are in memory.
303 */
304 if (!Wait)
305 {
306 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
307 current_entry = Bcb->BcbSegmentListHead.Flink;
308 while (current_entry != &Bcb->BcbSegmentListHead)
309 {
310 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
311 BcbSegmentListEntry);
312 if (!current->Valid && current->FileOffset < ReadOffset + Length
313 && current->FileOffset + Bcb->CacheSegmentSize > ReadOffset)
314 {
315 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
316 IoStatus->Status = STATUS_UNSUCCESSFUL;
317 IoStatus->Information = 0;
318 return FALSE;
319 }
320 current_entry = current_entry->Flink;
321 }
322 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
323 }
324
325 TempLength = ReadOffset % Bcb->CacheSegmentSize;
326 if (TempLength != 0)
327 {
328 TempLength = min (Length, Bcb->CacheSegmentSize - TempLength);
329 Status = CcRosRequestCacheSegment(Bcb,
330 ROUND_DOWN(ReadOffset,
331 Bcb->CacheSegmentSize),
332 &BaseAddress, &Valid, &CacheSeg);
333 if (!NT_SUCCESS(Status))
334 {
335 IoStatus->Information = 0;
336 IoStatus->Status = Status;
337 DPRINT("CcRosRequestCacheSegment faild, Status %x\n", Status);
338 return FALSE;
339 }
340 if (!Valid)
341 {
342 Status = ReadCacheSegment(CacheSeg);
343 if (!NT_SUCCESS(Status))
344 {
345 IoStatus->Information = 0;
346 IoStatus->Status = Status;
347 CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
348 return FALSE;
349 }
350 }
351 memcpy (Buffer, (char*)BaseAddress + ReadOffset % Bcb->CacheSegmentSize,
352 TempLength);
353 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, FALSE, FALSE);
354 ReadLength += TempLength;
355 Length -= TempLength;
356 ReadOffset += TempLength;
357 #if defined(__GNUC__)
358 Buffer += TempLength;
359 #else
360 {
361 char* pTemp = Buffer;
362 pTemp += TempLength;
363 Buffer = pTemp;
364 }
365 #endif
366 }
367 while (Length > 0)
368 {
369 TempLength = min(max(Bcb->CacheSegmentSize, 65536), Length);
370 ReadCacheSegmentChain(Bcb, ReadOffset, TempLength, Buffer);
371 ReadLength += TempLength;
372 Length -= TempLength;
373 ReadOffset += TempLength;
374 #if defined(__GNUC__)
375 Buffer += TempLength;
376 #else
377 {
378 char* pTemp = Buffer;
379 pTemp += TempLength;
380 Buffer = pTemp;
381 }
382 #endif
383 }
384 IoStatus->Status = STATUS_SUCCESS;
385 IoStatus->Information = ReadLength;
386 DPRINT("CcCopyRead O.K.\n");
387 return TRUE;
388 }
389
390 /*
391 * @implemented
392 */
393 BOOLEAN STDCALL
394 CcCopyWrite (IN PFILE_OBJECT FileObject,
395 IN PLARGE_INTEGER FileOffset,
396 IN ULONG Length,
397 IN BOOLEAN Wait,
398 IN PVOID Buffer)
399 {
400 NTSTATUS Status;
401 ULONG WriteOffset;
402 KIRQL oldirql;
403 PBCB Bcb;
404 PLIST_ENTRY current_entry;
405 PCACHE_SEGMENT CacheSeg;
406 ULONG TempLength;
407 PVOID BaseAddress;
408 BOOLEAN Valid;
409
410 DPRINT("CcCopyWrite(FileObject %x, FileOffset %x, "
411 "Length %d, Wait %d, Buffer %x)\n",
412 FileObject, (ULONG)FileOffset->QuadPart, Length, Wait, Buffer);
413
414 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
415 WriteOffset = (ULONG)FileOffset->QuadPart;
416
417 if (!Wait)
418 {
419 /* testing, if the requested datas are available */
420 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
421 current_entry = Bcb->BcbSegmentListHead.Flink;
422 while (current_entry != &Bcb->BcbSegmentListHead)
423 {
424 CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
425 BcbSegmentListEntry);
426 if (!CacheSeg->Valid)
427 {
428 if ((WriteOffset >= CacheSeg->FileOffset &&
429 WriteOffset < CacheSeg->FileOffset + Bcb->CacheSegmentSize)
430 || (WriteOffset + Length > CacheSeg->FileOffset &&
431 WriteOffset + Length <= CacheSeg->FileOffset +
432 Bcb->CacheSegmentSize))
433 {
434 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
435 /* datas not available */
436 return(FALSE);
437 }
438 }
439 current_entry = current_entry->Flink;
440 }
441 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
442 }
443
444 TempLength = WriteOffset % Bcb->CacheSegmentSize;
445 if (TempLength != 0)
446 {
447 ULONG ROffset;
448 ROffset = ROUND_DOWN(WriteOffset, Bcb->CacheSegmentSize);
449 TempLength = min (Length, Bcb->CacheSegmentSize - TempLength);
450 Status = CcRosRequestCacheSegment(Bcb, ROffset,
451 &BaseAddress, &Valid, &CacheSeg);
452 if (!NT_SUCCESS(Status))
453 {
454 return(FALSE);
455 }
456 if (!Valid)
457 {
458 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg)))
459 {
460 return(FALSE);
461 }
462 }
463 memcpy ((char*)BaseAddress + WriteOffset % Bcb->CacheSegmentSize,
464 Buffer, TempLength);
465 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE);
466
467 Length -= TempLength;
468 WriteOffset += TempLength;
469 #if defined(__GNUC__)
470 Buffer += TempLength;
471 #else
472 {
473 char* pTemp = Buffer;
474 pTemp += TempLength;
475 Buffer = pTemp;
476 }
477 #endif
478 }
479
480 while (Length > 0)
481 {
482 TempLength = min (Bcb->CacheSegmentSize, Length);
483 Status = CcRosRequestCacheSegment(Bcb, WriteOffset,
484 &BaseAddress, &Valid, &CacheSeg);
485 if (!NT_SUCCESS(Status))
486 {
487 return(FALSE);
488 }
489 if (!Valid && TempLength < Bcb->CacheSegmentSize)
490 {
491 if (!NT_SUCCESS(ReadCacheSegment(CacheSeg)))
492 {
493 CcRosReleaseCacheSegment(Bcb, CacheSeg, FALSE, FALSE, FALSE);
494 return FALSE;
495 }
496 }
497 memcpy (BaseAddress, Buffer, TempLength);
498 CcRosReleaseCacheSegment(Bcb, CacheSeg, TRUE, TRUE, FALSE);
499 Length -= TempLength;
500 WriteOffset += TempLength;
501 #if defined(__GNUC__)
502 Buffer += TempLength;
503 #else
504 {
505 char* pTemp = Buffer;
506 pTemp += TempLength;
507 Buffer = pTemp;
508 }
509 #endif
510 }
511 return(TRUE);
512 }
513
514 /*
515 * @implemented
516 */
517 BOOLEAN STDCALL
518 CcZeroData (IN PFILE_OBJECT FileObject,
519 IN PLARGE_INTEGER StartOffset,
520 IN PLARGE_INTEGER EndOffset,
521 IN BOOLEAN Wait)
522 {
523 NTSTATUS Status;
524 LARGE_INTEGER WriteOffset;
525 ULONG Length;
526 PMDL Mdl;
527 ULONG i;
528 IO_STATUS_BLOCK Iosb;
529 KEVENT Event;
530
531 DPRINT("CcZeroData(FileObject %x, StartOffset %I64x, EndOffset %I64x, "
532 "Wait %d\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart,
533 Wait);
534
535 Length = EndOffset->u.LowPart - StartOffset->u.LowPart;
536
537 if (FileObject->SectionObjectPointer->SharedCacheMap == NULL)
538 {
539 /* File is not cached */
540 WriteOffset.QuadPart = StartOffset->QuadPart;
541
542 while (Length > 0)
543 {
544 if (Length + WriteOffset.u.LowPart % PAGE_SIZE > 262144)
545 {
546 Mdl = MmCreateMdl(NULL, (PVOID)WriteOffset.u.LowPart,
547 262144 - WriteOffset.u.LowPart % PAGE_SIZE);
548 WriteOffset.QuadPart +=
549 (262144 - WriteOffset.u.LowPart % PAGE_SIZE);
550 Length -= (262144 - WriteOffset.u.LowPart % PAGE_SIZE);
551 }
552 else
553 {
554 Mdl =
555 MmCreateMdl(NULL, (PVOID)WriteOffset.u.LowPart,
556 Length - WriteOffset.u.LowPart % PAGE_SIZE);
557 WriteOffset.QuadPart +=
558 (Length - WriteOffset.u.LowPart % PAGE_SIZE);
559 Length = 0;
560 }
561 if (Mdl == NULL)
562 {
563 return(FALSE);
564 }
565 Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
566 for (i = 0; i < ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG)); i++)
567 {
568 ((PULONG)(Mdl + 1))[i] = CcZeroPage.u.LowPart;
569 }
570 KeInitializeEvent(&Event, NotificationEvent, FALSE);
571 Status = IoPageWrite(FileObject, Mdl, StartOffset, &Event, &Iosb);
572 if (Status == STATUS_PENDING)
573 {
574 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
575 Status = Iosb.Status;
576 }
577 if (!NT_SUCCESS(Status))
578 {
579 return(FALSE);
580 }
581 }
582 }
583 else
584 {
585 /* File is cached */
586 KIRQL oldirql;
587 PBCB Bcb;
588 PLIST_ENTRY current_entry;
589 PCACHE_SEGMENT CacheSeg, current, previous;
590 ULONG TempLength;
591 ULONG Start;
592 ULONG count;
593 ULONG size;
594 PHYSICAL_ADDRESS page;
595
596 Start = StartOffset->u.LowPart;
597 Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
598 if (Wait)
599 {
600 /* testing, if the requested datas are available */
601 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
602 current_entry = Bcb->BcbSegmentListHead.Flink;
603 while (current_entry != &Bcb->BcbSegmentListHead)
604 {
605 CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
606 BcbSegmentListEntry);
607 if (!CacheSeg->Valid)
608 {
609 if ((Start >= CacheSeg->FileOffset &&
610 Start < CacheSeg->FileOffset + Bcb->CacheSegmentSize)
611 || (Start + Length > CacheSeg->FileOffset &&
612 Start + Length <=
613 CacheSeg->FileOffset + Bcb->CacheSegmentSize))
614 {
615 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
616 /* datas not available */
617 return(FALSE);
618 }
619 }
620 current_entry = current_entry->Flink;
621 }
622 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
623 }
624
625 while (Length > 0)
626 {
627 ULONG RStart = ROUND_DOWN(Start, Bcb->CacheSegmentSize);
628 WriteOffset.QuadPart = ROUND_DOWN(Start, Bcb->CacheSegmentSize);
629 if (Start % Bcb->CacheSegmentSize + Length > 262144)
630 {
631 Mdl = MmCreateMdl(NULL, NULL, 262144);
632 if (Mdl == NULL)
633 {
634 return FALSE;
635 }
636 Status = CcRosGetCacheSegmentChain (Bcb, RStart,
637 262144, &CacheSeg);
638 if (!NT_SUCCESS(Status))
639 {
640 ExFreePool(Mdl);
641 return(FALSE);
642 }
643 }
644 else
645 {
646 ULONG RLength;
647 RLength = Start % Bcb->CacheSegmentSize + Length;
648 RLength = ROUND_UP(RLength, Bcb->CacheSegmentSize);
649 Mdl = MmCreateMdl(NULL, (PVOID)RStart, RLength);
650 if (Mdl == NULL)
651 {
652 return(FALSE);
653 }
654 Status = CcRosGetCacheSegmentChain (Bcb, RStart, RLength,
655 &CacheSeg);
656 if (!NT_SUCCESS(Status))
657 {
658 ExFreePool(Mdl);
659 return(FALSE);
660 }
661 }
662 Mdl->MdlFlags |= (MDL_PAGES_LOCKED|MDL_IO_PAGE_READ);
663 current = CacheSeg;
664 count = 0;
665 while (current != NULL)
666 {
667 if ((Start % Bcb->CacheSegmentSize) != 0 ||
668 Start % Bcb->CacheSegmentSize + Length <
669 Bcb->CacheSegmentSize)
670 {
671 if (!current->Valid)
672 {
673 /* Segment lesen */
674 Status = ReadCacheSegment(current);
675 if (!NT_SUCCESS(Status))
676 {
677 DPRINT1("ReadCacheSegment failed, status %x\n",
678 Status);
679 }
680 }
681 TempLength = min (Length, Bcb->CacheSegmentSize -
682 Start % Bcb->CacheSegmentSize);
683 memset ((char*)current->BaseAddress + Start % Bcb->CacheSegmentSize,
684 0, TempLength);
685 }
686 else
687 {
688 TempLength = Bcb->CacheSegmentSize;
689 memset (current->BaseAddress, 0, Bcb->CacheSegmentSize);
690 }
691 Start += TempLength;
692 Length -= TempLength;
693
694 size = ((Mdl->Size - sizeof(MDL)) / sizeof(ULONG));
695 for (i = 0; i < (Bcb->CacheSegmentSize / PAGE_SIZE) &&
696 count < size; i++)
697 {
698 PVOID Address;
699 Address = (char*)current->BaseAddress + (i * PAGE_SIZE);
700 page =
701 MmGetPhysicalAddressForProcess(NULL, Address);
702 ((PULONG)(Mdl + 1))[count++] = page.u.LowPart;
703 }
704 current = current->NextInChain;
705 }
706
707 /* Write the Segment */
708 KeInitializeEvent(&Event, NotificationEvent, FALSE);
709 Status = IoPageWrite(FileObject, Mdl, &WriteOffset, &Event, &Iosb);
710 if (Status == STATUS_PENDING)
711 {
712 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
713 Status = Iosb.Status;
714 }
715 if (!NT_SUCCESS(Status))
716 {
717 DPRINT1("IoPageWrite failed, status %x\n", Status);
718 }
719 current = CacheSeg;
720 while (current != NULL)
721 {
722 previous = current;
723 current = current->NextInChain;
724 CcRosReleaseCacheSegment(Bcb, previous, TRUE, FALSE, FALSE);
725 }
726 }
727 }
728 return(TRUE);
729 }
730