Use Rule class to generate instructions for .idl files
[reactos.git] / rosapps / ext2 / dir.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: services/fs/ext2/dir.c
5 * PURPOSE: ext2 filesystem
6 * PROGRAMMER: David Welch (welch@cwcom.net)
7 * UPDATE HISTORY:
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntddk.h>
13 #include <wchar.h>
14 #include <string.h>
15
16 //#define NDEBUG
17 #include <debug.h>
18
19 #include "ext2fs.h"
20
21 /* FUNCTIONS *****************************************************************/
22
23
24 static VOID Ext2ConvertName(PWSTR Out, PCH In, ULONG Len)
25 {
26 ULONG i;
27
28 for (i=0; i<Len; i++)
29 {
30 *Out = *In;
31 Out++;
32 In++;
33 }
34 *Out = 0;
35 }
36
37 PVOID Ext2ProcessDirEntry(PDEVICE_EXTENSION DeviceExt,
38 struct ext2_dir_entry* dir_entry,
39 PIO_STACK_LOCATION IoStack,
40 PVOID Buffer,
41 ULONG FileIndex)
42 {
43 PFILE_DIRECTORY_INFORMATION FDI;
44 PFILE_NAMES_INFORMATION FNI;
45 PFILE_BOTH_DIRECTORY_INFORMATION FBI;
46 struct ext2_inode inode;
47
48 DPRINT("FileIndex %d\n",FileIndex);
49 DPRINT("Buffer %x\n",Buffer);
50
51 Ext2ReadInode(DeviceExt,
52 dir_entry->inode,
53 &inode);
54
55 switch (IoStack->Parameters.QueryDirectory.FileInformationClass)
56 {
57 case FileNamesInformation:
58 FNI = (PFILE_NAMES_INFORMATION)Buffer;
59 FNI->NextEntryOffset = sizeof(FileDirectoryInformation) +
60 dir_entry->name_len + 1;
61 FNI->FileNameLength = dir_entry->name_len;
62 Ext2ConvertName(FNI->FileName, dir_entry->name, dir_entry->name_len);
63 Buffer = Buffer + FNI->NextEntryOffset;
64 break;
65
66 case FileDirectoryInformation:
67 FDI = (PFILE_DIRECTORY_INFORMATION)Buffer;
68 FDI->NextEntryOffset = sizeof(FileDirectoryInformation) +
69 dir_entry->name_len + 1;
70 FDI->FileIndex = FileIndex;
71 // FDI->CreationTime = 0;
72 // FDI->LastAccessTime = 0;
73 // FDI->LastWriteTime = 0;
74 // FDI->ChangeTime = 0;
75 FDI->AllocationSize.QuadPart = FDI->EndOfFile.QuadPart = inode.i_size;
76 FDI->FileAttributes = 0;
77 FDI->FileNameLength = dir_entry->name_len;
78 Ext2ConvertName(FDI->FileName, dir_entry->name, dir_entry->name_len);
79 Buffer = Buffer + FDI->NextEntryOffset;
80 break;
81
82 case FileBothDirectoryInformation:
83 FBI = (PFILE_BOTH_DIRECTORY_INFORMATION)Buffer;
84 FBI->NextEntryOffset = sizeof(FileBothDirectoryInformation) +
85 dir_entry->name_len + 1;
86 FBI->FileIndex = FileIndex;
87 FBI->AllocationSize.QuadPart = FBI->EndOfFile.QuadPart = inode.i_size;
88 FBI->FileAttributes = 0;
89 FBI->FileNameLength = dir_entry->name_len;
90 Ext2ConvertName(FBI->FileName, dir_entry->name, dir_entry->name_len);
91 memset(FBI->ShortName, 0, sizeof(FBI->ShortName));
92 Buffer = Buffer + FBI->NextEntryOffset;
93 break;
94
95 default:
96 UNIMPLEMENTED;
97 }
98 return(Buffer);
99 }
100
101
102 NTSTATUS Ext2QueryDirectory(PDEVICE_EXTENSION DeviceExt,
103 PEXT2_FCB Fcb,
104 PIRP Irp,
105 PIO_STACK_LOCATION IoStack)
106 {
107 ULONG Max;
108 ULONG i;
109 ULONG StartIndex;
110 PVOID Buffer = NULL;
111 struct ext2_dir_entry dir_entry;
112
113 Buffer = Irp->UserBuffer;
114 DPRINT("Buffer %x\n",Buffer);
115 DPRINT("IoStack->Flags %x\n",IoStack->Flags);
116
117 if (IoStack->Flags & SL_RETURN_SINGLE_ENTRY)
118 {
119 Max = 1;
120 }
121 else
122 {
123 UNIMPLEMENTED;
124 }
125
126 DPRINT("Buffer->FileIndex %d\n",
127 ((PFILE_DIRECTORY_INFORMATION)Buffer)->FileIndex);
128 if (IoStack->Flags & SL_INDEX_SPECIFIED)
129 {
130 StartIndex = ((PFILE_DIRECTORY_INFORMATION)Buffer)->FileIndex;
131 }
132 else
133 {
134 StartIndex = 0;
135 }
136
137 if (IoStack->Flags & SL_RESTART_SCAN)
138 {
139 StartIndex = 0;
140 }
141
142 DPRINT("StartIndex %d\n",StartIndex);
143
144 for (i=0; i<Max ;i++)
145 {
146 if (!Ext2ScanDir(DeviceExt,&Fcb->inode,"*",&dir_entry,&StartIndex))
147 {
148 ((PFILE_DIRECTORY_INFORMATION)Buffer)->NextEntryOffset = 0;
149 return(STATUS_NO_MORE_FILES);
150 }
151 Buffer = Ext2ProcessDirEntry(DeviceExt,
152 &dir_entry,
153 IoStack,
154 Buffer,
155 StartIndex);
156 }
157 return(STATUS_SUCCESS);
158 }
159
160 NTSTATUS STDCALL
161 Ext2DirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
162 {
163 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
164 PFILE_OBJECT FileObject = Stack->FileObject;
165 PEXT2_FCB Fcb = (PVOID)FileObject->FsContext;
166 NTSTATUS Status;
167 PDEVICE_EXTENSION DeviceExt;
168
169 DPRINT("Ext2DirectoryControl(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
170
171 DeviceExt = DeviceObject->DeviceExtension;
172
173 switch (Stack->MinorFunction)
174 {
175 case IRP_MN_QUERY_DIRECTORY:
176 Status = Ext2QueryDirectory(DeviceExt, Fcb, Irp, Stack);
177 break;
178
179 default:
180 Status = STATUS_UNSUCCESSFUL;
181 }
182
183 Irp->IoStatus.Status = Status;
184 Irp->IoStatus.Information = 0;
185
186 IoCompleteRequest(Irp, IO_NO_INCREMENT);
187 return(Status);
188 }
189
190 BOOL Ext2ScanDir(PDEVICE_EXTENSION DeviceExt,
191 struct ext2_inode* dir,
192 PCH filename,
193 struct ext2_dir_entry* ret,
194 PULONG StartIndex)
195 {
196 ULONG i;
197 char* buffer;
198 ULONG offset;
199 char name[255];
200 struct ext2_dir_entry* current;
201 ULONG block;
202 BOOL b;
203
204 DPRINT("Ext2ScanDir(dir %x, filename %s, ret %x)\n",dir,filename,ret);
205
206 buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
207
208 for (i=0; i<((*StartIndex)/BLOCKSIZE); i++);
209 for (; (block = Ext2BlockMap(DeviceExt, dir, i)) != 0; i++)
210 {
211 DPRINT("block %d\n",block);
212 b = Ext2ReadSectors(DeviceExt->StorageDevice,
213 block,
214 1,
215 buffer);
216 if (!b)
217 {
218 DbgPrint("ext2fs:%s:%d: Disk io failed\n", __FILE__, __LINE__);
219 return(FALSE);
220 }
221
222 offset = (*StartIndex)%BLOCKSIZE;
223 while (offset < BLOCKSIZE)
224 {
225 current = &buffer[offset];
226
227 strncpy(name,current->name,current->name_len);
228 name[current->name_len]=0;
229
230 DPRINT("Scanning offset %d inode %d name %s\n",
231 offset,current->inode,name);
232
233 DPRINT("Comparing %s %s\n",name,filename);
234 if (strcmp(name,filename)==0 || strcmp(filename,"*")==0)
235 {
236 DPRINT("Match found\n");
237 *StartIndex = (i*BLOCKSIZE) + offset + current->rec_len;
238 memcpy(ret,current,sizeof(struct ext2_dir_entry));
239 ExFreePool(buffer);
240 return(TRUE);
241 }
242
243 offset = offset + current->rec_len;
244 ASSERT(current->rec_len != 0);
245 DPRINT("offset %d\n",offset);
246 }
247 DPRINT("Onto next block\n");
248 }
249 DPRINT("No match\n");
250 ExFreePool(buffer);
251 return(FALSE);
252 }
253
254 void unicode_to_ansi(PCH StringA, PWSTR StringW)
255 {
256 while((*StringW)!=0)
257 {
258 *StringA = *StringW;
259 StringA++;
260 StringW++;
261 }
262 *StringA = 0;
263 }
264
265 NTSTATUS Ext2OpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
266 PWSTR FileName)
267 /*
268 * FUNCTION: Opens a file
269 */
270 {
271 EXT2_INODE parent_inode;
272 struct ext2_dir_entry entry;
273 char name[255];
274 ULONG current_inode = 2;
275 char* current_segment;
276 PEXT2_FCB Fcb;
277 ULONG StartIndex = 0;
278
279 DPRINT("Ext2OpenFile(DeviceExt %x, FileObject %x, FileName %S)\n",
280 DeviceExt,FileObject,FileName);
281
282 Fcb = ExAllocatePool(NonPagedPool, sizeof(EXT2_FCB));
283
284 unicode_to_ansi(name,FileName);
285 DPRINT("name %s\n",name);
286 DPRINT("strtok %x\n",strtok);
287 current_segment = strtok(name,"\\");
288 DPRINT("current_segment %x\n", current_segment);
289 while (current_segment!=NULL)
290 {
291 Ext2LoadInode(DeviceExt,
292 current_inode,
293 &parent_inode);
294 if (!Ext2ScanDir(DeviceExt,
295 parent_inode.inode,
296 current_segment,
297 &entry,
298 &StartIndex))
299 {
300 Ext2ReleaseInode(DeviceExt,
301 &parent_inode);
302 ExFreePool(Fcb);
303 return(STATUS_UNSUCCESSFUL);
304 }
305 current_inode = entry.inode;
306 current_segment = strtok(NULL,"\\");
307 StartIndex = 0;
308 Ext2ReleaseInode(DeviceExt,
309 &parent_inode);
310 }
311 DPRINT("Found file\n");
312
313 Fcb->inode = current_inode;
314 CcRosInitializeFileCache(FileObject, &Fcb->Bcb, PAGE_SIZE*3);
315 FileObject->FsContext = Fcb;
316
317 return(STATUS_SUCCESS);
318 }
319
320 NTSTATUS STDCALL
321 Ext2Create(PDEVICE_OBJECT DeviceObject, PIRP Irp)
322 {
323 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
324 PFILE_OBJECT FileObject = Stack->FileObject;
325 NTSTATUS Status;
326 PDEVICE_EXTENSION DeviceExt;
327
328 DPRINT("Ext2Create(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
329
330 DeviceExt = DeviceObject->DeviceExtension;
331 Status = Ext2OpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer);
332
333 Irp->IoStatus.Status = Status;
334 Irp->IoStatus.Information = 0;
335
336 IoCompleteRequest(Irp, IO_NO_INCREMENT);
337 return(Status);
338 }