Skip to content

Commit 7e1f794

Browse files
committed
[NTOSKRNL]
Stub FsRtlCancelNotify Implement FsRtlCheckNotifyForDelete, FsRtlNotifyCompleteIrp, FsRtlNotifyCompleteIrpList, FsRtlNotifySetCancelRoutine svn path=/trunk/; revision=55934
1 parent 04177d9 commit 7e1f794

File tree

1 file changed

+221
-0
lines changed

1 file changed

+221
-0
lines changed

reactos/ntoskrnl/fsrtl/notify.c

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,50 @@
1414

1515
/* PRIVATE FUNCTIONS *********************************************************/
1616

17+
VOID
18+
FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange,
19+
IN NTSTATUS Status);
20+
21+
BOOLEAN
22+
FsRtlNotifySetCancelRoutine(IN PIRP Irp,
23+
IN PNOTIFY_CHANGE NotifyChange OPTIONAL);
24+
25+
VOID
26+
NTAPI
27+
FsRtlCancelNotify(IN PDEVICE_OBJECT DeviceObject,
28+
IN PIRP Irp)
29+
{
30+
IoReleaseCancelSpinLock(Irp->CancelIrql);
31+
UNIMPLEMENTED;
32+
}
33+
34+
/*
35+
* @implemented
36+
*/
37+
VOID
38+
FsRtlCheckNotifyForDelete(IN PLIST_ENTRY NotifyList,
39+
IN PVOID FsContext)
40+
{
41+
PLIST_ENTRY NextEntry;
42+
PNOTIFY_CHANGE NotifyChange;
43+
44+
if (!IsListEmpty(NotifyList))
45+
{
46+
/* Browse the notifications list to find the matching entry */
47+
for (NextEntry = NotifyList->Flink;
48+
NextEntry != NotifyList;
49+
NextEntry = NextEntry->Flink)
50+
{
51+
NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList);
52+
/* If the current record matches with the given context, it's the good one */
53+
if (NotifyChange->FsContext == FsContext && !IsListEmpty(&(NotifyChange->NotifyIrps)))
54+
{
55+
FsRtlNotifyCompleteIrpList(NotifyChange, STATUS_DELETE_PENDING);
56+
}
57+
}
58+
}
59+
}
60+
1761
PNOTIFY_CHANGE
1862
FsRtlIsNotifyOnList(IN PLIST_ENTRY NotifyList,
1963
IN PVOID FsContext)
@@ -55,10 +99,138 @@ FsRtlNotifyAcquireFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
5599
RealNotifySync->OwnerCount++;
56100
}
57101

