Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 1 | /* |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 2 | * DOS drives handling functions |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 3 | * |
| 4 | * Copyright 1993 Erik Bos |
| 5 | * Copyright 1996 Alexandre Julliard |
| 6 | */ |
| 7 | |
Alexandre Julliard | 2d93d00 | 1996-05-21 15:01:41 +0000 | [diff] [blame] | 8 | #include <ctype.h> |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 9 | #include <string.h> |
| 10 | #include <stdlib.h> |
Alexandre Julliard | 0c126c7 | 1996-02-18 18:44:41 +0000 | [diff] [blame] | 11 | #include <sys/types.h> |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 12 | #include <sys/stat.h> |
| 13 | |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 14 | #if defined(__linux__) || defined(sun) || defined(hpux) |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 15 | #include <sys/vfs.h> |
| 16 | #endif |
| 17 | #if defined(__NetBSD__) || defined(__FreeBSD__) |
| 18 | #include <sys/param.h> |
| 19 | #include <sys/mount.h> |
| 20 | #include <sys/errno.h> |
| 21 | #endif |
Alexandre Julliard | 8664b89 | 1996-04-05 14:58:24 +0000 | [diff] [blame] | 22 | #if defined(__svr4__) || defined(_SCO_DS) |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 23 | #include <sys/statfs.h> |
| 24 | #endif |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 25 | |
| 26 | #include "windows.h" |
Alexandre Julliard | 339eefc | 1996-06-23 14:56:20 +0000 | [diff] [blame] | 27 | #include "winbase.h" |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 28 | #include "drive.h" |
| 29 | #include "file.h" |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 30 | #include "heap.h" |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 31 | #include "msdos.h" |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 32 | #include "options.h" |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 33 | #include "task.h" |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 34 | #include "stddebug.h" |
| 35 | #include "debug.h" |
| 36 | |
| 37 | typedef struct |
| 38 | { |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 39 | char *root; /* root dir in Unix format without trailing / */ |
| 40 | char *dos_cwd; /* cwd in DOS format without leading or trailing \ */ |
| 41 | char *unix_cwd; /* cwd in Unix format without leading or trailing / */ |
| 42 | char label[12]; /* drive label */ |
| 43 | DWORD serial; /* drive serial number */ |
| 44 | DRIVETYPE type; /* drive type */ |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 45 | UINT32 flags; /* drive flags */ |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 46 | } DOSDRIVE; |
| 47 | |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 48 | |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 49 | static const char * const DRIVE_Types[] = |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 50 | { |
| 51 | "floppy", /* TYPE_FLOPPY */ |
| 52 | "hd", /* TYPE_HD */ |
| 53 | "cdrom", /* TYPE_CDROM */ |
| 54 | "network" /* TYPE_NETWORK */ |
| 55 | }; |
| 56 | |
| 57 | |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 58 | /* Known filesystem types */ |
| 59 | |
| 60 | typedef struct |
| 61 | { |
| 62 | const char *name; |
| 63 | UINT32 flags; |
| 64 | } FS_DESCR; |
| 65 | |
| 66 | static const FS_DESCR DRIVE_Filesystems[] = |
| 67 | { |
| 68 | { "unix", DRIVE_CASE_SENSITIVE | DRIVE_CASE_PRESERVING }, |
| 69 | { "msdos", DRIVE_SHORT_NAMES }, |
| 70 | { "dos", DRIVE_SHORT_NAMES }, |
| 71 | { "fat", DRIVE_SHORT_NAMES }, |
| 72 | { "vfat", DRIVE_CASE_PRESERVING }, |
| 73 | { "win95", DRIVE_CASE_PRESERVING }, |
| 74 | { NULL, 0 } |
| 75 | }; |
| 76 | |
| 77 | |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 78 | static DOSDRIVE DOSDrives[MAX_DOS_DRIVES]; |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 79 | static int DRIVE_CurDrive = -1; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 80 | |
Alexandre Julliard | bf9130a | 1996-10-13 17:45:47 +0000 | [diff] [blame] | 81 | static HTASK16 DRIVE_LastTask = 0; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 82 | |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 83 | |
| 84 | /*********************************************************************** |
| 85 | * DRIVE_GetDriveType |
| 86 | */ |
| 87 | static DRIVETYPE DRIVE_GetDriveType( const char *name ) |
| 88 | { |
| 89 | char buffer[20]; |
| 90 | int i; |
| 91 | |
| 92 | PROFILE_GetWineIniString( name, "Type", "hd", buffer, sizeof(buffer) ); |
| 93 | for (i = 0; i < sizeof(DRIVE_Types)/sizeof(DRIVE_Types[0]); i++) |
| 94 | { |
Alexandre Julliard | d90840e | 1996-06-11 16:02:08 +0000 | [diff] [blame] | 95 | if (!lstrcmpi32A( buffer, DRIVE_Types[i] )) return (DRIVETYPE)i; |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 96 | } |
| 97 | fprintf( stderr, "%s: unknown type '%s', defaulting to 'hd'.\n", |
| 98 | name, buffer ); |
| 99 | return TYPE_HD; |
| 100 | } |
| 101 | |
| 102 | |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 103 | /*********************************************************************** |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 104 | * DRIVE_GetFSFlags |
| 105 | */ |
| 106 | static UINT32 DRIVE_GetFSFlags( const char *name, const char *value ) |
| 107 | { |
| 108 | const FS_DESCR *descr; |
| 109 | |
| 110 | for (descr = DRIVE_Filesystems; descr->name; descr++) |
| 111 | if (!lstrcmpi32A( value, descr->name )) return descr->flags; |
| 112 | fprintf( stderr, "%s: unknown filesystem type '%s', defaulting to 'unix'.\n", |
| 113 | name, value ); |
| 114 | return DRIVE_CASE_SENSITIVE | DRIVE_CASE_PRESERVING; |
| 115 | } |
| 116 | |
| 117 | |
| 118 | /*********************************************************************** |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 119 | * DRIVE_Init |
| 120 | */ |
| 121 | int DRIVE_Init(void) |
| 122 | { |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 123 | int i, len, count = 0; |
| 124 | char name[] = "Drive A"; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 125 | char path[MAX_PATHNAME_LEN]; |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 126 | char buffer[20]; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 127 | char *p; |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 128 | DOSDRIVE *drive; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 129 | |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 130 | for (i = 0, drive = DOSDrives; i < MAX_DOS_DRIVES; i++, name[6]++, drive++) |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 131 | { |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 132 | PROFILE_GetWineIniString( name, "Path", "", path, sizeof(path)-1 ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 133 | if (path[0]) |
| 134 | { |
| 135 | p = path + strlen(path) - 1; |
| 136 | while ((p > path) && ((*p == '/') || (*p == '\\'))) *p-- = '\0'; |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 137 | if (strlen(path)) |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 138 | drive->root = HEAP_strdupA( SystemHeap, 0, path ); |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 139 | else |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 140 | drive->root = HEAP_strdupA( SystemHeap, 0, "/" ); |
| 141 | drive->dos_cwd = HEAP_strdupA( SystemHeap, 0, "" ); |
| 142 | drive->unix_cwd = HEAP_strdupA( SystemHeap, 0, "" ); |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 143 | drive->type = DRIVE_GetDriveType( name ); |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 144 | drive->flags = 0; |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 145 | |
| 146 | /* Get the drive label */ |
| 147 | PROFILE_GetWineIniString( name, "Label", name, drive->label, 12 ); |
| 148 | if ((len = strlen(drive->label)) < 11) |
| 149 | { |
| 150 | /* Pad label with spaces */ |
| 151 | memset( drive->label + len, ' ', 11 - len ); |
| 152 | drive->label[12] = '\0'; |
| 153 | } |
| 154 | |
| 155 | /* Get the serial number */ |
| 156 | PROFILE_GetWineIniString( name, "Serial", "12345678", |
| 157 | buffer, sizeof(buffer) ); |
| 158 | drive->serial = strtoul( buffer, NULL, 16 ); |
| 159 | |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 160 | /* Get the filesystem type */ |
| 161 | PROFILE_GetWineIniString( name, "Filesystem", "unix", |
| 162 | buffer, sizeof(buffer) ); |
| 163 | drive->flags = DRIVE_GetFSFlags( name, buffer ); |
| 164 | |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 165 | /* Make the first hard disk the current drive */ |
| 166 | if ((DRIVE_CurDrive == -1) && (drive->type == TYPE_HD)) |
| 167 | DRIVE_CurDrive = i; |
| 168 | |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 169 | count++; |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 170 | dprintf_dosfs( stddeb, "%s: path=%s type=%s label='%s' serial=%08lx flags=%08x\n", |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 171 | name, path, DRIVE_Types[drive->type], |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 172 | drive->label, drive->serial, drive->flags ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 173 | } |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 174 | else dprintf_dosfs( stddeb, "%s: not defined\n", name ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 175 | } |
| 176 | |
| 177 | if (!count) |
| 178 | { |
Alexandre Julliard | 0c126c7 | 1996-02-18 18:44:41 +0000 | [diff] [blame] | 179 | fprintf( stderr, "Warning: no valid DOS drive found, check your configuration file.\n" ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 180 | /* Create a C drive pointing to Unix root dir */ |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 181 | DOSDrives[2].root = HEAP_strdupA( SystemHeap, 0, "/" ); |
| 182 | DOSDrives[2].dos_cwd = HEAP_strdupA( SystemHeap, 0, "" ); |
| 183 | DOSDrives[2].unix_cwd = HEAP_strdupA( SystemHeap, 0, "" ); |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 184 | strcpy( DOSDrives[2].label, "Drive C " ); |
| 185 | DOSDrives[2].serial = 0x12345678; |
| 186 | DOSDrives[2].type = TYPE_HD; |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 187 | DOSDrives[2].flags = 0; |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 188 | DRIVE_CurDrive = 2; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 189 | } |
| 190 | |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 191 | /* Make sure the current drive is valid */ |
| 192 | if (DRIVE_CurDrive == -1) |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 193 | { |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 194 | for (i = 0, drive = DOSDrives; i < MAX_DOS_DRIVES; i++, drive++) |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 195 | { |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 196 | if (drive->root && !(drive->flags & DRIVE_DISABLED)) |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 197 | { |
| 198 | DRIVE_CurDrive = i; |
| 199 | break; |
| 200 | } |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 201 | } |
| 202 | } |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 203 | |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 204 | return 1; |
| 205 | } |
| 206 | |
| 207 | |
| 208 | /*********************************************************************** |
| 209 | * DRIVE_IsValid |
| 210 | */ |
| 211 | int DRIVE_IsValid( int drive ) |
| 212 | { |
| 213 | if ((drive < 0) || (drive >= MAX_DOS_DRIVES)) return 0; |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 214 | return (DOSDrives[drive].root && |
| 215 | !(DOSDrives[drive].flags & DRIVE_DISABLED)); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 216 | } |
| 217 | |
| 218 | |
| 219 | /*********************************************************************** |
| 220 | * DRIVE_GetCurrentDrive |
| 221 | */ |
| 222 | int DRIVE_GetCurrentDrive(void) |
| 223 | { |
Alexandre Julliard | 1285c2f | 1996-05-06 16:06:24 +0000 | [diff] [blame] | 224 | TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 225 | if (pTask && (pTask->curdrive & 0x80)) return pTask->curdrive & ~0x80; |
| 226 | return DRIVE_CurDrive; |
| 227 | } |
| 228 | |
| 229 | |
| 230 | /*********************************************************************** |
| 231 | * DRIVE_SetCurrentDrive |
| 232 | */ |
| 233 | int DRIVE_SetCurrentDrive( int drive ) |
| 234 | { |
Alexandre Julliard | 1285c2f | 1996-05-06 16:06:24 +0000 | [diff] [blame] | 235 | TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 236 | if (!DRIVE_IsValid( drive )) |
| 237 | { |
| 238 | DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); |
| 239 | return 0; |
| 240 | } |
| 241 | dprintf_dosfs( stddeb, "DRIVE_SetCurrentDrive: %c:\n", 'A' + drive ); |
| 242 | DRIVE_CurDrive = drive; |
| 243 | if (pTask) pTask->curdrive = drive | 0x80; |
| 244 | return 1; |
| 245 | } |
| 246 | |
| 247 | |
| 248 | /*********************************************************************** |
| 249 | * DRIVE_FindDriveRoot |
| 250 | * |
| 251 | * Find a drive for which the root matches the begginning of the given path. |
| 252 | * This can be used to translate a Unix path into a drive + DOS path. |
| 253 | * Return value is the drive, or -1 on error. On success, path is modified |
| 254 | * to point to the beginning of the DOS path. |
| 255 | * FIXME: this only does a textual comparison of the path names, and won't |
| 256 | * work well in the presence of symbolic links. |
| 257 | */ |
| 258 | int DRIVE_FindDriveRoot( const char **path ) |
| 259 | { |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 260 | int drive, rootdrive = -1; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 261 | const char *p1, *p2; |
| 262 | |
| 263 | dprintf_dosfs( stddeb, "DRIVE_FindDriveRoot: searching '%s'\n", *path ); |
| 264 | for (drive = 0; drive < MAX_DOS_DRIVES; drive++) |
| 265 | { |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 266 | if (!DOSDrives[drive].root || |
| 267 | (DOSDrives[drive].flags & DRIVE_DISABLED)) continue; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 268 | p1 = *path; |
| 269 | p2 = DOSDrives[drive].root; |
| 270 | dprintf_dosfs( stddeb, "DRIVE_FindDriveRoot: checking %c: '%s'\n", |
| 271 | 'A' + drive, p2 ); |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 272 | |
| 273 | while (*p2 == '/') p2++; |
| 274 | if (!*p2) |
| 275 | { |
| 276 | rootdrive = drive; |
| 277 | continue; /* Look if there's a better match */ |
| 278 | } |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 279 | for (;;) |
| 280 | { |
| 281 | while ((*p1 == '\\') || (*p1 == '/')) p1++; |
| 282 | while (*p2 == '/') p2++; |
| 283 | while ((*p1 == *p2) && (*p2) && (*p2 != '/')) p1++, p2++; |
| 284 | if (!*p2) |
| 285 | { |
| 286 | if (IS_END_OF_NAME(*p1)) /* OK, found it */ |
| 287 | { |
| 288 | *path = p1; |
| 289 | return drive; |
| 290 | } |
| 291 | } |
| 292 | else if (*p2 == '/') |
| 293 | { |
| 294 | if (IS_END_OF_NAME(*p1)) |
| 295 | continue; /* Go to next path element */ |
| 296 | } |
| 297 | break; /* No match, go to next drive */ |
| 298 | } |
| 299 | } |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 300 | return rootdrive; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 301 | } |
| 302 | |
| 303 | |
| 304 | /*********************************************************************** |
| 305 | * DRIVE_GetRoot |
| 306 | */ |
| 307 | const char * DRIVE_GetRoot( int drive ) |
| 308 | { |
| 309 | if (!DRIVE_IsValid( drive )) return NULL; |
| 310 | return DOSDrives[drive].root; |
| 311 | } |
| 312 | |
| 313 | |
| 314 | /*********************************************************************** |
| 315 | * DRIVE_GetDosCwd |
| 316 | */ |
| 317 | const char * DRIVE_GetDosCwd( int drive ) |
| 318 | { |
Alexandre Julliard | 1285c2f | 1996-05-06 16:06:24 +0000 | [diff] [blame] | 319 | TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 320 | if (!DRIVE_IsValid( drive )) return NULL; |
| 321 | |
| 322 | /* Check if we need to change the directory to the new task. */ |
| 323 | if (pTask && (pTask->curdrive & 0x80) && /* The task drive is valid */ |
| 324 | ((pTask->curdrive & ~0x80) == drive) && /* and it's the one we want */ |
| 325 | (DRIVE_LastTask != GetCurrentTask())) /* and the task changed */ |
| 326 | { |
| 327 | /* Perform the task-switch */ |
| 328 | if (!DRIVE_Chdir( drive, pTask->curdir )) DRIVE_Chdir( drive, "\\" ); |
| 329 | DRIVE_LastTask = GetCurrentTask(); |
| 330 | } |
| 331 | return DOSDrives[drive].dos_cwd; |
| 332 | } |
| 333 | |
| 334 | |
| 335 | /*********************************************************************** |
| 336 | * DRIVE_GetUnixCwd |
| 337 | */ |
| 338 | const char * DRIVE_GetUnixCwd( int drive ) |
| 339 | { |
Alexandre Julliard | 1285c2f | 1996-05-06 16:06:24 +0000 | [diff] [blame] | 340 | TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 341 | if (!DRIVE_IsValid( drive )) return NULL; |
| 342 | |
| 343 | /* Check if we need to change the directory to the new task. */ |
| 344 | if (pTask && (pTask->curdrive & 0x80) && /* The task drive is valid */ |
| 345 | ((pTask->curdrive & ~0x80) == drive) && /* and it's the one we want */ |
| 346 | (DRIVE_LastTask != GetCurrentTask())) /* and the task changed */ |
| 347 | { |
| 348 | /* Perform the task-switch */ |
| 349 | if (!DRIVE_Chdir( drive, pTask->curdir )) DRIVE_Chdir( drive, "\\" ); |
| 350 | DRIVE_LastTask = GetCurrentTask(); |
| 351 | } |
| 352 | return DOSDrives[drive].unix_cwd; |
| 353 | } |
| 354 | |
| 355 | |
| 356 | /*********************************************************************** |
| 357 | * DRIVE_GetLabel |
| 358 | */ |
| 359 | const char * DRIVE_GetLabel( int drive ) |
| 360 | { |
| 361 | if (!DRIVE_IsValid( drive )) return NULL; |
| 362 | return DOSDrives[drive].label; |
| 363 | } |
| 364 | |
| 365 | |
| 366 | /*********************************************************************** |
| 367 | * DRIVE_GetSerialNumber |
| 368 | */ |
| 369 | DWORD DRIVE_GetSerialNumber( int drive ) |
| 370 | { |
| 371 | if (!DRIVE_IsValid( drive )) return 0; |
| 372 | return DOSDrives[drive].serial; |
| 373 | } |
| 374 | |
| 375 | |
| 376 | /*********************************************************************** |
| 377 | * DRIVE_SetSerialNumber |
| 378 | */ |
| 379 | int DRIVE_SetSerialNumber( int drive, DWORD serial ) |
| 380 | { |
| 381 | if (!DRIVE_IsValid( drive )) return 0; |
| 382 | DOSDrives[drive].serial = serial; |
| 383 | return 1; |
| 384 | } |
| 385 | |
| 386 | |
| 387 | /*********************************************************************** |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 388 | * DRIVE_GetType |
| 389 | */ |
| 390 | DRIVETYPE DRIVE_GetType( int drive ) |
| 391 | { |
| 392 | if (!DRIVE_IsValid( drive )) return TYPE_INVALID; |
| 393 | return DOSDrives[drive].type; |
| 394 | } |
| 395 | |
| 396 | |
| 397 | /*********************************************************************** |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 398 | * DRIVE_GetFlags |
| 399 | */ |
| 400 | UINT32 DRIVE_GetFlags( int drive ) |
| 401 | { |
| 402 | if ((drive < 0) || (drive >= MAX_DOS_DRIVES)) return 0; |
| 403 | return DOSDrives[drive].flags; |
| 404 | } |
| 405 | |
| 406 | |
| 407 | /*********************************************************************** |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 408 | * DRIVE_Chdir |
| 409 | */ |
| 410 | int DRIVE_Chdir( int drive, const char *path ) |
| 411 | { |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame^] | 412 | DOS_FULL_NAME full_name; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 413 | char buffer[MAX_PATHNAME_LEN]; |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame^] | 414 | LPSTR unix_cwd; |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 415 | BY_HANDLE_FILE_INFORMATION info; |
Alexandre Julliard | 1285c2f | 1996-05-06 16:06:24 +0000 | [diff] [blame] | 416 | TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 417 | |
| 418 | dprintf_dosfs( stddeb, "DRIVE_Chdir(%c:,%s)\n", 'A' + drive, path ); |
| 419 | strcpy( buffer, "A:" ); |
| 420 | buffer[0] += drive; |
Alexandre Julliard | d90840e | 1996-06-11 16:02:08 +0000 | [diff] [blame] | 421 | lstrcpyn32A( buffer + 2, path, sizeof(buffer) - 2 ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 422 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame^] | 423 | if (!DOSFS_GetFullName( buffer, TRUE, &full_name )) return 0; |
| 424 | if (!FILE_Stat( full_name.long_name, &info )) return 0; |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 425 | if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 426 | { |
| 427 | DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk ); |
| 428 | return 0; |
| 429 | } |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame^] | 430 | unix_cwd = full_name.long_name + strlen( DOSDrives[drive].root ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 431 | while (*unix_cwd == '/') unix_cwd++; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 432 | |
| 433 | dprintf_dosfs( stddeb, "DRIVE_Chdir(%c:): unix_cwd=%s dos_cwd=%s\n", |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame^] | 434 | 'A' + drive, unix_cwd, full_name.short_name + 3 ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 435 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 436 | HeapFree( SystemHeap, 0, DOSDrives[drive].dos_cwd ); |
| 437 | HeapFree( SystemHeap, 0, DOSDrives[drive].unix_cwd ); |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame^] | 438 | DOSDrives[drive].dos_cwd = HEAP_strdupA( SystemHeap, 0, |
| 439 | full_name.short_name + 3 ); |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 440 | DOSDrives[drive].unix_cwd = HEAP_strdupA( SystemHeap, 0, unix_cwd ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 441 | |
| 442 | if (pTask && (pTask->curdrive & 0x80) && |
| 443 | ((pTask->curdrive & ~0x80) == drive)) |
| 444 | { |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame^] | 445 | lstrcpyn32A( pTask->curdir, full_name.short_name + 2, |
| 446 | sizeof(pTask->curdir) ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 447 | DRIVE_LastTask = GetCurrentTask(); |
| 448 | } |
| 449 | return 1; |
| 450 | } |
| 451 | |
| 452 | |
| 453 | /*********************************************************************** |
| 454 | * DRIVE_Disable |
| 455 | */ |
| 456 | int DRIVE_Disable( int drive ) |
| 457 | { |
| 458 | if ((drive < 0) || (drive >= MAX_DOS_DRIVES) || !DOSDrives[drive].root) |
| 459 | { |
| 460 | DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); |
| 461 | return 0; |
| 462 | } |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 463 | DOSDrives[drive].flags |= DRIVE_DISABLED; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 464 | return 1; |
| 465 | } |
| 466 | |
| 467 | |
| 468 | /*********************************************************************** |
| 469 | * DRIVE_Enable |
| 470 | */ |
| 471 | int DRIVE_Enable( int drive ) |
| 472 | { |
| 473 | if ((drive < 0) || (drive >= MAX_DOS_DRIVES) || !DOSDrives[drive].root) |
| 474 | { |
| 475 | DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); |
| 476 | return 0; |
| 477 | } |
Alexandre Julliard | 1e37a18 | 1996-08-18 16:21:52 +0000 | [diff] [blame] | 478 | DOSDrives[drive].flags &= ~DRIVE_DISABLED; |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 479 | return 1; |
| 480 | } |
| 481 | |
| 482 | |
| 483 | /*********************************************************************** |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 484 | * DRIVE_GetFreeSpace |
| 485 | */ |
Alexandre Julliard | 339eefc | 1996-06-23 14:56:20 +0000 | [diff] [blame] | 486 | static int DRIVE_GetFreeSpace( int drive, DWORD *size, DWORD *available ) |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 487 | { |
| 488 | struct statfs info; |
| 489 | |
| 490 | if (!DRIVE_IsValid(drive)) |
| 491 | { |
| 492 | DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); |
| 493 | return 0; |
| 494 | } |
| 495 | |
Alexandre Julliard | 8664b89 | 1996-04-05 14:58:24 +0000 | [diff] [blame] | 496 | #if defined(__svr4__) || defined(_SCO_DS) |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 497 | if (statfs( DOSDrives[drive].root, &info, 0, 0) < 0) |
| 498 | #else |
| 499 | if (statfs( DOSDrives[drive].root, &info) < 0) |
| 500 | #endif |
| 501 | { |
| 502 | FILE_SetDosError(); |
| 503 | fprintf(stderr,"dosfs: cannot do statfs(%s)\n", DOSDrives[drive].root); |
| 504 | return 0; |
| 505 | } |
| 506 | |
| 507 | *size = info.f_bsize * info.f_blocks; |
Alexandre Julliard | 8664b89 | 1996-04-05 14:58:24 +0000 | [diff] [blame] | 508 | #if defined(__svr4__) || defined(_SCO_DS) |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 509 | *available = info.f_bfree * info.f_bsize; |
| 510 | #else |
| 511 | *available = info.f_bavail * info.f_bsize; |
| 512 | #endif |
| 513 | return 1; |
| 514 | } |
| 515 | |
| 516 | |
| 517 | /*********************************************************************** |
Alexandre Julliard | 339eefc | 1996-06-23 14:56:20 +0000 | [diff] [blame] | 518 | * GetDiskFreeSpace16 (KERNEL.422) |
| 519 | */ |
| 520 | BOOL16 GetDiskFreeSpace16( LPCSTR root, LPDWORD cluster_sectors, |
| 521 | LPDWORD sector_bytes, LPDWORD free_clusters, |
| 522 | LPDWORD total_clusters ) |
| 523 | { |
| 524 | return GetDiskFreeSpace32A( root, cluster_sectors, sector_bytes, |
| 525 | free_clusters, total_clusters ); |
| 526 | } |
| 527 | |
| 528 | |
| 529 | /*********************************************************************** |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 530 | * GetDiskFreeSpace32A (KERNEL32.206) |
Alexandre Julliard | 339eefc | 1996-06-23 14:56:20 +0000 | [diff] [blame] | 531 | */ |
| 532 | BOOL32 GetDiskFreeSpace32A( LPCSTR root, LPDWORD cluster_sectors, |
| 533 | LPDWORD sector_bytes, LPDWORD free_clusters, |
| 534 | LPDWORD total_clusters ) |
| 535 | { |
| 536 | int drive; |
| 537 | DWORD size,available; |
| 538 | |
| 539 | if (!root) drive = DRIVE_GetCurrentDrive(); |
| 540 | else |
| 541 | { |
| 542 | if ((root[1] != ':') || (root[2] != '\\')) |
| 543 | { |
| 544 | fprintf( stderr, "GetDiskFreeSpaceA: invalid root '%s'\n", root ); |
| 545 | return FALSE; |
| 546 | } |
| 547 | drive = toupper(root[0]) - 'A'; |
| 548 | } |
| 549 | if (!DRIVE_GetFreeSpace(drive, &size, &available)) return FALSE; |
| 550 | |
| 551 | *sector_bytes = 512; |
| 552 | size /= 512; |
| 553 | available /= 512; |
| 554 | *cluster_sectors = 1; |
| 555 | while (*cluster_sectors * 65530 < size) *cluster_sectors *= 2; |
| 556 | *free_clusters = available/ *cluster_sectors; |
| 557 | *total_clusters = size/ *cluster_sectors; |
| 558 | return TRUE; |
| 559 | } |
| 560 | |
| 561 | |
| 562 | /*********************************************************************** |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 563 | * GetDiskFreeSpace32W (KERNEL32.207) |
Alexandre Julliard | 339eefc | 1996-06-23 14:56:20 +0000 | [diff] [blame] | 564 | */ |
| 565 | BOOL32 GetDiskFreeSpace32W( LPCWSTR root, LPDWORD cluster_sectors, |
| 566 | LPDWORD sector_bytes, LPDWORD free_clusters, |
| 567 | LPDWORD total_clusters ) |
| 568 | { |
| 569 | LPSTR xroot; |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 570 | BOOL32 ret; |
Alexandre Julliard | 339eefc | 1996-06-23 14:56:20 +0000 | [diff] [blame] | 571 | |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 572 | xroot = HEAP_strdupWtoA( GetProcessHeap(), 0, root); |
Alexandre Julliard | 339eefc | 1996-06-23 14:56:20 +0000 | [diff] [blame] | 573 | ret = GetDiskFreeSpace32A( xroot,cluster_sectors, sector_bytes, |
| 574 | free_clusters, total_clusters ); |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 575 | HeapFree( GetProcessHeap(), 0, xroot ); |
Alexandre Julliard | 339eefc | 1996-06-23 14:56:20 +0000 | [diff] [blame] | 576 | return ret; |
| 577 | } |
| 578 | |
| 579 | |
| 580 | /*********************************************************************** |
Alexandre Julliard | 3051b64 | 1996-07-05 17:14:13 +0000 | [diff] [blame] | 581 | * GetDriveType16 (KERNEL.136) |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 582 | */ |
Alexandre Julliard | 3051b64 | 1996-07-05 17:14:13 +0000 | [diff] [blame] | 583 | UINT16 GetDriveType16( UINT16 drive ) |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 584 | { |
| 585 | dprintf_dosfs( stddeb, "GetDriveType(%c:)\n", 'A' + drive ); |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 586 | switch(DRIVE_GetType(drive)) |
| 587 | { |
| 588 | case TYPE_FLOPPY: return DRIVE_REMOVABLE; |
| 589 | case TYPE_HD: return DRIVE_FIXED; |
Alexandre Julliard | d1ce8b2 | 1996-09-02 16:46:30 +0000 | [diff] [blame] | 590 | case TYPE_CDROM: return DRIVE_REMOTE; |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 591 | case TYPE_NETWORK: return DRIVE_REMOTE; |
| 592 | case TYPE_INVALID: |
| 593 | default: return DRIVE_CANNOTDETERMINE; |
| 594 | } |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 595 | } |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 596 | |
| 597 | |
| 598 | /*********************************************************************** |
Alexandre Julliard | 3051b64 | 1996-07-05 17:14:13 +0000 | [diff] [blame] | 599 | * GetDriveType32A (KERNEL32.208) |
Alexandre Julliard | 2d93d00 | 1996-05-21 15:01:41 +0000 | [diff] [blame] | 600 | */ |
Alexandre Julliard | 3051b64 | 1996-07-05 17:14:13 +0000 | [diff] [blame] | 601 | UINT32 GetDriveType32A( LPCSTR root ) |
Alexandre Julliard | 2d93d00 | 1996-05-21 15:01:41 +0000 | [diff] [blame] | 602 | { |
| 603 | dprintf_dosfs( stddeb, "GetDriveType32A(%s)\n", root ); |
Alexandre Julliard | b1bac32 | 1996-12-15 19:45:59 +0000 | [diff] [blame] | 604 | if (root[1] != ':') |
Alexandre Julliard | 2d93d00 | 1996-05-21 15:01:41 +0000 | [diff] [blame] | 605 | { |
| 606 | fprintf( stderr, "GetDriveType32A: invalid root '%s'\n", root ); |
| 607 | return DRIVE_DOESNOTEXIST; |
| 608 | } |
| 609 | switch(DRIVE_GetType(toupper(root[0]) - 'A')) |
| 610 | { |
| 611 | case TYPE_FLOPPY: return DRIVE_REMOVABLE; |
| 612 | case TYPE_HD: return DRIVE_FIXED; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 613 | case TYPE_CDROM: return DRIVE_CDROM; |
Alexandre Julliard | 2d93d00 | 1996-05-21 15:01:41 +0000 | [diff] [blame] | 614 | case TYPE_NETWORK: return DRIVE_REMOTE; |
| 615 | case TYPE_INVALID: |
| 616 | default: return DRIVE_CANNOTDETERMINE; |
| 617 | } |
| 618 | } |
| 619 | |
| 620 | |
| 621 | /*********************************************************************** |
Alexandre Julliard | 3051b64 | 1996-07-05 17:14:13 +0000 | [diff] [blame] | 622 | * GetDriveType32W (KERNEL32.209) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 623 | */ |
Alexandre Julliard | 3051b64 | 1996-07-05 17:14:13 +0000 | [diff] [blame] | 624 | UINT32 GetDriveType32W( LPCWSTR root ) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 625 | { |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 626 | LPSTR xpath = HEAP_strdupWtoA( GetProcessHeap(), 0, root ); |
| 627 | UINT32 ret = GetDriveType32A( xpath ); |
| 628 | HeapFree( GetProcessHeap(), 0, xpath ); |
Alexandre Julliard | 3051b64 | 1996-07-05 17:14:13 +0000 | [diff] [blame] | 629 | return ret; |
| 630 | } |
| 631 | |
| 632 | |
| 633 | /*********************************************************************** |
| 634 | * GetCurrentDirectory16 (KERNEL.411) |
| 635 | */ |
| 636 | UINT16 GetCurrentDirectory16( UINT16 buflen, LPSTR buf ) |
| 637 | { |
| 638 | return (UINT16)GetCurrentDirectory32A( buflen, buf ); |
| 639 | } |
| 640 | |
| 641 | |
| 642 | /*********************************************************************** |
| 643 | * GetCurrentDirectory32A (KERNEL32.196) |
| 644 | * |
| 645 | * Returns "X:\\path\\etc\\". |
| 646 | */ |
| 647 | UINT32 GetCurrentDirectory32A( UINT32 buflen, LPSTR buf ) |
| 648 | { |
| 649 | char *pref = "A:\\"; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 650 | const char *s = DRIVE_GetDosCwd( DRIVE_GetCurrentDrive() ); |
| 651 | if (!s) |
| 652 | { |
| 653 | *buf = '\0'; |
| 654 | return 0; |
| 655 | } |
Alexandre Julliard | b1bac32 | 1996-12-15 19:45:59 +0000 | [diff] [blame] | 656 | lstrcpyn32A( buf, pref, MIN( 4, buflen ) ); |
Alexandre Julliard | 3051b64 | 1996-07-05 17:14:13 +0000 | [diff] [blame] | 657 | if (buflen) buf[0] += DRIVE_GetCurrentDrive(); |
Alexandre Julliard | b1bac32 | 1996-12-15 19:45:59 +0000 | [diff] [blame] | 658 | if (buflen > 3) lstrcpyn32A( buf + 3, s, buflen - 3 ); |
Alexandre Julliard | 3051b64 | 1996-07-05 17:14:13 +0000 | [diff] [blame] | 659 | return strlen(s) + 3; /* length of WHOLE current directory */ |
| 660 | } |
| 661 | |
| 662 | |
| 663 | /*********************************************************************** |
| 664 | * GetCurrentDirectory32W (KERNEL32.197) |
| 665 | */ |
| 666 | UINT32 GetCurrentDirectory32W( UINT32 buflen, LPWSTR buf ) |
| 667 | { |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 668 | LPSTR xpath = HeapAlloc( GetProcessHeap(), 0, buflen+1 ); |
| 669 | UINT32 ret = GetCurrentDirectory32A( buflen, xpath ); |
| 670 | lstrcpyAtoW( buf, xpath ); |
| 671 | HeapFree( GetProcessHeap(), 0, xpath ); |
Alexandre Julliard | 3051b64 | 1996-07-05 17:14:13 +0000 | [diff] [blame] | 672 | return ret; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 673 | } |
| 674 | |
| 675 | |
| 676 | /*********************************************************************** |
| 677 | * SetCurrentDirectory (KERNEL.412) |
| 678 | */ |
Alexandre Julliard | b1bac32 | 1996-12-15 19:45:59 +0000 | [diff] [blame] | 679 | BOOL16 SetCurrentDirectory16( LPCSTR dir ) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 680 | { |
Alexandre Julliard | 75d86e1 | 1996-11-17 18:59:11 +0000 | [diff] [blame] | 681 | if (dir[0] && (dir[1]==':')) |
| 682 | { |
| 683 | int drive = tolower( *dir ) - 'a'; |
| 684 | if (!DRIVE_IsValid(drive)) |
| 685 | { |
| 686 | DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk ); |
| 687 | return 0; |
| 688 | } |
| 689 | dir += 2; |
| 690 | } |
| 691 | /* FIXME: what about empty strings? Add a \\ ? */ |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 692 | return DRIVE_Chdir( DRIVE_GetCurrentDrive(), dir ); |
| 693 | } |
Alexandre Julliard | 2d93d00 | 1996-05-21 15:01:41 +0000 | [diff] [blame] | 694 | |
Alexandre Julliard | b1bac32 | 1996-12-15 19:45:59 +0000 | [diff] [blame] | 695 | /*********************************************************************** |
| 696 | * SetCurrentDirectory32A (KERNEL32.479) |
| 697 | */ |
| 698 | BOOL32 SetCurrentDirectory32A( LPCSTR dir ) |
| 699 | { |
| 700 | /* FIXME: Unauthorized Windows 95 mentions that SetCurrentDirectory |
| 701 | * may change drive and current directory for there is no drive based |
| 702 | * currentdir table? |
| 703 | */ |
| 704 | return SetCurrentDirectory16(dir); |
| 705 | } |
| 706 | |
| 707 | /*********************************************************************** |
| 708 | * SetCurrentDirectory32W (KERNEL32.480) |
| 709 | */ |
| 710 | BOOL32 SetCurrentDirectory32W( LPCWSTR dirW) |
| 711 | { |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 712 | LPSTR dir = HEAP_strdupWtoA( GetProcessHeap(), 0, dirW ); |
| 713 | BOOL32 res = SetCurrentDirectory32A( dir ); |
| 714 | HeapFree( GetProcessHeap(), 0, dir ); |
Alexandre Julliard | b1bac32 | 1996-12-15 19:45:59 +0000 | [diff] [blame] | 715 | return res; |
| 716 | } |
| 717 | |
Alexandre Julliard | 2d93d00 | 1996-05-21 15:01:41 +0000 | [diff] [blame] | 718 | |
| 719 | /*********************************************************************** |
| 720 | * GetLogicalDriveStrings32A (KERNEL32.231) |
| 721 | */ |
| 722 | UINT32 GetLogicalDriveStrings32A( UINT32 len, LPSTR buffer ) |
| 723 | { |
| 724 | int drive, count; |
| 725 | |
| 726 | for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++) |
| 727 | if (DRIVE_IsValid(drive)) count++; |
| 728 | if (count * 4 * sizeof(char) <= len) |
| 729 | { |
| 730 | LPSTR p = buffer; |
| 731 | for (drive = 0; drive < MAX_DOS_DRIVES; drive++) |
| 732 | if (DRIVE_IsValid(drive)) |
| 733 | { |
| 734 | *p++ = 'a' + drive; |
| 735 | *p++ = ':'; |
| 736 | *p++ = '\\'; |
| 737 | *p++ = '\0'; |
| 738 | } |
| 739 | *p = '\0'; |
| 740 | } |
| 741 | return count * 4 * sizeof(char); |
| 742 | } |
| 743 | |
| 744 | |
| 745 | /*********************************************************************** |
| 746 | * GetLogicalDriveStrings32W (KERNEL32.232) |
| 747 | */ |
| 748 | UINT32 GetLogicalDriveStrings32W( UINT32 len, LPWSTR buffer ) |
| 749 | { |
| 750 | int drive, count; |
| 751 | |
| 752 | for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++) |
| 753 | if (DRIVE_IsValid(drive)) count++; |
| 754 | if (count * 4 * sizeof(WCHAR) <= len) |
| 755 | { |
| 756 | LPWSTR p = buffer; |
| 757 | for (drive = 0; drive < MAX_DOS_DRIVES; drive++) |
| 758 | if (DRIVE_IsValid(drive)) |
| 759 | { |
| 760 | *p++ = (WCHAR)('a' + drive); |
| 761 | *p++ = (WCHAR)':'; |
| 762 | *p++ = (WCHAR)'\\'; |
| 763 | *p++ = (WCHAR)'\0'; |
| 764 | } |
| 765 | *p = (WCHAR)'\0'; |
| 766 | } |
| 767 | return count * 4 * sizeof(WCHAR); |
| 768 | } |
| 769 | |
| 770 | |
| 771 | /*********************************************************************** |
| 772 | * GetLogicalDrives (KERNEL32.233) |
| 773 | */ |
| 774 | DWORD GetLogicalDrives(void) |
| 775 | { |
| 776 | DWORD ret = 0; |
| 777 | int drive; |
| 778 | |
| 779 | for (drive = 0; drive < MAX_DOS_DRIVES; drive++) |
| 780 | if (DRIVE_IsValid(drive)) ret |= (1 << drive); |
| 781 | return ret; |
| 782 | } |
Alexandre Julliard | 339eefc | 1996-06-23 14:56:20 +0000 | [diff] [blame] | 783 | |
| 784 | |
| 785 | /*********************************************************************** |
| 786 | * GetVolumeInformation32A (KERNEL32.309) |
| 787 | */ |
| 788 | BOOL32 GetVolumeInformation32A( LPCSTR root, LPSTR label, DWORD label_len, |
| 789 | DWORD *serial, DWORD *filename_len, |
| 790 | DWORD *flags, LPSTR fsname, DWORD fsname_len ) |
| 791 | { |
| 792 | int drive; |
| 793 | |
| 794 | /* FIXME, SetLastErrors missing */ |
| 795 | |
| 796 | if (!root) drive = DRIVE_GetCurrentDrive(); |
| 797 | else |
| 798 | { |
| 799 | if ((root[1] != ':') || (root[2] != '\\')) |
| 800 | { |
| 801 | fprintf( stderr, "GetVolumeInformation: invalid root '%s'\n",root); |
| 802 | return FALSE; |
| 803 | } |
| 804 | drive = toupper(root[0]) - 'A'; |
| 805 | } |
| 806 | if (!DRIVE_IsValid( drive )) return FALSE; |
| 807 | if (label) lstrcpyn32A( label, DOSDrives[drive].label, label_len ); |
| 808 | if (serial) *serial = DOSDrives[drive].serial; |
| 809 | |
| 810 | /* Set the filesystem information */ |
| 811 | /* Note: we only emulate a FAT fs at the present */ |
| 812 | |
| 813 | if (filename_len) *filename_len = 12; |
| 814 | if (flags) *flags = 0; |
| 815 | if (fsname) lstrcpyn32A( fsname, "FAT", fsname_len ); |
| 816 | return TRUE; |
| 817 | } |
| 818 | |
| 819 | |
| 820 | /*********************************************************************** |
| 821 | * GetVolumeInformation32W (KERNEL32.310) |
| 822 | */ |
| 823 | BOOL32 GetVolumeInformation32W( LPCWSTR root, LPWSTR label, DWORD label_len, |
| 824 | DWORD *serial, DWORD *filename_len, |
| 825 | DWORD *flags, LPWSTR fsname, DWORD fsname_len) |
| 826 | { |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 827 | LPSTR xroot = HEAP_strdupWtoA( GetProcessHeap(), 0, root ); |
| 828 | LPSTR xvolname = label ? HeapAlloc(GetProcessHeap(),0,label_len) : NULL; |
| 829 | LPSTR xfsname = fsname ? HeapAlloc(GetProcessHeap(),0,fsname_len) : NULL; |
Alexandre Julliard | 339eefc | 1996-06-23 14:56:20 +0000 | [diff] [blame] | 830 | BOOL32 ret = GetVolumeInformation32A( xroot, xvolname, label_len, serial, |
| 831 | filename_len, flags, xfsname, |
| 832 | fsname_len ); |
| 833 | if (ret) |
| 834 | { |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 835 | if (label) lstrcpyAtoW( label, xvolname ); |
| 836 | if (fsname) lstrcpyAtoW( fsname, xfsname ); |
Alexandre Julliard | 339eefc | 1996-06-23 14:56:20 +0000 | [diff] [blame] | 837 | } |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 838 | HeapFree( GetProcessHeap(), 0, xroot ); |
| 839 | HeapFree( GetProcessHeap(), 0, xvolname ); |
| 840 | HeapFree( GetProcessHeap(), 0, xfsname ); |
Alexandre Julliard | 339eefc | 1996-06-23 14:56:20 +0000 | [diff] [blame] | 841 | return ret; |
| 842 | } |