|
|
1.1 root 1: /* Copyright (C) 2004 TrueCrypt Team, truecrypt.org
2: This product uses components written by Paul Le Roux <[email protected]> */
3:
4: /* WARNING: The code for unmounting volumes is ugly for all Windows versions;
5: becarefull what you change here as there might be unintended side effects
6: in the device drivers */
7:
8: /* For Windows NT the part of the system that actually unmounts drives is the
9: TrueCryptService, this is because of NT security. Users don't normally have
10: enough access to open raw partitions, but services do, TrueCryptService still
11: calls this code however. */
12:
13: #include "TCdefs.h"
14: #include "crypto.h"
15: #include "apidrvr.h"
16:
17: #include "dismount.h"
18:
19: extern HANDLE hDriver;
20:
21: #ifdef NTSERVICE
22: extern void handleWin32Error (HWND dummy);
23: #else
24: #include "dlgcode.h"
25: #endif
26:
27: /* NT support routines -----------------------------------> */
28:
29: BOOL
30: UnmountAllVolumes (HWND hwndDlg, DWORD * os_error, int *err)
31: {
32: MOUNT_LIST_STRUCT driver;
33: DWORD dwResult;
34: BOOL bResult, bOK = TRUE;
35: int i;
36:
37: *os_error = 0;
38: *err = 0;
39:
40: bResult = DeviceIoControl (hDriver, MOUNT_LIST, &driver, sizeof (driver), &driver,
41: sizeof (driver), &dwResult, NULL);
42:
43: if (bResult == FALSE)
44: {
45: *os_error = GetLastError ();
46: *err = ERR_OS_ERROR;
47: return FALSE;
48: }
49:
50: for (i = 0; i < 26; i++)
51: {
52: if ((driver.ulMountedDrives & 1 << i))
53: {
54: UnmountVolume (i, os_error, err);
55:
56: if (*err != 0)
57: bOK = FALSE;
58:
59: if (*err != 0 && *err == ERR_OS_ERROR)
60: handleWin32Error (hwndDlg);
61: }
62: }
63:
64: return bOK;
65: }
66:
67: BOOL
68: UnmountVolume (int nDosDriveNo, DWORD * os_error, int *err)
69: {
70: UNMOUNT_STRUCT tcUnmount;
71: char volMountName[32];
72: char dosName[3];
73: DWORD dwResult;
74: BOOL bResult;
75:
76: *os_error = 0;
77: *err = 0;
78:
79: tcUnmount.nDosDriveNo = nDosDriveNo;
80:
81: dosName[0] = (char) (tcUnmount.nDosDriveNo + 'A');
82: dosName[1] = ':';
83: dosName[2] = 0;
84:
85: sprintf (volMountName, "\\\\.\\%s", dosName);
86:
87: if (DismountVolume (volMountName, os_error, err) == FALSE)
88: return FALSE;
89:
90: bResult = DeviceIoControl (hDriver, UNMOUNT, &tcUnmount,
91: sizeof (tcUnmount), &tcUnmount, sizeof (tcUnmount), &dwResult, NULL);
92:
93: if (bResult == FALSE)
94: {
95: *os_error = GetLastError ();
96: *err = ERR_OS_ERROR;
97: return FALSE;
98: }
99:
100: if (tcUnmount.nReturnCode == 0)
101: {
102: bResult = DefineDosDevice (DDD_REMOVE_DEFINITION, dosName, NULL);
103:
104: if (bResult == FALSE)
105: {
106: *os_error = GetLastError ();
107: *err = ERR_OS_ERROR;
108: return FALSE;
109: }
110: }
111: else
112: *err = tcUnmount.nReturnCode;
113:
114: return TRUE;
115: }
116:
117: BOOL
118: DismountVolume (char *lpszVolMountName, DWORD * os_error, int *err)
119: {
120: HANDLE hVolume = INVALID_HANDLE_VALUE;
121: BOOL bRetry = FALSE;
122: DWORD dwResult;
123: int i;
124:
125: *os_error = 0;
126: *err = 0;
127:
128: retry:
129:
130: #ifdef _DEBUG
131: OutputDebugString ("mount: dismount volume ----------------->...\n");
132: #endif
133:
134: for (i = 0; i < 16; i++)
135: {
136: BOOL bResult;
137:
138: #ifdef _DEBUG
139: OutputDebugString ("mount: trying to open the volume...\n");
140: #endif
141: /* Try to open a handle to the mounted volume */
142: hVolume = CreateFile (lpszVolMountName, GENERIC_READ | GENERIC_WRITE,
143: FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
144: if (hVolume == INVALID_HANDLE_VALUE)
145: {
146: *os_error = GetLastError ();
147: *err = ERR_OS_ERROR;
148: return FALSE;
149: }
150:
151: #ifdef _DEBUG
152: OutputDebugString ("mount: trying to lock the volume...\n");
153: #endif
154: bResult = DeviceIoControl (hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL);
155: if (bResult == FALSE)
156: {
157: DWORD dwError = GetLastError ();
158: if (dwError != ERROR_ACCESS_DENIED)
159: {
160: *os_error = GetLastError ();
161: *err = ERR_OS_ERROR;
162: CloseHandle (hVolume);
163: return FALSE;
164: }
165: else
166: {
167: CloseHandle (hVolume);
168: hVolume = INVALID_HANDLE_VALUE;
169: }
170: }
171: else
172: break;
173: }
174:
175: if (hVolume == INVALID_HANDLE_VALUE)
176: {
177: if (bRetry == FALSE)
178: {
179: bRetry = TRUE;
180: Sleep (1000);
181: goto retry;
182: }
183:
184: *err = ERR_FILES_OPEN_LOCK;
185:
186: return FALSE;
187: }
188:
189: #ifdef _DEBUG
190: OutputDebugString ("mount: trying to dismount the volume...\n");
191: #endif
192: DeviceIoControl (hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL);
193: #ifdef _DEBUG
194: OutputDebugString ("mount: trying to unmount the volume...\n");
195: #endif
196:
197: DeviceIoControl (hVolume, UNMOUNT_PENDING, NULL, 0, NULL, 0, &dwResult, NULL);
198: CloseHandle (hVolume);
199:
200: #ifdef _DEBUG
201: OutputDebugString ("<-------------------------------- mount: dismount volume!\n");
202: #endif
203:
204: return TRUE;
205: }
206:
207:
208: /* Windows 9x support routines -----------------------------------> */
209:
210: typedef struct _DIOC_REGISTERS
211: {
212: DWORD reg_EBX;
213: DWORD reg_EDX;
214: DWORD reg_ECX;
215: DWORD reg_EAX;
216: DWORD reg_EDI;
217: DWORD reg_ESI;
218: DWORD reg_Flags;
219: } DIOC_REGISTERS, *PDIOC_REGISTERS;
220:
221: #define VWIN32_DIOC_DOS_IOCTL 1
222:
223: typedef struct PARAMBLOCK
224: {
225: char Operation;
226: char NumLocks;
227: } PARAMBLOCK;
228:
229:
230: BOOL
231: DoDeviceClose (int slot, int *err)
232: {
233: MOUNT_LIST_N_STRUCT mount_list;
234: UNMOUNT_STRUCT unmount;
235: int tries;
236: int c;
237:
238: mount_list.nDosDriveNo = slot;
239: if (DeviceIoControl (hDriver, MOUNT_LIST_N, &mount_list, sizeof (mount_list), NULL, 0, NULL, NULL) == FALSE)
240: {
241: *err = ERR_OS_ERROR;
242: return FALSE;
243: }
244: else
245: {
246: if (mount_list.nReturnCode != 0)
247: {
248: *err = mount_list.nReturnCode;
249: return TRUE;
250: }
251: }
252:
253: if (mount_list.mountfilehandle)
254: EjectStop ((char)toupper(*((char *) mount_list.wszVolume)), FALSE);
255:
256: unmount.nDosDriveNo = slot;
257: if (DeviceIoControl (hDriver, UNMOUNT_PENDING, &unmount, sizeof (unmount), NULL, 0, NULL, NULL) == FALSE)
258: {
259: *err = ERR_OS_ERROR;
260: return FALSE;
261: }
262: else
263: {
264: if (mount_list.nReturnCode != 0)
265: {
266: *err = mount_list.nReturnCode;
267: return TRUE;
268: }
269: }
270:
271: for (c = 0; c < 20; c++)
272: {
273: DeviceIoControl (hDriver, RELEASE_TIME_SLICE, NULL, 0, NULL, 0, NULL, NULL);
274: }
275:
276: for (tries=0;tries<32;tries++)
277: {
278: DeviceIoControl (hDriver, RELEASE_TIME_SLICE, NULL, 0, NULL, 0, NULL, NULL);
279: if (DeviceIoControl (hDriver, UNMOUNT, &unmount, sizeof (UNMOUNT), NULL, 0, NULL, NULL) == FALSE)
280: {
281: *err = ERR_OS_ERROR;
282: return FALSE;
283: }
284: else
285: {
286: if (mount_list.nReturnCode == 0)
287: {
288: *err = 0;
289: return TRUE;
290: }
291: }
292: }
293:
294: *err = ERR_FILES_OPEN_LOCK;
295: return TRUE;
296: }
297:
298: int
299: ioctllock (unsigned int nDrive, int permissions, int function)
300: {
301: HANDLE hDevice;
302: DIOC_REGISTERS reg;
303: BOOL fResult;
304: DWORD cb;
305: int lockfunc;
306:
307: if (function)
308: lockfunc = 0x4a;
309: else
310: lockfunc = 0x6a;
311:
312: hDevice = CreateFile ("\\\\.\\vwin32",
313: 0, 0, NULL, 0, FILE_FLAG_DELETE_ON_CLOSE, NULL);
314:
315: reg.reg_EAX = 0x440D;
316: reg.reg_EBX = nDrive;
317: reg.reg_ECX = 0x0800 | lockfunc;
318: reg.reg_EDX = permissions;
319: reg.reg_Flags = 0x0001;
320:
321: fResult = DeviceIoControl (hDevice,
322: VWIN32_DIOC_DOS_IOCTL,
323: ®, sizeof (reg),
324: ®, sizeof (reg),
325: &cb, 0);
326:
327: CloseHandle (hDevice);
328:
329: return reg.reg_Flags & 1; /* error if carry flag is set */
330: }
331:
332: int
333: locklogdrive (int drivenum, int mode) /* error if true returned.... */
334: {
335: int a;
336:
337: if (mode)
338: {
339: a = ioctllock (drivenum, 0, 1);
340: a = ioctllock (drivenum, 4, 1);
341: }
342: else
343: {
344: a = 0;
345: ioctllock (drivenum, 0, 0);
346: ioctllock (drivenum, 0, 0);
347: }
348:
349: return a;
350: }
351:
352:
353:
354: int
355: ld (char *d, int mode)
356: {
357: int drivelett = d[0];
358: int a = 1;
359:
360: drivelett -= 'A';
361: drivelett += 1;
362:
363: if ((drivelett > 1) && drivelett < 27)
364: a = (locklogdrive (drivelett, mode));
365:
366: return a;
367:
368: }
369:
370: BOOL
371: CloseSlot (int slot, int brutal, int *err)
372: {
373: char dr[3];
374: BOOL bResult;
375:
376: if (brutal); /* Remove warning */
377:
378: dr[0] = (char) (slot + 'A');
379: dr[1] = ':';
380: dr[2] = 0;
381:
382: if (ld (dr, 1))
383: {
384: bResult = TRUE;
385: *err = ERR_FILES_OPEN_LOCK;
386: }
387: else
388: {
389: bResult = DoDeviceClose (slot, err);
390: ld (dr, 0);
391: }
392:
393: return bResult;
394: }
395:
396:
397: int
398: EjectStop (char Driveletter, BOOL function)
399: {
400: HANDLE hDevice;
401: DIOC_REGISTERS reg;
402: BOOL fResult;
403: DWORD cb;
404: int lockfunc;
405: PARAMBLOCK p;
406:
407: if (Driveletter == 0)
408: return 0;
409:
410: Driveletter -= 'A';
411: Driveletter++;
412:
413: lockfunc = 0x48;
414:
415: if (function == TRUE)
416: p.Operation = 0;/* lock */
417: else
418: p.Operation = 1;
419:
420: hDevice = CreateFile ("\\\\.\\vwin32", 0, 0, NULL, 0,
421: FILE_FLAG_DELETE_ON_CLOSE, NULL);
422:
423: reg.reg_EAX = 0x440D;
424: reg.reg_EBX = Driveletter;
425: reg.reg_ECX = 0x0800 | lockfunc;
426: reg.reg_EDX = (unsigned long) &p;
427: reg.reg_Flags = 0x0001;
428:
429: fResult = DeviceIoControl (hDevice,
430: VWIN32_DIOC_DOS_IOCTL,
431: ®, sizeof (reg),
432: ®, sizeof (reg),
433: &cb, 0);
434:
435: CloseHandle (hDevice);
436:
437: return reg.reg_Flags & 1; /* error if carry flag is set */
438: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.