/[rdesktop]/jpeg/rdesktop/trunk/disk.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /jpeg/rdesktop/trunk/disk.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 597 - (hide annotations)
Thu Feb 5 15:41:56 2004 UTC (20 years, 3 months ago) by n-ki
Original Path: sourceforge.net/trunk/rdesktop/disk.c
File MIME type: text/plain
File size: 17349 byte(s)
add some defines. handle dirs first, otherwise we can not create dirs

1 n-ki 569 /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.
3     Disk Redirection
4     Copyright (C) Jeroen Meijer 2003
5    
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10    
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     GNU General Public License for more details.
15    
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     */
20    
21     #define FILE_ATTRIBUTE_READONLY 0x00000001
22     #define FILE_ATTRIBUTE_HIDDEN 0x00000002
23     #define FILE_ATTRIBUTE_SYSTEM 0x00000004
24     #define FILE_ATTRIBUTE_DIRECTORY 0x00000010
25     #define FILE_ATTRIBUTE_ARCHIVE 0x00000020
26     #define FILE_ATTRIBUTE_DEVICE 0x00000040
27 n-ki 597 #define FILE_ATTRIBUTE_UNKNOWNXXX0 0x00000060 /* ??? ACTION i.e. 0x860 == compress this file ? */
28 n-ki 569 #define FILE_ATTRIBUTE_NORMAL 0x00000080
29     #define FILE_ATTRIBUTE_TEMPORARY 0x00000100
30     #define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
31     #define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
32     #define FILE_ATTRIBUTE_COMPRESSED 0x00000800
33     #define FILE_ATTRIBUTE_OFFLINE 0x00001000
34     #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
35     #define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
36    
37 n-ki 597 #define FILE_FLAG_OPEN_NO_RECALL 0x00100000
38     #define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000
39     #define FILE_FLAG_POSIX_SEMANTICS 0x01000000
40     #define FILE_FLAG_BACKUP_SEMANTICS 0x02000000 /* sometimes used to create a directory */
41     #define FILE_FLAG_DELETE_ON_CLOSE 0x04000000
42     #define FILE_FLAG_SEQUENTIAL_SCAN 0x08000000
43     #define FILE_FLAG_RANDOM_ACCESS 0x10000000
44     #define FILE_FLAG_NO_BUFFERING 0x20000000
45     #define FILE_FLAG_OVERLAPPED 0x40000000
46     #define FILE_FLAG_WRITE_THROUGH 0x80000000
47    
48     #define FILE_SHARE_READ 0x01
49     #define FILE_SHARE_WRITE 0x02
50     #define FILE_SHARE_DELETE 0x04
51    
52 n-ki 569 #define FILE_BASIC_INFORMATION 0x04
53     #define FILE_STANDARD_INFORMATION 0x05
54    
55     #define FS_CASE_SENSITIVE 0x00000001
56     #define FS_CASE_IS_PRESERVED 0x00000002
57     #define FS_UNICODE_STORED_ON_DISK 0x00000004
58     #define FS_PERSISTENT_ACLS 0x00000008
59     #define FS_FILE_COMPRESSION 0x00000010
60     #define FS_VOLUME_QUOTAS 0x00000020
61     #define FS_SUPPORTS_SPARSE_FILES 0x00000040
62     #define FS_SUPPORTS_REPARSE_POINTS 0x00000080
63     #define FS_SUPPORTS_REMOTE_STORAGE 0X00000100
64     #define FS_VOL_IS_COMPRESSED 0x00008000
65     #define FILE_READ_ONLY_VOLUME 0x00080000
66    
67     #define OPEN_EXISTING 1
68     #define CREATE_NEW 2
69     #define OPEN_ALWAYS 3
70     #define TRUNCATE_EXISTING 4
71     #define CREATE_ALWAYS 5
72    
73     #define GENERIC_READ 0x80000000
74     #define GENERIC_WRITE 0x40000000
75     #define GENERIC_EXECUTE 0x20000000
76     #define GENERIC_ALL 0x10000000
77    
78     #define ERROR_FILE_NOT_FOUND 2L
79     #define ERROR_ALREADY_EXISTS 183L
80    
81     #define MAX_OPEN_FILES 0x100
82    
83 stargo 572 #if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
84     #define SOLARIS
85     #endif
86    
87     #ifdef SOLARIS
88     #define DIRFD(a) ((a)->dd_fd)
89     #else
90     #define DIRFD(a) (dirfd(a))
91     #endif
92    
93 n-ki 569 #include <sys/types.h>
94     #include <sys/stat.h>
95     #include <unistd.h>
96     #include <fcntl.h> /* open, close */
97     #include <dirent.h> /* opendir, closedir, readdir */
98     #include <fnmatch.h>
99     #include <errno.h> /* errno */
100 stargo 572
101 stargo 573 #if defined(SOLARIS)
102 stargo 572 #include <sys/statvfs.h> /* solaris statvfs */
103 stargo 574 #define STATFS_FN(path, buf) (statvfs(path,buf))
104     #define STATFS_T statvfs
105 stargo 573 #define F_NAMELEN(buf) ((buf).f_namemax)
106    
107 stargo 576 #elif (defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__))
108 stargo 573 #include <sys/param.h>
109     #include <sys/mount.h>
110 stargo 574 #define STATFS_FN(path, buf) (statfs(path,buf))
111     #define STATFS_T statfs
112 stargo 573 #define F_NAMELEN(buf) (NAME_MAX)
113    
114 stargo 572 #else
115     #include <sys/vfs.h> /* linux statfs */
116 stargo 574 #define STATFS_FN(path, buf) (statfs(path,buf))
117     #define STATFS_T statfs
118 stargo 573 #define F_NAMELEN(buf) ((buf).f_namelen)
119 stargo 572 #endif
120    
121 n-ki 569 #include "rdesktop.h"
122    
123     extern RDPDR_DEVICE g_rdpdr_device[];
124    
125     struct fileinfo
126     {
127     uint32 device_id, flags_and_attributes;
128     char path[256];
129     DIR *pdir;
130     struct dirent *pdirent;
131     char pattern[64];
132     BOOL delete_on_close;
133     }
134     g_fileinfo[MAX_OPEN_FILES];
135    
136     /* Convert seconds since 1970 to a filetime */
137     void
138     seconds_since_1970_to_filetime(time_t seconds, uint32 * high, uint32 * low)
139     {
140     unsigned long long ticks;
141    
142     ticks = (seconds + 11644473600LL) * 10000000;
143     *low = (uint32) ticks;
144     *high = (uint32) (ticks >> 32);
145     }
146    
147     /* Enumeration of devices from rdesktop.c */
148     /* returns numer of units found and initialized. */
149     /* optarg looks like ':h:=/mnt/floppy,b:=/mnt/usbdevice1' */
150     /* when it arrives to this function. */
151     int
152     disk_enum_devices(int *id, char *optarg)
153     {
154     char *pos = optarg;
155     char *pos2;
156     int count = 0;
157    
158     // skip the first colon
159     optarg++;
160     while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
161     {
162     pos2 = next_arg(optarg, '=');
163     strcpy(g_rdpdr_device[*id].name, optarg);
164    
165 stargo 570 toupper_str(g_rdpdr_device[*id].name);
166 n-ki 569
167     /* add trailing colon to name. */
168     strcat(g_rdpdr_device[*id].name, ":");
169    
170     g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
171     strcpy(g_rdpdr_device[*id].local_path, pos2);
172     printf("DISK %s to %s\n", g_rdpdr_device[*id].name, g_rdpdr_device[*id].local_path);
173     g_rdpdr_device[*id].device_type = DEVICE_TYPE_DISK;
174     count++;
175     (*id)++;
176    
177     optarg = pos;
178     }
179     return count;
180     }
181    
182 n-ki 596 /* Opens or creates a file or directory */
183 n-ki 569 NTSTATUS
184     disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
185     uint32 flags_and_attributes, char *filename, HANDLE * phandle)
186     {
187     HANDLE handle;
188     DIR *dirp;
189     int flags, mode;
190     char path[256];
191    
192     handle = 0;
193     dirp = NULL;
194     flags = 0;
195     mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
196    
197     if (filename[strlen(filename) - 1] == '/')
198     filename[strlen(filename) - 1] = 0;
199     sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);
200    
201     switch (create_disposition)
202     {
203     case CREATE_ALWAYS:
204    
205     // Delete existing file/link.
206     unlink(path);
207     flags |= O_CREAT;
208     break;
209    
210     case CREATE_NEW:
211    
212     // If the file already exists, then fail.
213     flags |= O_CREAT | O_EXCL;
214     break;
215    
216     case OPEN_ALWAYS:
217    
218     // Create if not already exists.
219     flags |= O_CREAT;
220     break;
221    
222     case OPEN_EXISTING:
223    
224     // Default behaviour
225     break;
226    
227     case TRUNCATE_EXISTING:
228    
229     // If the file does not exist, then fail.
230     flags |= O_TRUNC;
231     break;
232     }
233    
234 n-ki 597 //printf("Open: \"%s\" flags: %u, accessmask: %u sharemode: %u create disp: %u\n", path, flags_and_attributes, accessmask, sharemode, create_disposition);
235    
236     /* since we can't trust the FILE_DIRECTORY_FILE flag */
237     /* we need to double check that the file isn't a dir */
238     struct stat filestat;
239    
240     // Get information about file and set that flag ourselfs
241     if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))
242     flags_and_attributes |= FILE_DIRECTORY_FILE;
243    
244     if (flags_and_attributes & FILE_DIRECTORY_FILE)
245 n-ki 569 {
246 n-ki 597 if (flags & O_CREAT)
247 n-ki 569 {
248 n-ki 597 mkdir(path, mode);
249 n-ki 569 }
250    
251 n-ki 597 dirp = opendir(path);
252     if (!dirp)
253 n-ki 569 {
254     switch (errno)
255     {
256     case EACCES:
257    
258     return STATUS_ACCESS_DENIED;
259    
260     case ENOENT:
261    
262     return STATUS_NO_SUCH_FILE;
263    
264     default:
265    
266 n-ki 597 perror("opendir");
267 n-ki 569 return STATUS_NO_SUCH_FILE;
268     }
269     }
270 n-ki 597 handle = DIRFD(dirp);
271 n-ki 569 }
272 n-ki 597 else
273 n-ki 569 {
274 n-ki 596
275 n-ki 597 if (accessmask & GENERIC_ALL
276     || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE))
277 n-ki 569 {
278 n-ki 597 flags |= O_RDWR;
279 n-ki 569 }
280 n-ki 597 else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ))
281 n-ki 569 {
282 n-ki 597 flags |= O_WRONLY;
283 n-ki 569 }
284 n-ki 597 else
285     {
286     flags |= O_RDONLY;
287     }
288 n-ki 569
289 n-ki 597 handle = open(path, flags, mode);
290     if (handle == -1)
291 n-ki 569 {
292     switch (errno)
293     {
294     case EACCES:
295    
296     return STATUS_ACCESS_DENIED;
297    
298     case ENOENT:
299    
300     return STATUS_NO_SUCH_FILE;
301     default:
302    
303 n-ki 597 perror("open");
304 n-ki 569 return STATUS_NO_SUCH_FILE;
305     }
306     }
307 n-ki 597
308     /* all read and writes of files should be non blocking */
309     if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1)
310     perror("fcntl");
311 n-ki 569 }
312    
313     if (handle >= MAX_OPEN_FILES)
314     {
315     error("Maximum number of open files (%s) reached. Increase MAX_OPEN_FILES!\n",
316     handle);
317     exit(1);
318     }
319    
320     if (dirp)
321     g_fileinfo[handle].pdir = dirp;
322     g_fileinfo[handle].device_id = device_id;
323     g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
324     strncpy(g_fileinfo[handle].path, path, 255);
325    
326     *phandle = handle;
327     return STATUS_SUCCESS;
328     }
329    
330     NTSTATUS
331     disk_close(HANDLE handle)
332     {
333     struct fileinfo *pfinfo;
334    
335     pfinfo = &(g_fileinfo[handle]);
336    
337     if (pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE)
338     {
339     closedir(pfinfo->pdir);
340     //FIXME: Should check exit code
341     }
342     else
343     {
344     close(handle);
345     }
346    
347     return STATUS_SUCCESS;
348     }
349    
350     NTSTATUS
351     disk_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
352     {
353     int n;
354    
355 n-ki 596 /* browsing dir ???? */
356     /* each request is 24 bytes */
357     if (g_fileinfo[handle].flags_and_attributes & FILE_DIRECTORY_FILE)
358     {
359     *result = 0;
360     return STATUS_SUCCESS;
361     }
362    
363 n-ki 569 if (offset)
364     lseek(handle, offset, SEEK_SET);
365     n = read(handle, data, length);
366    
367     if (n < 0)
368     {
369     perror("read");
370     *result = 0;
371     return STATUS_INVALID_PARAMETER;
372     }
373    
374     *result = n;
375    
376     return STATUS_SUCCESS;
377     }
378    
379     NTSTATUS
380     disk_write(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
381     {
382     int n;
383    
384     if (offset)
385     lseek(handle, offset, SEEK_SET);
386    
387     n = write(handle, data, length);
388    
389     if (n < 0)
390     {
391     perror("write");
392     *result = 0;
393     return STATUS_ACCESS_DENIED;
394     }
395    
396     *result = n;
397    
398     return STATUS_SUCCESS;
399     }
400    
401     NTSTATUS
402     disk_query_information(HANDLE handle, uint32 info_class, STREAM out)
403     {
404     uint32 file_attributes, ft_high, ft_low;
405     struct stat filestat;
406     char *path, *filename;
407    
408     path = g_fileinfo[handle].path;
409    
410     // Get information about file
411     if (fstat(handle, &filestat) != 0)
412     {
413     perror("stat");
414     out_uint8(out, 0);
415     return STATUS_ACCESS_DENIED;
416     }
417    
418     // Set file attributes
419     file_attributes = 0;
420     if (S_ISDIR(filestat.st_mode))
421     {
422     file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
423     }
424     filename = 1 + strrchr(path, '/');
425     if (filename && filename[0] == '.')
426     {
427     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
428     }
429    
430     // Return requested data
431     switch (info_class)
432     {
433     case 4: /* FileBasicInformation */
434    
435     out_uint8s(out, 8); //create_time not available;
436    
437     seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
438     out_uint32_le(out, ft_low); //last_access_time
439     out_uint32_le(out, ft_high);
440    
441     seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
442     out_uint32_le(out, ft_low); //last_write_time
443     out_uint32_le(out, ft_high);
444    
445     out_uint8s(out, 8); //unknown zero
446     out_uint32_le(out, file_attributes);
447     break;
448    
449     case 5: /* FileStandardInformation */
450    
451     out_uint32_le(out, filestat.st_size); //Allocation size
452     out_uint32_le(out, 0);
453     out_uint32_le(out, filestat.st_size); //End of file
454     out_uint32_le(out, 0);
455     out_uint32_le(out, filestat.st_nlink); //Number of links
456     out_uint8(out, 0); //Delete pending
457     out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0); //Directory
458     break;
459    
460     case 35: /* FileObjectIdInformation */
461    
462     out_uint32_le(out, file_attributes); /* File Attributes */
463     out_uint32_le(out, 0); /* Reparse Tag */
464     break;
465    
466     default:
467    
468     unimpl("IRP Query (File) Information class: 0x%x\n", info_class);
469     return STATUS_INVALID_PARAMETER;
470     }
471     return STATUS_SUCCESS;
472     }
473    
474     NTSTATUS
475     disk_set_information(HANDLE handle, uint32 info_class, STREAM in, STREAM out)
476     {
477     uint32 device_id, length, file_attributes, ft_high, ft_low;
478     char newname[256], fullpath[256];
479     struct fileinfo *pfinfo;
480    
481     pfinfo = &(g_fileinfo[handle]);
482    
483     switch (info_class)
484     {
485     case 4: /* FileBasicInformation */
486    
487     // Probably safe to ignore
488     break;
489    
490     case 10: /* FileRenameInformation */
491    
492     in_uint8s(in, 4); /* Handle of root dir? */
493     in_uint8s(in, 0x1a); /* unknown */
494     in_uint32_le(in, length);
495    
496     if (length && (length / 2) < 256)
497     {
498     rdp_in_unistr(in, newname, length);
499     convert_to_unix_filename(newname);
500     }
501     else
502     {
503     return STATUS_INVALID_PARAMETER;
504     }
505    
506     sprintf(fullpath, "%s%s", g_rdpdr_device[pfinfo->device_id].local_path,
507     newname);
508    
509     if (rename(pfinfo->path, fullpath) != 0)
510     {
511     perror("rename");
512     return STATUS_ACCESS_DENIED;
513     }
514     break;
515    
516     case 13: /* FileDispositionInformation */
517    
518     //unimpl("IRP Set File Information class: FileDispositionInformation\n");
519     // in_uint32_le(in, delete_on_close);
520     // disk_close(handle);
521     unlink(pfinfo->path);
522     break;
523    
524     case 19: /* FileAllocationInformation */
525    
526     unimpl("IRP Set File Information class: FileAllocationInformation\n");
527     break;
528    
529     case 20: /* FileEndOfFileInformation */
530    
531     unimpl("IRP Set File Information class: FileEndOfFileInformation\n");
532     break;
533    
534     default:
535    
536     unimpl("IRP Set File Information class: 0x%x\n", info_class);
537     return STATUS_INVALID_PARAMETER;
538     }
539     return STATUS_SUCCESS;
540     }
541    
542     NTSTATUS
543     disk_query_volume_information(HANDLE handle, uint32 info_class, STREAM out)
544     {
545     char *volume, *fs_type;
546 stargo 574 struct STATFS_T stat_fs;
547 n-ki 569 struct fileinfo *pfinfo;
548    
549     pfinfo = &(g_fileinfo[handle]);
550     volume = "RDESKTOP";
551     fs_type = "RDPFS";
552    
553 stargo 574 if (STATFS_FN(pfinfo->path, &stat_fs) != 0) /* FIXME: statfs is not portable */
554 n-ki 569 {
555     perror("statfs");
556     return STATUS_ACCESS_DENIED;
557     }
558    
559     switch (info_class)
560     {
561     case 1: /* FileFsVolumeInformation */
562    
563     out_uint32_le(out, 0); /* volume creation time low */
564     out_uint32_le(out, 0); /* volume creation time high */
565     out_uint32_le(out, 0); /* serial */
566     out_uint32_le(out, 2 * strlen(volume)); /* length of string */
567     out_uint8(out, 0); /* support objects? */
568     rdp_out_unistr(out, volume, 2 * strlen(volume) - 2);
569     break;
570    
571     case 3: /* FileFsSizeInformation */
572    
573     out_uint32_le(out, stat_fs.f_blocks); /* Total allocation units low */
574     out_uint32_le(out, 0); /* Total allocation high units */
575     out_uint32_le(out, stat_fs.f_bfree); /* Available allocation units */
576     out_uint32_le(out, 0); /* Available allowcation units */
577     out_uint32_le(out, stat_fs.f_bsize / 0x200); /* Sectors per allocation unit */
578     out_uint32_le(out, 0x200); /* Bytes per sector */
579     break;
580    
581     case 5: /* FileFsAttributeInformation */
582    
583     out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */
584 stargo 574 out_uint32_le(out, F_NAMELEN(stat_fs)); /* max length of filename */
585 n-ki 569 out_uint32_le(out, 2 * strlen(fs_type)); /* length of fs_type */
586     rdp_out_unistr(out, fs_type, 2 * strlen(fs_type) - 2);
587     break;
588    
589     case 2: /* FileFsLabelInformation */
590     case 4: /* FileFsDeviceInformation */
591     case 6: /* FileFsControlInformation */
592     case 7: /* FileFsFullSizeInformation */
593     case 8: /* FileFsObjectIdInformation */
594     case 9: /* FileFsMaximumInformation */
595     default:
596    
597     unimpl("IRP Query Volume Information class: 0x%x\n", info_class);
598     return STATUS_INVALID_PARAMETER;
599     }
600     return STATUS_SUCCESS;
601     }
602    
603     NTSTATUS
604     disk_query_directory(HANDLE handle, uint32 info_class, char *pattern, STREAM out)
605     {
606     uint32 file_attributes, ft_low, ft_high;
607     char *dirname, fullpath[256];
608     DIR *pdir;
609     struct dirent *pdirent;
610     struct stat fstat;
611     struct fileinfo *pfinfo;
612    
613     pfinfo = &(g_fileinfo[handle]);
614     pdir = pfinfo->pdir;
615     dirname = pfinfo->path;
616     file_attributes = 0;
617    
618     switch (info_class)
619     {
620     case 3: //FIXME: Why 3?
621    
622     // If a search pattern is received, remember this pattern, and restart search
623     if (pattern[0] != 0)
624     {
625     strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), 64);
626     rewinddir(pdir);
627     }
628    
629     // find next dirent matching pattern
630     pdirent = readdir(pdir);
631     while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)
632     {
633     pdirent = readdir(pdir);
634     }
635    
636     if (pdirent == NULL)
637     {
638     return STATUS_NO_MORE_FILES;
639     }
640    
641     // Get information for directory entry
642     sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
643 n-ki 596 /* JIF
644 n-ki 569 printf("Stat: %s\n", fullpath); */
645     if (stat(fullpath, &fstat))
646     {
647     perror("stat");
648     out_uint8(out, 0);
649     return STATUS_ACCESS_DENIED;
650     }
651    
652     if (S_ISDIR(fstat.st_mode))
653     file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
654     if (pdirent->d_name[0] == '.')
655     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
656    
657     // Return requested information
658     out_uint8s(out, 8); //unknown zero
659     out_uint8s(out, 8); //create_time not available in posix;
660    
661     seconds_since_1970_to_filetime(fstat.st_atime, &ft_high, &ft_low);
662     out_uint32_le(out, ft_low); //last_access_time
663     out_uint32_le(out, ft_high);
664    
665     seconds_since_1970_to_filetime(fstat.st_mtime, &ft_high, &ft_low);
666     out_uint32_le(out, ft_low); //last_write_time
667     out_uint32_le(out, ft_high);
668    
669     out_uint8s(out, 8); //unknown zero
670     out_uint32_le(out, fstat.st_size); //filesize low
671     out_uint32_le(out, 0); //filesize high
672     out_uint32_le(out, fstat.st_size); //filesize low
673     out_uint32_le(out, 0); //filesize high
674     out_uint32_le(out, file_attributes);
675     out_uint8(out, 2 * strlen(pdirent->d_name) + 2); //unicode length
676     out_uint8s(out, 7); //pad?
677     out_uint8(out, 0); //8.3 file length
678     out_uint8s(out, 2 * 12); //8.3 unicode length
679     rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
680     break;
681    
682     default:
683    
684     unimpl("IRP Query Directory sub: 0x%x\n", info_class);
685     return STATUS_INVALID_PARAMETER;
686     }
687    
688     return STATUS_SUCCESS;
689     }
690    
691     DEVICE_FNS disk_fns = {
692     disk_create,
693     disk_close,
694     disk_read,
695     disk_write,
696     NULL /* device_control */
697     };

  ViewVC Help
Powered by ViewVC 1.1.26