~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/programs/winecfg/drive.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Drive management code
  3  *
  4  * Copyright 2003 Mark Westcott
  5  * Copyright 2003-2004 Mike Hearn
  6  * Copyright 2004 Chris Morgan
  7  *
  8  * This library is free software; you can redistribute it and/or
  9  * modify it under the terms of the GNU Lesser General Public
 10  * License as published by the Free Software Foundation; either
 11  * version 2.1 of the License, or (at your option) any later version.
 12  *
 13  * This library is distributed in the hope that it will be useful,
 14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16  * Lesser General Public License for more details.
 17  *
 18  * You should have received a copy of the GNU Lesser General Public
 19  * License along with this library; if not, write to the Free Software
 20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 21  *
 22  */
 23 
 24 #include "config.h"
 25 #include "wine/port.h"
 26 
 27 #include <assert.h>
 28 #include <stdarg.h>
 29 #include <stdio.h>
 30 #include <string.h>
 31 
 32 #include <ntstatus.h>
 33 #define WIN32_NO_STATUS
 34 #include <windef.h>
 35 #include <winbase.h>
 36 #include <winternl.h>
 37 #include <winioctl.h>
 38 #include <winreg.h>
 39 #include <wine/debug.h>
 40 #include <shellapi.h>
 41 #include <objbase.h>
 42 #include <shlguid.h>
 43 #include <shlwapi.h>
 44 #include <shlobj.h>
 45 #define WINE_MOUNTMGR_EXTENSIONS
 46 #include <ddk/mountmgr.h>
 47 #include <wine/library.h>
 48 
 49 #include "winecfg.h"
 50 #include "resource.h"
 51 
 52 
 53 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
 54 
 55 struct drive drives[26]; /* one for each drive letter */
 56 
 57 static inline int letter_to_index(char letter)
 58 {
 59     return (toupper(letter) - 'A');
 60 }
 61 
 62 /* This function produces a mask for each drive letter that isn't
 63  * currently used. Each bit of the long result represents a letter,
 64  * with A being the least significant bit, and Z being the most
 65  * significant.
 66  *
 67  * To calculate this, we loop over each letter, and see if we can get
 68  * a drive entry for it. If so, we set the appropriate bit. At the
 69  * end, we flip each bit, to give the desired result.
 70  *
 71  * The letter parameter is always marked as being available. This is
 72  * so the edit dialog can display the currently used drive letter
 73  * alongside the available ones.
 74  */
 75 ULONG drive_available_mask(char letter)
 76 {
 77   ULONG result = 0;
 78   int i;
 79 
 80   WINE_TRACE("\n");
 81 
 82 
 83   for(i = 0; i < 26; i++)
 84   {
 85       if (!drives[i].in_use) continue;
 86       result |= (1 << (letter_to_index(drives[i].letter)));
 87   }
 88 
 89   result = ~result;
 90   if (letter) result |= DRIVE_MASK_BIT(letter);
 91 
 92   WINE_TRACE("finished drive letter loop with %x\n", result);
 93   return result;
 94 }
 95 
 96 BOOL add_drive(char letter, const char *targetpath, const char *device, const WCHAR *label,
 97                DWORD serial, DWORD type)
 98 {
 99     int driveIndex = letter_to_index(letter);
100 
101     if(drives[driveIndex].in_use)
102         return FALSE;
103 
104     WINE_TRACE("letter == '%c', unixpath == %s, device == %s, label == %s, serial == %08x, type == %d\n",
105                letter, wine_dbgstr_a(targetpath), wine_dbgstr_a(device),
106                wine_dbgstr_w(label), serial, type);
107 
108     drives[driveIndex].letter   = toupper(letter);
109     drives[driveIndex].unixpath = strdupA(targetpath);
110     drives[driveIndex].device   = device ? strdupA(device) : NULL;
111     drives[driveIndex].label    = label ? strdupW(label) : NULL;
112     drives[driveIndex].serial   = serial;
113     drives[driveIndex].type     = type;
114     drives[driveIndex].in_use   = TRUE;
115     drives[driveIndex].modified = TRUE;
116 
117     return TRUE;
118 }
119 
120 /* deallocates the contents of the drive. does not free the drive itself  */
121 void delete_drive(struct drive *d)
122 {
123     HeapFree(GetProcessHeap(), 0, d->unixpath);
124     d->unixpath = NULL;
125     HeapFree(GetProcessHeap(), 0, d->device);
126     d->device = NULL;
127     HeapFree(GetProcessHeap(), 0, d->label);
128     d->label = NULL;
129     d->serial = 0;
130     d->in_use = FALSE;
131     d->modified = TRUE;
132 }
133 
134 static DWORD get_drive_type( char letter )
135 {
136     HKEY hKey;
137     char driveValue[4];
138     DWORD ret = DRIVE_UNKNOWN;
139 
140     sprintf(driveValue, "%c:", letter);
141 
142     if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Wine\\Drives", &hKey) != ERROR_SUCCESS)
143         WINE_TRACE("  Unable to open Software\\Wine\\Drives\n" );
144     else
145     {
146         char buffer[80];
147         DWORD size = sizeof(buffer);
148 
149         if (!RegQueryValueExA( hKey, driveValue, NULL, NULL, (LPBYTE)buffer, &size ))
150         {
151             WINE_TRACE("Got type '%s' for %s\n", buffer, driveValue );
152             if (!lstrcmpi( buffer, "hd" )) ret = DRIVE_FIXED;
153             else if (!lstrcmpi( buffer, "network" )) ret = DRIVE_REMOTE;
154             else if (!lstrcmpi( buffer, "floppy" )) ret = DRIVE_REMOVABLE;
155             else if (!lstrcmpi( buffer, "cdrom" )) ret = DRIVE_CDROM;
156         }
157         RegCloseKey(hKey);
158     }
159     return ret;
160 }
161 
162 
163 static void set_drive_label( char letter, const WCHAR *label )
164 {
165     static const WCHAR emptyW[1];
166     WCHAR device[] = {'a',':','\\',0};  /* SetVolumeLabel() requires a trailing slash */
167     device[0] = letter;
168 
169     if (!label) label = emptyW;
170     if(!SetVolumeLabelW(device, label))
171     {
172         WINE_WARN("unable to set volume label for devicename of %s, label of %s\n",
173                   wine_dbgstr_w(device), wine_dbgstr_w(label));
174         PRINTERROR();
175     }
176     else
177     {
178         WINE_TRACE("  set volume label for devicename of %s, label of %s\n",
179                   wine_dbgstr_w(device), wine_dbgstr_w(label));
180     }
181 }
182 
183 /* set the drive serial number via a .windows-serial file */
184 static void set_drive_serial( char letter, DWORD serial )
185 {
186     char filename[] = "a:\\.windows-serial";
187     HANDLE hFile;
188 
189     filename[0] = letter;
190     WINE_TRACE("Putting serial number of %08X into file '%s'\n", serial, filename);
191     hFile = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
192                        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
193     if (hFile != INVALID_HANDLE_VALUE)
194     {
195         DWORD w;
196         char buffer[16];
197 
198         sprintf( buffer, "%X\n", serial );
199         WriteFile(hFile, buffer, strlen(buffer), &w, NULL);
200         CloseHandle(hFile);
201     }
202 }
203 
204 #if 0
205 
206 /* currently unused, but if users have this burning desire to be able to rename drives,
207    we can put it back in.
208  */
209 
210 BOOL copyDrive(struct drive *pSrc, struct drive *pDst)
211 {
212     if(pDst->in_use)
213     {
214         WINE_TRACE("pDst already in use\n");
215         return FALSE;
216     }
217 
218     if(!pSrc->unixpath) WINE_TRACE("!pSrc->unixpath\n");
219     if(!pSrc->label) WINE_TRACE("!pSrc->label\n");
220     if(!pSrc->serial) WINE_TRACE("!pSrc->serial\n");
221 
222     pDst->unixpath = strdupA(pSrc->unixpath);
223     pDst->label = strdupA(pSrc->label);
224     pDst->serial = strdupA(pSrc->serial);
225     pDst->type = pSrc->type;
226     pDst->in_use = TRUE;
227 
228     return TRUE;
229 }
230 
231 BOOL moveDrive(struct drive *pSrc, struct drive *pDst)
232 {
233     WINE_TRACE("pSrc->letter == %c, pDst->letter == %c\n", pSrc->letter, pDst->letter);
234 
235     if(!copyDrive(pSrc, pDst))
236     {
237         WINE_TRACE("copyDrive failed\n");
238         return FALSE;
239     }
240 
241     delete_drive(pSrc);
242     return TRUE;
243 }
244 
245 #endif
246 
247 static HANDLE open_mountmgr(void)
248 {
249     HANDLE ret;
250 
251     if ((ret = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, GENERIC_READ|GENERIC_WRITE,
252                             FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
253                             0, 0 )) == INVALID_HANDLE_VALUE)
254         WINE_ERR( "failed to open mount manager err %u\n", GetLastError() );
255     return ret;
256 }
257 
258 /* Load currently defined drives into the drives array  */
259 BOOL load_drives(void)
260 {
261     DWORD i, size = 1024;
262     HANDLE mgr;
263     WCHAR root[] = {'A',':','\\',0};
264 
265     if ((mgr = open_mountmgr()) == INVALID_HANDLE_VALUE) return FALSE;
266 
267     while (root[0] <= 'Z')
268     {
269         struct mountmgr_unix_drive input;
270         struct mountmgr_unix_drive *data;
271 
272         if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) break;
273 
274         memset( &input, 0, sizeof(input) );
275         input.letter = root[0];
276 
277         if (DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE, &input, sizeof(input),
278                              data, size, NULL, NULL ))
279         {
280             char *unixpath = NULL, *device = NULL;
281             WCHAR volname[MAX_PATH];
282             DWORD serial;
283 
284             if (data->mount_point_offset) unixpath = (char *)data + data->mount_point_offset;
285             if (data->device_offset) device = (char *)data + data->device_offset;
286 
287             if (!GetVolumeInformationW( root, volname, sizeof(volname)/sizeof(WCHAR),
288                                         &serial, NULL, NULL, NULL, 0 ))
289             {
290                 volname[0] = 0;
291                 serial = 0;
292             }
293             if (unixpath)  /* FIXME: handle unmounted drives too */
294                 add_drive( root[0], unixpath, device, volname, serial, get_drive_type(root[0]) );
295             root[0]++;
296         }
297         else
298         {
299             if (GetLastError() == ERROR_MORE_DATA) size = data->size;
300             else root[0]++;  /* skip this drive */
301         }
302         HeapFree( GetProcessHeap(), 0, data );
303     }
304 
305     /* reset modified flags */
306     for (i = 0; i < 26; i++) drives[i].modified = FALSE;
307 
308     CloseHandle( mgr );
309     return TRUE;
310 }
311 
312 /* some of this code appears to be broken by bugs in Wine: the label
313  * setting code has no effect, for instance  */
314 void apply_drive_changes(void)
315 {
316     int i;
317     HANDLE mgr;
318     DWORD len;
319     struct mountmgr_unix_drive *ioctl;
320 
321     WINE_TRACE("\n");
322 
323     if ((mgr = open_mountmgr()) == INVALID_HANDLE_VALUE) return;
324 
325     /* add each drive and remove as we go */
326     for(i = 0; i < 26; i++)
327     {
328         if (!drives[i].modified) continue;
329         drives[i].modified = FALSE;
330 
331         len = sizeof(*ioctl);
332         if (drives[i].in_use)
333         {
334             len += strlen(drives[i].unixpath) + 1;
335             if (drives[i].device) len += strlen(drives[i].device) + 1;
336         }
337         if (!(ioctl = HeapAlloc( GetProcessHeap(), 0, len ))) continue;
338         ioctl->size = len;
339         ioctl->letter = 'a' + i;
340         ioctl->device_offset = 0;
341         if (drives[i].in_use)
342         {
343             char *ptr = (char *)(ioctl + 1);
344 
345             ioctl->type = drives[i].type;
346             strcpy( ptr, drives[i].unixpath );
347             ioctl->mount_point_offset = ptr - (char *)ioctl;
348             if (drives[i].device)
349             {
350                 ptr += strlen(ptr) + 1;
351                 strcpy( ptr, drives[i].device );
352                 ioctl->device_offset = ptr - (char *)ioctl;
353             }
354         }
355         else
356         {
357             ioctl->type = DRIVE_NO_ROOT_DIR;
358             ioctl->mount_point_offset = 0;
359         }
360 
361         if (DeviceIoControl( mgr, IOCTL_MOUNTMGR_DEFINE_UNIX_DRIVE, ioctl, len, NULL, 0, NULL, NULL ))
362         {
363             set_drive_label( drives[i].letter, drives[i].label );
364             if (drives[i].in_use) set_drive_serial( drives[i].letter, drives[i].serial );
365             WINE_TRACE( "set drive %c: to %s type %u\n", 'a' + i,
366                         wine_dbgstr_a(drives[i].unixpath), drives[i].type );
367         }
368         else WINE_WARN( "failed to set drive %c: to %s type %u err %u\n", 'a' + i,
369                        wine_dbgstr_a(drives[i].unixpath), drives[i].type, GetLastError() );
370     }
371     CloseHandle( mgr );
372 }
373 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.