Added regedit unit test, a couple minor changes to regedit.
[wine] / dlls / ntdll / file.c
1 /*
2  * Copyright 1999, 2000 Juergen Schmied
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include "config.h"
20 #include "wine/port.h"
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #ifdef HAVE_SYS_ERRNO_H
28 #include <sys/errno.h>
29 #endif
30 #include "wine/debug.h"
31 #include "wine/server.h"
32 #include "ntdll_misc.h"
33 #include "file.h" /* FIXME */
34
35 #include "ntddk.h"
36 #include "winioctl.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
39
40
41 /**************************************************************************
42  *                 NtOpenFile                           [NTDLL.@]
43  *                 ZwOpenFile                           [NTDLL.@]
44  * FUNCTION: Opens a file
45  * ARGUMENTS:
46  *  FileHandle          Variable that receives the file handle on return
47  *  DesiredAccess       Access desired by the caller to the file
48  *  ObjectAttributes    Structue describing the file to be opened
49  *  IoStatusBlock       Receives details about the result of the operation
50  *  ShareAccess         Type of shared access the caller requires
51  *  OpenOptions         Options for the file open
52  */
53 NTSTATUS WINAPI NtOpenFile(
54         OUT PHANDLE FileHandle,
55         ACCESS_MASK DesiredAccess,
56         POBJECT_ATTRIBUTES ObjectAttributes,
57         OUT PIO_STATUS_BLOCK IoStatusBlock,
58         ULONG ShareAccess,
59         ULONG OpenOptions)
60 {
61         ULONG len = 0;
62         PSTR filename;
63         CHAR szDosDevices[] = "\\DosDevices\\";
64         DOS_FULL_NAME full_name;
65         NTSTATUS r;
66
67         FIXME("(%p,0x%08lx,%p,%p,0x%08lx,0x%08lx) partial stub\n",
68                 FileHandle, DesiredAccess, ObjectAttributes,
69                 IoStatusBlock, ShareAccess, OpenOptions);
70
71         dump_ObjectAttributes (ObjectAttributes);
72
73         if(ObjectAttributes->RootDirectory)
74         {
75                 FIXME("Object root directory unknown %x\n",
76                         ObjectAttributes->RootDirectory);
77                 return STATUS_OBJECT_NAME_NOT_FOUND;
78         }
79
80         /* create an ascii string from the unicode filename */
81         RtlUnicodeToMultiByteSize( &len, ObjectAttributes->ObjectName->Buffer,
82                                 ObjectAttributes->ObjectName->Length );
83         filename = RtlAllocateHeap( GetProcessHeap(), 0, len + 1);
84         RtlUnicodeToMultiByteN(filename, len, NULL, ObjectAttributes->ObjectName->Buffer,
85                                 ObjectAttributes->ObjectName->Length );
86         filename[len]=0;
87
88         /* FIXME: DOSFS stuff should call here, not vice-versa */
89         if(strncmp(filename, szDosDevices, strlen(szDosDevices)))
90                 return STATUS_OBJECT_NAME_NOT_FOUND;
91
92         /* FIXME: this calls SetLastError() -> bad */
93         if(!DOSFS_GetFullName(&filename[strlen(szDosDevices)], TRUE,
94                                 &full_name))
95                 return STATUS_OBJECT_NAME_NOT_FOUND;
96
97         /* FIXME: modify server protocol so
98                   create file takes an OBJECT_ATTRIBUTES structure */
99         SERVER_START_REQ( create_file )
100         {
101             req->access     = DesiredAccess;
102             req->inherit    = 0;
103             req->sharing    = ShareAccess;
104             req->create     = OPEN_EXISTING;
105             req->attrs      = 0;
106             req->drive_type = GetDriveTypeA( full_name.short_name );
107             wine_server_add_data( req, full_name.long_name, strlen(full_name.long_name) );
108             SetLastError(0);
109             r = wine_server_call( req );
110             *FileHandle = reply->handle;
111         }
112         SERVER_END_REQ;
113
114         return r;
115 }
116
117 /**************************************************************************
118  *              NtCreateFile                            [NTDLL.@]
119  *              ZwCreateFile                            [NTDLL.@]
120  * FUNCTION: Either causes a new file or directory to be created, or it opens
121  *  an existing file, device, directory or volume, giving the caller a handle
122  *  for the file object. This handle can be used by subsequent calls to
123  *  manipulate data within the file or the file object's state of attributes.
124  * ARGUMENTS:
125  *      FileHandle              Points to a variable which receives the file handle on return
126  *      DesiredAccess           Desired access to the file
127  *      ObjectAttributes        Structure describing the file
128  *      IoStatusBlock           Receives information about the operation on return
129  *      AllocationSize          Initial size of the file in bytes
130  *      FileAttributes          Attributes to create the file with
131  *      ShareAccess             Type of shared access the caller would like to the file
132  *      CreateDisposition       Specifies what to do, depending on whether the file already exists
133  *      CreateOptions           Options for creating a new file
134  *      EaBuffer                Undocumented
135  *      EaLength                Undocumented
136  */
137 NTSTATUS WINAPI NtCreateFile(
138         OUT PHANDLE FileHandle,
139         ACCESS_MASK DesiredAccess,
140         POBJECT_ATTRIBUTES ObjectAttributes,
141         OUT PIO_STATUS_BLOCK IoStatusBlock,
142         PLARGE_INTEGER AllocateSize,
143         ULONG FileAttributes,
144         ULONG ShareAccess,
145         ULONG CreateDisposition,
146         ULONG CreateOptions,
147         PVOID EaBuffer,
148         ULONG EaLength)
149 {
150         FIXME("(%p,0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx) stub\n",
151         FileHandle,DesiredAccess,ObjectAttributes,
152         IoStatusBlock,AllocateSize,FileAttributes,
153         ShareAccess,CreateDisposition,CreateOptions,EaBuffer,EaLength);
154         dump_ObjectAttributes (ObjectAttributes);
155         return 0;
156 }
157
158 /* set the last error depending on errno */
159 NTSTATUS NTFILE_errno_to_status(int val)
160 {
161     switch (val)
162     {
163     case EAGAIN:    return ( STATUS_SHARING_VIOLATION );
164     case ESPIPE:
165     case EBADF:     return ( STATUS_INVALID_HANDLE );
166     case ENOSPC:    return ( STATUS_DISK_FULL );
167     case EACCES:
168     case ESRCH:
169     case EPERM:     return ( STATUS_ACCESS_DENIED );
170     case EROFS:     return ( STATUS_MEDIA_WRITE_PROTECTED );
171     case EBUSY:     return ( STATUS_FILE_LOCK_CONFLICT );
172     case ENOENT:    return ( STATUS_NO_SUCH_FILE );
173     case EISDIR:    return ( STATUS_FILE_IS_A_DIRECTORY );
174     case ENFILE:
175     case EMFILE:    return ( STATUS_NO_MORE_FILES );
176     case EEXIST:    return ( STATUS_OBJECT_NAME_COLLISION );
177     case EINVAL:    return ( STATUS_INVALID_PARAMETER );
178     case ENOTEMPTY: return ( STATUS_DIRECTORY_NOT_EMPTY );
179     case EIO:       return ( STATUS_ACCESS_VIOLATION );
180     }
181     perror("file_set_error");
182     return ( STATUS_INVALID_PARAMETER );
183 }
184
185
186 /******************************************************************************
187  *  NtReadFile                                  [NTDLL.@]
188  *  ZwReadFile                                  [NTDLL.@]
189  *
190  * Parameters
191  *   HANDLE32           FileHandle
192  *   HANDLE32           Event           OPTIONAL
193  *   PIO_APC_ROUTINE    ApcRoutine      OPTIONAL
194  *   PVOID              ApcContext      OPTIONAL
195  *   PIO_STATUS_BLOCK   IoStatusBlock
196  *   PVOID              Buffer
197  *   ULONG              Length
198  *   PLARGE_INTEGER     ByteOffset      OPTIONAL
199  *   PULONG             Key             OPTIONAL
200  *
201  * IoStatusBlock->Information contains the number of bytes read on return.
202  */
203 NTSTATUS WINAPI NtReadFile (
204         HANDLE FileHandle,
205         HANDLE EventHandle,
206         PIO_APC_ROUTINE ApcRoutine,
207         PVOID ApcContext,
208         PIO_STATUS_BLOCK IoStatusBlock,
209         PVOID Buffer,
210         ULONG Length,
211         PLARGE_INTEGER ByteOffset,
212         PULONG Key)
213 {
214         int fd, result, flags, ret;
215         enum fd_type type;
216
217         FIXME("(0x%08x,0x%08x,%p,%p,%p,%p,0x%08lx,%p,%p),partial stub!\n",
218                 FileHandle,EventHandle,ApcRoutine,ApcContext,IoStatusBlock,Buffer,Length,ByteOffset,Key);
219
220         if (IsBadWritePtr( Buffer, Length ) ||
221             IsBadWritePtr( IoStatusBlock, sizeof *IoStatusBlock) ||
222             IsBadWritePtr( ByteOffset, sizeof *ByteOffset) )
223                 return STATUS_ACCESS_VIOLATION;
224
225         IoStatusBlock->Information = 0;
226
227         ret = wine_server_handle_to_fd( FileHandle, GENERIC_READ, &fd, &type, &flags );
228         if(ret)
229                 return ret;
230
231         /* FIXME: this code only does synchronous reads so far */
232
233         /* FIXME: depending on how libc implements this, between two processes
234               there could be a race condition between the seek and read here */
235         do
236         {
237                 result = pread( fd, Buffer, Length, ByteOffset->QuadPart);
238         }
239         while ( (result == -1) && ((errno == EAGAIN) || (errno == EINTR)) );
240
241         close( fd );
242
243         if (result == -1)
244         {
245                 return IoStatusBlock->u.Status = NTFILE_errno_to_status(errno);
246         }
247
248         IoStatusBlock->Information = result;
249         IoStatusBlock->u.Status = 0;
250
251         return STATUS_SUCCESS;
252 }
253
254 /******************************************************************************
255  *  NtWriteFile                                 [NTDLL.@]
256  *  ZwWriteFile                                 [NTDLL.@]
257  *
258  * Parameters
259  *   HANDLE32           FileHandle
260  *   HANDLE32           Event           OPTIONAL
261  *   PIO_APC_ROUTINE    ApcRoutine      OPTIONAL
262  *   PVOID              ApcContext      OPTIONAL
263  *   PIO_STATUS_BLOCK   IoStatusBlock
264  *   PVOID              Buffer
265  *   ULONG              Length
266  *   PLARGE_INTEGER     ByteOffset      OPTIONAL
267  *   PULONG             Key             OPTIONAL
268  */
269 NTSTATUS WINAPI NtWriteFile (
270         HANDLE FileHandle,
271         HANDLE EventHandle,
272         PIO_APC_ROUTINE ApcRoutine,
273         PVOID ApcContext,
274         PIO_STATUS_BLOCK IoStatusBlock,
275         PVOID Buffer,
276         ULONG Length,
277         PLARGE_INTEGER ByteOffset,
278         PULONG Key)
279 {
280         FIXME("(0x%08x,0x%08x,%p,%p,%p,%p,0x%08lx,%p,%p),stub!\n",
281         FileHandle,EventHandle,ApcRoutine,ApcContext,IoStatusBlock,Buffer,Length,ByteOffset,Key);
282         return 0;
283 }
284
285 /**************************************************************************
286  *              NtDeviceIoControlFile                   [NTDLL.@]
287  *              ZwDeviceIoControlFile                   [NTDLL.@]
288  */
289 NTSTATUS WINAPI NtDeviceIoControlFile(
290         IN HANDLE DeviceHandle,
291         IN HANDLE Event OPTIONAL,
292         IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL,
293         IN PVOID UserApcContext OPTIONAL,
294         OUT PIO_STATUS_BLOCK IoStatusBlock,
295         IN ULONG IoControlCode,
296         IN PVOID InputBuffer,
297         IN ULONG InputBufferSize,
298         OUT PVOID OutputBuffer,
299         IN ULONG OutputBufferSize)
300 {
301         FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx): empty stub\n",
302         DeviceHandle, Event, UserApcRoutine, UserApcContext,
303         IoStatusBlock, IoControlCode, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize);
304         return 0;
305 }
306
307 /******************************************************************************
308  * NtFsControlFile [NTDLL.@]
309  * ZwFsControlFile [NTDLL.@]
310  */
311 NTSTATUS WINAPI NtFsControlFile(
312         IN HANDLE DeviceHandle,
313         IN HANDLE Event OPTIONAL,
314         IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
315         IN PVOID ApcContext OPTIONAL,
316         OUT PIO_STATUS_BLOCK IoStatusBlock,
317         IN ULONG IoControlCode,
318         IN PVOID InputBuffer,
319         IN ULONG InputBufferSize,
320         OUT PVOID OutputBuffer,
321         IN ULONG OutputBufferSize)
322 {
323         FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx): stub\n",
324         DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,IoControlCode,
325         InputBuffer,InputBufferSize,OutputBuffer,OutputBufferSize);
326         return 0;
327 }
328
329 /******************************************************************************
330  *  NtSetVolumeInformationFile          [NTDLL.@]
331  *  ZwSetVolumeInformationFile          [NTDLL.@]
332  */
333 NTSTATUS WINAPI NtSetVolumeInformationFile(
334         IN HANDLE FileHandle,
335         PIO_STATUS_BLOCK IoStatusBlock,
336         PVOID FsInformation,
337         ULONG Length,
338         FS_INFORMATION_CLASS FsInformationClass)
339 {
340         FIXME("(0x%08x,%p,%p,0x%08lx,0x%08x) stub\n",
341         FileHandle,IoStatusBlock,FsInformation,Length,FsInformationClass);
342         return 0;
343 }
344
345 /******************************************************************************
346  *  NtQueryInformationFile              [NTDLL.@]
347  *  ZwQueryInformationFile              [NTDLL.@]
348  */
349 NTSTATUS WINAPI NtQueryInformationFile(
350         HANDLE FileHandle,
351         PIO_STATUS_BLOCK IoStatusBlock,
352         PVOID FileInformation,
353         ULONG Length,
354         FILE_INFORMATION_CLASS FileInformationClass)
355 {
356         FIXME("(0x%08x,%p,%p,0x%08lx,0x%08x),stub!\n",
357         FileHandle,IoStatusBlock,FileInformation,Length,FileInformationClass);
358         return 0;
359 }
360
361 /******************************************************************************
362  *  NtSetInformationFile                [NTDLL.@]
363  *  ZwSetInformationFile                [NTDLL.@]
364  */
365 NTSTATUS WINAPI NtSetInformationFile(
366         HANDLE FileHandle,
367         PIO_STATUS_BLOCK IoStatusBlock,
368         PVOID FileInformation,
369         ULONG Length,
370         FILE_INFORMATION_CLASS FileInformationClass)
371 {
372         FIXME("(0x%08x,%p,%p,0x%08lx,0x%08x)\n",
373         FileHandle,IoStatusBlock,FileInformation,Length,FileInformationClass);
374         return 0;
375 }
376
377 /******************************************************************************
378  *  NtQueryDirectoryFile        [NTDLL.@]
379  *  ZwQueryDirectoryFile        [NTDLL.@]
380  *  ZwQueryDirectoryFile
381  */
382 NTSTATUS WINAPI NtQueryDirectoryFile(
383         IN HANDLE FileHandle,
384         IN HANDLE Event OPTIONAL,
385         IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
386         IN PVOID ApcContext OPTIONAL,
387         OUT PIO_STATUS_BLOCK IoStatusBlock,
388         OUT PVOID FileInformation,
389         IN ULONG Length,
390         IN FILE_INFORMATION_CLASS FileInformationClass,
391         IN BOOLEAN ReturnSingleEntry,
392         IN PUNICODE_STRING FileName OPTIONAL,
393         IN BOOLEAN RestartScan)
394 {
395         FIXME("(0x%08x 0x%08x %p %p %p %p 0x%08lx 0x%08x 0x%08x %p 0x%08x\n",
396         FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, FileInformation,
397         Length, FileInformationClass, ReturnSingleEntry,
398         debugstr_us(FileName),RestartScan);
399         return 0;
400 }
401
402 /******************************************************************************
403  *  NtQueryVolumeInformationFile                [NTDLL.@]
404  *  ZwQueryVolumeInformationFile                [NTDLL.@]
405  */
406 NTSTATUS WINAPI NtQueryVolumeInformationFile (
407         IN HANDLE FileHandle,
408         OUT PIO_STATUS_BLOCK IoStatusBlock,
409         OUT PVOID FSInformation,
410         IN ULONG Length,
411         IN FS_INFORMATION_CLASS FSInformationClass)
412 {
413         ULONG len = 0;
414
415         FIXME("(0x%08x %p %p 0x%08lx 0x%08x) stub!\n",
416         FileHandle, IoStatusBlock, FSInformation, Length, FSInformationClass);
417
418         switch ( FSInformationClass )
419         {
420           case FileFsVolumeInformation:
421             len = sizeof( FILE_FS_VOLUME_INFORMATION );
422             break;
423           case FileFsLabelInformation:
424             len = 0;
425             break;
426
427           case FileFsSizeInformation:
428             len = sizeof( FILE_FS_SIZE_INFORMATION );
429             break;
430
431           case FileFsDeviceInformation:
432             len = sizeof( FILE_FS_DEVICE_INFORMATION );
433             break;
434           case FileFsAttributeInformation:
435             len = sizeof( FILE_FS_ATTRIBUTE_INFORMATION );
436             break;
437
438           case FileFsControlInformation:
439             len = 0;
440             break;
441
442           case FileFsFullSizeInformation:
443             len = 0;
444             break;
445
446           case FileFsObjectIdInformation:
447             len = 0;
448             break;
449
450           case FileFsMaximumInformation:
451             len = 0;
452             break;
453         }
454
455         if (Length < len)
456           return STATUS_BUFFER_TOO_SMALL;
457
458         switch ( FSInformationClass )
459         {
460           case FileFsVolumeInformation:
461             break;
462           case FileFsLabelInformation:
463             break;
464
465           case FileFsSizeInformation:
466             break;
467
468           case FileFsDeviceInformation:
469             if (FSInformation)
470             {
471               FILE_FS_DEVICE_INFORMATION * DeviceInfo = FSInformation;
472               DeviceInfo->DeviceType = FILE_DEVICE_DISK;
473               DeviceInfo->Characteristics = 0;
474               break;
475             };
476           case FileFsAttributeInformation:
477             break;
478
479           case FileFsControlInformation:
480             break;
481
482           case FileFsFullSizeInformation:
483             break;
484
485           case FileFsObjectIdInformation:
486             break;
487
488           case FileFsMaximumInformation:
489             break;
490         }
491         IoStatusBlock->DUMMYUNIONNAME.Status = STATUS_SUCCESS;
492         IoStatusBlock->Information = len;
493         return STATUS_SUCCESS;
494 }