102+
/*
103+
* @implemented
104+
*/
105+
VOID
106+
FsRtlNotifyCompleteIrp(IN PIRP Irp,
107+
IN PNOTIFY_CHANGE NotifyChange,
108+
IN ULONG DataLength,
109+
IN NTSTATUS Status,
110+
IN BOOLEAN SkipCompletion)
111+
{
112+
PVOID Buffer;
113+
PIO_STACK_LOCATION Stack;
114+
115+
PAGED_CODE();
116+
117+
/* Check if we need to complete */
118+
if (!FsRtlNotifySetCancelRoutine(Irp, NotifyChange) && SkipCompletion)
119+
{
120+
return;
121+
}
122+
123+
/* No succes => no data to return just complete */
124+
if (Status != STATUS_SUCCESS)
125+
{
126+
goto Completion;
127+
}
128+
129+
/* Ensure there's something to return */
130+
Stack = IoGetCurrentIrpStackLocation(Irp);
131+
if (!DataLength || Stack->Parameters.NotifyDirectory.Length < DataLength)
132+
{
133+
Status = STATUS_NOTIFY_ENUM_DIR;
134+
goto Completion;
135+
}
136+
137+
/* Ensture there's a buffer where to find data */
138+
if (!NotifyChange->AllocatedBuffer)
139+
{
140+
Irp->IoStatus.Information = DataLength;
141+
NotifyChange->Buffer = NULL;
142+
goto Completion;
143+
}
144+
145+
/* Now, browse all the way to return data
146+
* and find the one that will work. We will
147+
* return data whatever happens
148+
*/
149+
if (Irp->AssociatedIrp.SystemBuffer)
150+
{
151+
Buffer = Irp->AssociatedIrp.SystemBuffer;
152+
goto CopyAndComplete;
153+
}
154+
155+
if (Irp->MdlAddress)
156+
{
157+
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
158+
goto CopyAndComplete;
159+
}
160+
161+
if (!(Stack->Control & SL_PENDING_RETURNED))
162+
{
163+
Buffer = Irp->UserBuffer;
164+
goto CopyAndComplete;
165+
}
166+
167+
Irp->Flags |= (IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_SYNCHRONOUS_PAGING_IO);
168+
Irp->AssociatedIrp.SystemBuffer = NotifyChange->AllocatedBuffer;
169+
/* Nothing to copy */
170+
goto ReleaseAndComplete;
171+
172+
CopyAndComplete:
173+
_SEH2_TRY
174+
{
175+
RtlCopyMemory(Buffer, NotifyChange->AllocatedBuffer, DataLength);
176+
}
177+
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
178+
{
179+
/* Do nothing */
180+
}
181+
_SEH2_END;
182+
183+
ReleaseAndComplete:
184+
PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
185+
186+
/* Release buffer UNLESS it's used */
187+
if (NotifyChange->AllocatedBuffer != Irp->AssociatedIrp.SystemBuffer &&
188+
NotifyChange->AllocatedBuffer)
189+
{
190+
ExFreePoolWithTag(NotifyChange->AllocatedBuffer, 0);
191+
}
192+
193+
/* Prepare for return */
194+
NotifyChange->AllocatedBuffer = 0;
195+
NotifyChange->ThisBufferLength = 0;
196+
Irp->IoStatus.Information = DataLength;
197+
NotifyChange->Buffer = NULL;
198+
199+
/* Finally complete */
200+
Completion:
201+
IoMarkIrpPending(Irp);
202+
Irp->IoStatus.Status = Status;
203+
IofCompleteRequest(Irp, EVENT_INCREMENT);
204+
}
205+
206+
/*
207+
* @implemented
208+
*/
58209
VOID
59210
FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange,
60211
IN NTSTATUS Status)
61212
{
213+
PIRP Irp;
214+
ULONG DataLength;
215+
PLIST_ENTRY NextEntry;
216+
217+
DataLength = NotifyChange->DataLength;
218+
219+
NotifyChange->Flags &= (INVALIDATE_BUFFERS | WATCH_TREE);
220+
NotifyChange->DataLength = 0;
221+
NotifyChange->LastEntry = 0;
222+
223+
while (!IsListEmpty(&(NotifyChange->NotifyIrps)))
224+
{
225+
/* We take the first entry */
226+
NextEntry = RemoveHeadList(&(NotifyChange->NotifyIrps));
227+
Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
228+
/* We complete it */
229+
FsRtlNotifyCompleteIrp(Irp, NotifyChange, DataLength, Status, TRUE);
230+
/* If we're notifying success, just notify first one */
231+
if (Status == STATUS_SUCCESS)
232+
break;
233+
}
62234
}
63235

64236
VOID
@@ -74,6 +246,55 @@ FsRtlNotifyReleaseFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync)
74246
}
75247
}
76248

249+
/*
250+
* @implemented
251+
*/
252+
BOOLEAN
253+
FsRtlNotifySetCancelRoutine(IN PIRP Irp,
254+
IN PNOTIFY_CHANGE NotifyChange OPTIONAL)
255+
{
256+
PDRIVER_CANCEL CancelRoutine;
257+
258+
/* Acquire cancel lock */
259+
IoAcquireCancelSpinLock(&Irp->CancelIrql);
260+
261+
/* If NotifyChange was given */
262+
if (NotifyChange)
263+
{
264+
/* First get cancel routine */
265+
CancelRoutine = IoSetCancelRoutine(Irp, NULL);
266+
Irp->IoStatus.Information = 0;
267+
/* Release cancel lock */
268+
IoReleaseCancelSpinLock(Irp->CancelIrql);
269+
/* If there was a cancel routine */
270+
if (CancelRoutine)
271+
{
272+
/* Decrease reference count */
273+
InterlockedDecrement((PLONG)&NotifyChange->ReferenceCount);
274+
/* Notify that we removed cancel routine */
275+
return TRUE;
276+
}
277+
}
278+
else
279+
{
280+
/* If IRP is cancel, call FsRtl cancel routine */
281+
if (Irp->Cancel)
282+
{
283+
FsRtlCancelNotify(NULL, Irp);
284+
}
285+
else
286+
{
287+
/* Otherwise, define FsRtl cancel routine as IRP cancel routine */
288+
IoSetCancelRoutine(Irp, FsRtlCancelNotify);
289+
/* Release lock */
290+
IoReleaseCancelSpinLock(Irp->CancelIrql);
291+
}
292+
}
293+
294+
/* Return that we didn't removed cancel routine */
295+
return FALSE;
296+
}
297+
77298
/* PUBLIC FUNCTIONS **********************************************************/
78299

79300
/*++

0 commit comments

Comments
 (0)