WDK Mini Filter Example
ncoffsets.c
Go to the documentation of this file.
1 #include "nc.h"
2 
3 /*
4 
5 Munging entries from the directory query responses requires name changer
6 to interpret the data returned from the query. There are currently 9
7 information classes, each with a different structure for holding the file data.
8 
9 Of the 9 queries, we are interested in the following:
10 
11 FileBothDirectoryInformation
12 FileDirectoryInformation
13 FileFullDirectoryInformation
14 FileFullDirectoryInformation
15 FileIdFullDirectoryInformation
16 FileNamesInformation
17 FileObjectIdInformation
18 
19 Each of structures related to these queries have the following properties:
20 1) Holds the offset to the next entry
21 2) Holds the file name length (in bytes)
22 3) The first WCHAR of the file name is the last entry of the structure,
23 with the remainder of the name following the structure.
24 
25 The purpose of the DIRECTORY_CONTROL_OFFSETS structure is to allow
26 a generic method of interpreting the query data by holding the offset
27 information for each of the above variables. Combined with the directory
28 walking functions (below) we now have an easy uniform means of parsing
29 the directory queries.
30 
31 */
32 
33 #ifdef ALLOC_PRAGMA
34 #pragma alloc_text(PAGE, NcCalculateDirectoryNotificationOffsets)
35 #pragma alloc_text(PAGE, NcDetermineStructureOffsets)
36 #pragma alloc_text(PAGE, NcGetEntrySize)
37 #pragma alloc_text(PAGE, NcGetFileName)
38 #pragma alloc_text(PAGE, NcGetFileNameLength)
39 #pragma alloc_text(PAGE, NcGetNextEntry)
40 #pragma alloc_text(PAGE, NcGetNextEntryOffset)
41 #pragma alloc_text(PAGE, NcGetShortName)
42 #pragma alloc_text(PAGE, NcGetShortNameLength)
43 #pragma alloc_text(PAGE, NcSetFileName)
44 #pragma alloc_text(PAGE, NcSetNextEntryOffset)
45 #pragma alloc_text(PAGE, NcSetShortName)
46 #endif
47 
48 //---------------------------------------------------------------------------
49 // FUNCTIONS FOR WALKING DIRECTORY STRUCTURE
50 //---------------------------------------------------------------------------
51 BOOLEAN
53  _Out_ PDIRECTORY_CONTROL_OFFSETS Offsets,
54  _In_ FILE_INFORMATION_CLASS Information
55  )
56 /*++
57 
58 Routine Description:
59 
60  Determines the structure offsets for the FILE_INFORMATION_CLASS provided.
61 
62 Arguments:
63 
64  Offsets - Output DIRECTORY_CONTROL_OFFSETS pointer.
65 
66  Information - What structure to use.
67 
68  DirectoryBuffer - A sample buffer for us to test with.
69 
70 Returns:
71 
72  return TRUE if we have a structure to handle this request,
73  otherwise return FALSE. Offsets are returned through the Offsets
74  pointer.
75 
76 --*/
77 {
78  BOOLEAN ReturnValue = TRUE;
79  PAGED_CODE();
80 
81  //
82  // Not all directory information classes have short names.
83  // So we'll zero out short name data for classes that don't expose it .
84  //
85 
86  Offsets->ShortNamePresent = FALSE;
87  Offsets->ShortNameLengthDist = 0;
88  Offsets->ShortNameDist = 0;
89 
90  switch( Information ) {
91 
92  case FileBothDirectoryInformation:
93 
94  Offsets->NextEntryOffsetDist =
95  FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION, NextEntryOffset );
96 
97  Offsets->FileNameLengthDist =
98  FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION, FileNameLength );
99 
100  Offsets->FileNameDist =
101  FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION, FileName );
102 
103  Offsets->ShortNamePresent = TRUE;
104 
105  Offsets->ShortNameLengthDist =
106  FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION, ShortNameLength );
107 
108  Offsets->ShortNameDist =
109  FIELD_OFFSET( FILE_BOTH_DIR_INFORMATION, ShortName );
110 
111  break;
112 
113  case FileDirectoryInformation:
114 
115  Offsets->NextEntryOffsetDist =
116  FIELD_OFFSET( FILE_DIRECTORY_INFORMATION, NextEntryOffset );
117 
118  Offsets->FileNameLengthDist =
119  FIELD_OFFSET( FILE_DIRECTORY_INFORMATION, FileNameLength );
120 
121  Offsets->FileNameDist =
122  FIELD_OFFSET( FILE_DIRECTORY_INFORMATION, FileName );
123 
124  break;
125 
126  case FileFullDirectoryInformation:
127 
128  Offsets->NextEntryOffsetDist =
129  FIELD_OFFSET( FILE_FULL_DIR_INFORMATION, NextEntryOffset );
130 
131  Offsets->FileNameLengthDist =
132  FIELD_OFFSET( FILE_FULL_DIR_INFORMATION, FileNameLength );
133 
134  Offsets->FileNameDist =
135  FIELD_OFFSET( FILE_FULL_DIR_INFORMATION, FileName );
136 
137  break;
138 
139  case FileIdBothDirectoryInformation:
140 
141  Offsets->NextEntryOffsetDist =
142  FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION, NextEntryOffset );
143 
144  Offsets->FileNameLengthDist =
145  FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION, FileNameLength );
146 
147  Offsets->FileNameDist =
148  FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION, FileName );
149 
150  Offsets->ShortNamePresent = TRUE;
151 
152  Offsets->ShortNameLengthDist =
153  FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION, ShortNameLength );
154 
155  Offsets->ShortNameDist =
156  FIELD_OFFSET( FILE_ID_BOTH_DIR_INFORMATION, ShortName );
157 
158  break;
159 
160  case FileIdFullDirectoryInformation:
161 
162  Offsets->NextEntryOffsetDist =
163  FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION, NextEntryOffset );
164 
165  Offsets->FileNameLengthDist =
166  FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION, FileNameLength );
167 
168  Offsets->FileNameDist =
169  FIELD_OFFSET( FILE_ID_FULL_DIR_INFORMATION, FileName );
170 
171  break;
172 
173  case FileNamesInformation:
174 
175  Offsets->NextEntryOffsetDist =
176  FIELD_OFFSET( FILE_NAMES_INFORMATION, NextEntryOffset );
177 
178  Offsets->FileNameLengthDist =
179  FIELD_OFFSET( FILE_NAMES_INFORMATION, FileNameLength );
180 
181  Offsets->FileNameDist =
182  FIELD_OFFSET( FILE_NAMES_INFORMATION, FileName );
183 
184  break;
185 
186  default:
187 
188  //
189  // There are queries that we don't filter,
190  // so just return FALSE to state failure.
191  //
192 
193  ReturnValue = FALSE;
194  break;
195  }
196 
197  return ReturnValue;
198 }
199 
200 VOID
203  )
204 /*++
205 
206 Routine Description:
207 
208  Directory Notifications use a structure with similar properties
209  to a directory query. CalculateDirectoryNotificationOffsets allows
210  us to reuse the ncoffsets library with directory notification structures.
211 
212 Arguments
213 
214  Offsets - Output DIRECTORY_CONTROL_OFFSETS pointer.
215 
216 --*/
217 {
218 
219  PAGED_CODE();
220 
221  //
222  // Place offsets for next entry and file name.
223  //
224 
225  Offsets->NextEntryOffsetDist = FIELD_OFFSET( FILE_NOTIFY_INFORMATION, NextEntryOffset );
226  Offsets->FileNameLengthDist = FIELD_OFFSET( FILE_NOTIFY_INFORMATION, FileNameLength );
227  Offsets->FileNameDist = FIELD_OFFSET( FILE_NOTIFY_INFORMATION, FileName );
228 
229  //
230  // Directory notification does not have short names.
231  //
232 
233  Offsets->ShortNamePresent = FALSE;
234  Offsets->ShortNameLengthDist = 0;
235  Offsets->ShortNameDist = 0;
236 }
237 
238 
239 ULONG
241  _In_ CONST PVOID Buffer,
242  _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets
243  )
244 /*++
245 
246 Routine Description:
247 
248  Returns the offset in bytes to the next entry.
249 
250 Arguments:
251 
252  Buffer - Pointer to the start of the current entry.
253 
254  Offsets - Offsets structure for this information class.
255 
256 Return Value:
257 
258  The number of bytes from Buffer to the next entry.
259 
260 --*/
261 {
262  PULONG Offset = Add2Ptr( Buffer, Offsets->NextEntryOffsetDist );
263  PAGED_CODE();
264  return *Offset;
265 }
266 
267 
268 PVOID
270  _In_ CONST PVOID Buffer,
271  _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets
272  )
273 /*++
274 
275 Routine Description:
276 
277  Returns a pointer to the next entry in the buffer.
278 
279 Arguments:
280 
281  Buffer - Pointer to the start of the current entry.
282 
283  Offsets - Offsets structure for this information class.
284 
285 Return Value:
286 
287  Returns a pointer to the beginning of the next entry.
288 
289 --*/
290 {
291  ULONG Offset = NcGetNextEntryOffset( Buffer, Offsets );
292  PVOID NextEntry = Add2Ptr( Buffer, Offset );
293  PAGED_CODE();
294  return NextEntry;
295 }
296 
297 
298 ULONG
300  _In_ CONST PVOID Buffer,
301  _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets
302  )
303 /*++
304 
305 Routine Description:
306 
307  Returns the length of the file name in bytes.
308 
309 Arguments:
310 
311  Buffer - Pointer to the start of the entry.
312 
313  Offsets - Offsets structure for the information class.
314 
315 Return Value:
316 
317  Returns the length of the file name component of the buffer.
318 
319 --*/
320 {
321  ULONG Result = *((PULONG)(Add2Ptr( Buffer, Offsets->FileNameLengthDist )));
322  PAGED_CODE();
323  return Result;
324 }
325 
326 
327 ULONG
329  _In_ CONST PVOID Buffer,
330  _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets
331  )
332 /*++
333 
334 Routine Description:
335 
336  Returns the size of this entry in bytes.
337 
338 Arguments:
339 
340  Buffer - Pointer to the start of the entry.
341 
342  Offsets - Offsets structure for the information class.
343 
344 Return Value:
345 
346  Returns the size of this entry in bytes.
347 
348 --*/
349 {
350  ULONG EntrySize = NcGetNextEntryOffset(Buffer, Offsets);
351  PAGED_CODE();
352 
353  if (EntrySize == 0) {
354 
355  //
356  // We are at last entry, so we need to calculate this ourselves.
357  //
358 
359  EntrySize = NcGetFileNameLength( Buffer, Offsets );
360  EntrySize += Offsets->FileNameDist;
361  }
362 
363  return EntrySize;
364 }
365 
366 
367 PWSTR
369  _In_ CONST PVOID Buffer,
370  _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets
371  )
372 /*++
373 
374 Routine Description:
375 
376  Returns a pointer to the file name string.
377 
378 Arguments:
379 
380  Buffer - Pointer to the start of the entry.
381 
382  Offsets - Offsets structure for the information class.
383 
384 Return Value:
385 
386  A pointer to the start of the file name for this entry.
387 
388 --*/
389 {
390  PAGED_CODE();
391  return Add2Ptr(Buffer, Offsets->FileNameDist);
392 }
393 
394 
395 PWSTR
397  _In_ CONST PVOID Buffer,
398  _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets
399  )
400 /*++
401 
402 Routine Description:
403 
404  Returns a pointer to the short name for this entry.
405 
406 Arguments:
407 
408  Buffer - Pointer to the start of this entry.
409 
410  Offsets - Offsets structure for the information class.
411 
412 Return Value:
413 
414  If there is a short name in this information class, returns a pointer to the
415  start of the short name. Otherwise, returns NULL.
416 --*/
417 {
418  PAGED_CODE();
419 
420  if (Offsets->ShortNamePresent) {
421 
422  return Add2Ptr(Buffer, Offsets->ShortNameDist);
423 
424  } else {
425 
426  return NULL;
427  }
428 }
429 
430 
431 CCHAR
433  _In_ CONST PVOID Buffer,
434  _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets
435  )
436 /*++
437 
438 Routine Description:
439 
440  Returns the length of the shortname.
441 
442 Arguments
443 
444  Buffer - Pointer to the start of this entry.
445 
446  Offsets - Offsets structure for the information class.
447 
448 Return Value
449 
450  Returns the length of the short name.
451  Returns -1 on failure.
452 
453 --*/
454 {
455  CCHAR *Ptr;
456  PAGED_CODE();
457 
458  if (Offsets->ShortNamePresent) {
459 
460  Ptr = Add2Ptr(Buffer, Offsets->ShortNameLengthDist);
461  return *Ptr;
462  } else {
463 
464  return -1;
465  }
466 }
467 
468 
469 VOID
471  _Inout_ PVOID Buffer,
472  _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets,
473  _In_ BOOLEAN ForceLast
474  )
475 /*++
476 
477 Routine Description:
478 
479  Sets the Next Entry Offset to Value.
480 
481 Arguments:
482 
483  Buffer - Pointer to the start of this entry.
484 
485  Offsets - Offsets structure for the information class.
486 
487  ForceLast - If true, the size of the next entry is set to zero.
488  Otherwise, the size will be set to the size of the
489  information class + the file name's length.
490 
491 --*/
492 {
493  //
494  // Get pointer to NextEntryOffset value.
495  //
496 
497  PULONG NextEntry = Add2Ptr( Buffer, Offsets->NextEntryOffsetDist );
498  PAGED_CODE();
499 
500  //
501  // Get length of name.
502  //
503 
504  if (ForceLast) {
505 
506  //
507  // This is the last entry, so we need to make sure 0 is in the
508  // next entry offset.
509  //
510 
511  *NextEntry = 0;
512 
513  } else {
514 
515  //
516  // Next entry offset is the distance to the name
517  // plus the length of the name.
518  //
519 
520  ULONG NameLength = NcGetFileNameLength( Buffer, Offsets );
521  *NextEntry = Offsets->FileNameDist + NameLength;
522  }
523 }
524 
525 
526 VOID
528  _In_ PVOID Entry,
529  _In_ PWSTR NewName,
530  _In_ ULONG Length,
531  _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets,
532  _In_ BOOLEAN ForceLast
533  )
534 /*++
535 
536 Routine Description:
537 
538  Sets a new file name into the entry.
539 
540 Arguments:
541 
542  Entry - A pointer to the start of the entry.
543 
544  NewName - A pointer to the new file name.
545 
546  Length - The length of the new name (in bytes).
547 
548  Offsets - Offsets structure for the information class.
549 
550  ForceLast - If true, the entry's size will be set to zero
551  so that it looks like a valid last entry.
552 
553 Return Value
554 
555  None.
556 
557 --*/
558 {
559  PWSTR NamePtr;
560  PULONG NameLength;
561 
562  PAGED_CODE();
563 
564  //
565  // Get a pointer to the name in the buffer.
566  //
567 
568  NamePtr = NcGetFileName( Entry, Offsets);
569  NameLength = Add2Ptr( Entry, Offsets->FileNameLengthDist );
570 
571  //
572  // Copy the new name into buffer.
573  //
574 
575  RtlCopyMemory( NamePtr, NewName, Length );
576  *NameLength = Length;
577 
578  //
579  // Now we have to update the size of this entry.
580  //
581 
582  NcSetNextEntryOffset( Entry, Offsets, ForceLast );
583 }
584 
585 
586 VOID
588  _In_ PVOID Entry,
589  _In_ PWSTR NewShortName,
590  _In_ USHORT Length,
591  _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets
592  )
593 /*++
594 
595 Routine Description:
596 
597  Sets a new short name into an entry if the information class
598  supports short names.
599 
600 Arguments:
601 
602  Entry - Pointer to the start of an entry.
603 
604  NewShortName - Pointer to the new shortname.
605 
606  Length - The length of the short name in bytes.
607 
608  Offsets - Offsets structure for the information class.
609 
610 Return Value:
611 
612  None.
613 
614 --*/
615 {
616  PWSTR NamePtr;
617  PCCHAR NameLength;
618 
619  PAGED_CODE();
620 
621  if( Offsets->ShortNamePresent ) {
622 
623  NamePtr = NcGetShortName( Entry, Offsets );
624  NameLength = Add2Ptr( Entry, Offsets->ShortNameLengthDist );
625 
626  FLT_ASSERT( Length <= (12 * sizeof(WCHAR)) );
627 
628  RtlCopyMemory(NamePtr, NewShortName, Length );
629  *NameLength = (UCHAR) Length;
630  }
631 }
632 
VOID NcSetShortName(_In_ PVOID Entry, _In_ PWSTR NewShortName, _In_ USHORT Length, _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets)
Definition: ncoffsets.c:587
VOID NcSetFileName(_In_ PVOID Entry, _In_ PWSTR NewName, _In_ ULONG Length, _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets, _In_ BOOLEAN ForceLast)
Definition: ncoffsets.c:527
CCHAR NcGetShortNameLength(_In_ CONST PVOID Buffer, _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets)
Definition: ncoffsets.c:432
_In_ PLARGE_INTEGER _In_ ULONG Length
BOOLEAN NcDetermineStructureOffsets(_Out_ PDIRECTORY_CONTROL_OFFSETS Offsets, _In_ FILE_INFORMATION_CLASS Information)
Definition: ncoffsets.c:52
ULONG FileNameLengthDist
Definition: nc.h:458
VOID NcSetNextEntryOffset(_Inout_ PVOID Buffer, _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets, _In_ BOOLEAN ForceLast)
Definition: ncoffsets.c:470
RtlCopyMemory(OutputStringBuffer, TempMappingBuffer->Data, OutputString->MaximumLength)
ULONG NcGetNextEntryOffset(_In_ CONST PVOID Buffer, _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets)
Definition: ncoffsets.c:240
#define Add2Ptr(P, I)
Definition: minispy.h:238
PWSTR NcGetFileName(_In_ CONST PVOID Buffer, _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets)
Definition: ncoffsets.c:368
PVOID NcGetNextEntry(_In_ CONST PVOID Buffer, _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets)
Definition: ncoffsets.c:269
FLT_ASSERT(IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))
VOID NcCalculateDirectoryNotificationOffsets(PDIRECTORY_CONTROL_OFFSETS Offsets)
Definition: ncoffsets.c:201
return TRUE
IoStatus Information
_In_ BOOLEAN _Out_ PFILE_BASIC_INFORMATION Buffer
NcLoadRegistryStringRetry NULL
Definition: ncinit.c:53
ULONG NextEntryOffsetDist
Definition: nc.h:457
ULONG NcGetEntrySize(_In_ CONST PVOID Buffer, _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets)
Definition: ncoffsets.c:328
ULONG ShortNameLengthDist
Definition: nc.h:462
BOOLEAN ShortNamePresent
Definition: nc.h:461
ULONG NcGetFileNameLength(_In_ CONST PVOID Buffer, _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets)
Definition: ncoffsets.c:299
PAGED_CODE()
PWSTR NcGetShortName(_In_ CONST PVOID Buffer, _In_ CONST PDIRECTORY_CONTROL_OFFSETS Offsets)
Definition: ncoffsets.c:396

Social Network


Services Overview

Architect, implement and test file system filter drivers for a wide range of functionality. We can offer several levels of assistance to meet your specific.

Contact Us

You are welcome to contact us for salse or partnership.

Sales: sales@easefilter.com
Support: support@easefilter.com
Info: info@easefilter.com