/[winpt]/trunk/Src/wptCryptdisk.cpp
ViewVC logotype

Contents of /trunk/Src/wptCryptdisk.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 36 - (show annotations)
Thu Oct 27 15:25:13 2005 UTC (19 years, 4 months ago) by werner
File size: 15846 byte(s)
First set of changes to use autotools for building.
1 /* wptCryptdisk.cpp
2 * Copyright (C) 2004 Timo Schulz
3 *
4 * This file is part of WinPT.
5 *
6 * WinPT 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 * WinPT 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 WinPT; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <windows.h>
26 #include <windows.h>
27 #include <winioctl.h>
28 #include <stdio.h>
29 #include <ctype.h>
30
31 #include "../resource.h"
32 #include "wptCryptdisk.h"
33 #include "wptTypes.h"
34 #include "wptW32API.h"
35 #include "wptNLS.h"
36 #include "wptErrors.h"
37
38 /*DWORD SHFormatDrive(HWND hwnd, UINT drive, UINT fmtID, UINT options);*/
39 typedef DWORD (WINAPI *sh_format_drive_p) (HWND, UINT, UINT, UINT);
40
41 static mount_list_t mounted=NULL;
42 static HMODULE shell32=NULL;
43 static sh_format_drive_p shfmt=NULL;
44
45
46 static int
47 is_nt4 (void)
48 {
49 static int nt_flag = -1;
50 OSVERSIONINFO osinf;
51
52 if (nt_flag != -1)
53 return nt_flag;
54
55 memset (&osinf, 0, sizeof osinf);
56 osinf.dwOSVersionInfoSize = sizeof osinf;
57 GetVersionEx (&osinf);
58 if (osinf.dwPlatformId == VER_PLATFORM_WIN32_NT) {
59 nt_flag = 1;
60 shell32 = LoadLibrary ("SHELL32.DLL");
61 shfmt = (sh_format_drive_p)GetProcAddress (shell32, "SHFormatDrive");
62 if (!shfmt)
63 BUG (0);
64 }
65 else
66 nt_flag = 0;
67 return nt_flag;
68 }
69
70 static int
71 check_filedisk (void)
72 {
73 HKEY hk;
74 int rc = -1;
75
76 rc = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
77 "SYSTEM\\CurrentControlSet\\Services\\FileDisk",
78 0, KEY_READ, &hk);
79 if (rc == ERROR_SUCCESS) {
80 RegCloseKey (hk);
81 rc = 0;
82 }
83 return rc;
84 }
85
86
87 int
88 cryptdisk_available (void)
89 {
90 return (is_nt4 () == 1 && check_filedisk () == 0)? 1 : 0;
91 }
92
93
94 void
95 cryptdisk_cleanup (void)
96 {
97 if (shell32)
98 FreeLibrary (shell32);
99 shell32 = NULL;
100 }
101
102
103 static int
104 num_of_devices (void)
105 {
106 HKEY hk;
107 BYTE buf[32];
108 DWORD n=0, type=0;
109 int rc;
110
111 rc = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
112 "SYSTEM\\CurrentControlSet\\Services\\FileDisk\\Parameters",
113 0, KEY_READ, &hk);
114 if (rc != ERROR_SUCCESS)
115 return -1;
116
117 n = sizeof buf-1;
118 memset (buf, 0, sizeof buf);
119 rc = RegQueryValueEx (hk, "NumberOfDevices", 0, &type, buf, &n);
120 if (rc != ERROR_SUCCESS || type != REG_DWORD)
121 n=0;
122 else
123 n = *buf;
124 RegCloseKey (hk);
125 return n;
126 }
127
128
129 static HWND
130 start_cryptdisk_server (HANDLE * r_proc)
131 {
132 STARTUPINFO si;
133 PROCESS_INFORMATION pi;
134
135 memset (&si, 0, sizeof si);
136 memset (&pi, 0, sizeof pi);
137 si.cb = sizeof si;
138
139 if (CreateProcess (NULL, "CryptdiskSrv", NULL, NULL, FALSE, 0,
140 NULL, NULL, &si, &pi) == FALSE) {
141 msg_box (NULL, _("Could not execute Cryptdisk Server."),
142 _("Cryptdisk Error"), MB_ERR);
143 return NULL;
144 }
145 *r_proc = pi.hProcess;
146 Sleep (300);
147 return FindWindow ("CryptdiskSrv", NULL);
148 }
149
150
151 static int
152 cryptdisk_mount (int devnum,
153 const char * imgfile,
154 u32 size,
155 const char * hdlet)
156 {
157 HWND h;
158 HANDLE proc, wait_ev;
159 COPYDATASTRUCT cds;
160 struct private_ofi_s ofi;
161
162 h = start_cryptdisk_server (&proc);
163 if (!h)
164 return WPTERR_GENERAL;
165 memset (&ofi, 0, sizeof ofi);
166 ofi.cmd = CMD_MOUNT;
167 ofi.devnum = devnum;
168 ofi.filesize.LowPart = size;
169 ofi.drvlet = *hdlet;
170 ofi.readonly = 0;
171 strcpy ((char *)ofi.fname, imgfile);
172 ofi.flen = strlen (imgfile);
173
174 wait_ev = OpenEvent (SYNCHRONIZE, FALSE, "cryptdisksrv.wait");
175 if (!wait_ev)
176 BUG (0);
177 memset (&cds, 0, sizeof cds);
178 cds.cbData = sizeof ofi;
179 cds.lpData = &ofi;
180 SendMessage (h, WM_COPYDATA, (WPARAM)GetDesktopWindow (), (LPARAM)&cds);
181 WaitForSingleObject (wait_ev, INFINITE);
182 CloseHandle (wait_ev);
183 CloseHandle (proc);
184 return 0;
185 }
186
187
188
189 int
190 cryptdisk_unmount (char drivelet, int forced)
191 {
192 HWND h;
193 HANDLE proc;
194 COPYDATASTRUCT cds;
195 struct private_ofi_s ofi;
196
197 h = start_cryptdisk_server (&proc);
198 if (!h)
199 return WPTERR_GENERAL;
200
201 memset (&ofi, 0, sizeof ofi);
202 ofi.cmd = CMD_UMOUNT;
203 ofi.drvlet = drivelet;
204 ofi.forced = forced;
205
206 memset (&cds, 0, sizeof cds);
207 cds.lpData = &ofi;
208 cds.cbData = sizeof ofi;
209 SendMessage (h, WM_COPYDATA, (WPARAM)GetDesktopWindow (), (LPARAM)&cds);
210 CloseHandle (proc);
211
212 return 0;
213 }
214
215 static void
216 print_lasterr (char * prefix)
217 {
218 LPVOID msg;
219
220 FormatMessage(
221 FORMAT_MESSAGE_ALLOCATE_BUFFER |
222 FORMAT_MESSAGE_FROM_SYSTEM |
223 FORMAT_MESSAGE_IGNORE_INSERTS,
224 NULL,
225 GetLastError(),
226 0,
227 (LPTSTR) &msg,
228 0,
229 NULL
230 );
231 MessageBox (NULL, (LPTSTR)msg, prefix, MB_ICONERROR|MB_OK);
232 LocalFree (msg);
233 }
234
235
236 static int
237 filedisk_status (char drivelet, LARGE_INTEGER * size, int * rdonly)
238 {
239 char VolumeName[] = "\\\\.\\ :";
240 HANDLE Device;
241 POPEN_FILE_INFORMATION ofi;
242 DWORD BytesReturned;
243 int n= sizeof (OPEN_FILE_INFORMATION)+ MAX_PATH;
244
245 VolumeName[4] = drivelet;
246
247 Device = CreateFile (VolumeName,
248 GENERIC_READ,
249 FILE_SHARE_READ | FILE_SHARE_WRITE,
250 NULL,
251 OPEN_EXISTING,
252 FILE_FLAG_NO_BUFFERING,
253 NULL);
254
255 if (Device == INVALID_HANDLE_VALUE) {
256 print_lasterr(&VolumeName[4]);
257 return WPTERR_CDISK_OPEN;
258 }
259
260 ofi = (POPEN_FILE_INFORMATION)malloc (n);
261
262 if (!DeviceIoControl (Device,
263 IOCTL_FILE_DISK_QUERY_FILE,
264 NULL,
265 0,
266 ofi,
267 sizeof(OPEN_FILE_INFORMATION) + MAX_PATH,
268 &BytesReturned, NULL)) {
269 print_lasterr (&VolumeName[4]);
270 return WPTERR_CDISK_QUERY;
271 }
272
273 if (BytesReturned < sizeof(OPEN_FILE_INFORMATION)) {
274 SetLastError (ERROR_INSUFFICIENT_BUFFER);
275 print_lasterr (&VolumeName[4]);
276 return WPTERR_CDISK_QUERY;
277 }
278
279 if (size)
280 *size = ofi->FileSize;
281 if (rdonly)
282 *rdonly = ofi->ReadOnly;
283
284 return 0;
285 }
286
287
288 static mount_list_t
289 new_mount_list (const char * drive, int devnum)
290 {
291 mount_list_t n;
292
293 n = (mount_list_t)calloc (1, sizeof *n);
294 if (n) {
295 strcpy (n->drive, drive);
296 n->devnum = devnum;
297 n->ttl = 1;
298 filedisk_status (*drive, &n->size, &n->rdonly);
299 }
300 return n;
301 }
302
303
304 static mount_list_t
305 find_mount_list (mount_list_t root, const char * drive)
306 {
307 mount_list_t n;
308
309 for (n=root; n; n=n->next) {
310 if (n->ttl == 0)
311 continue;
312 if (!strncmp (n->drive, drive, strlen (drive)))
313 return n;
314 }
315 return NULL;
316 }
317
318
319 static void
320 add_mount_list (mount_list_t root, mount_list_t node)
321 {
322 mount_list_t n;
323
324 if (find_mount_list (root, node->drive))
325 return;
326
327 for (n=root; n->next; n=n->next)
328 ;
329 n->next = node;
330 }
331
332
333 static void
334 remove_mount_list (mount_list_t root, mount_list_t node)
335 {
336 mount_list_t n;
337
338 n = find_mount_list (root, node->drive);
339 if (n)
340 n->ttl = 0;
341 }
342
343
344 static void
345 free_mount_list (mount_list_t root)
346 {
347 mount_list_t n;
348
349 while (root) {
350 n = root->next;
351 free (root);
352 root = n;
353 }
354 }
355
356
357 static int
358 last_devnum (mount_list_t root)
359 {
360 mount_list_t n;
361 int devnum=0;
362
363 if (!root)
364 return 0;
365
366 for (n=root; n; n=n->next) {
367 if (devnum < n->devnum)
368 devnum=n->devnum;
369 }
370 return devnum+1;
371 }
372
373
374 static char
375 init_drives (HWND dlg, int ctlid)
376 {
377 char buf[512], drv[5];
378 DWORD n=0, i=0;
379
380 n=GetLogicalDriveStrings (sizeof buf-1, buf);
381 for (i=0; i < n; i++) {
382 memcpy (drv, buf+i, 3); drv[3]=0;
383 i += 3;
384 }
385 if (!dlg && ctlid == -1)
386 return ++drv[0];
387
388 for (++drv[0]; drv[0] < 'Z'; drv[0]++)
389 SendDlgItemMessage (dlg, ctlid, CB_ADDSTRING, 0,
390 (LPARAM)(const char *)drv);
391 SendDlgItemMessage (dlg, ctlid, CB_SETCURSEL, 0, 0);
392 return 0;
393 }
394
395
396 static int
397 check_freespace (const char * imgfile, u32 size)
398 {
399 ULARGE_INTEGER tocaller, total, totfree;
400 char buf[128] = {0};
401
402 if (!strchr (imgfile, ':'))
403 GetCurrentDirectory (sizeof buf-1, buf);
404 else
405 strncpy (buf, imgfile, sizeof buf-1);
406 buf[3] = '\0';
407 GetDiskFreeSpaceEx (buf, &tocaller, &total, &totfree);
408 if (size > tocaller.LowPart)
409 return -1;
410 return 0;
411 }
412
413
414 static void
415 do_check (HWND dlg)
416 {
417 if (!cryptdisk_serv_run ()) { /* xxx */
418 msg_box (dlg, _("The Cryptdisk service seems to be available but "
419 "it is not started yet.\nPlease start the service "
420 "and try again."), _("Cryptdisk Error"), MB_ERR);
421 EndDialog (dlg, TRUE);
422 }
423 }
424
425
426 BOOL CALLBACK
427 cryptdisk_new_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
428 {
429 const char * ciphers [] = {
430 "twofish",
431 NULL
432 };
433 const char * s;
434 char imgfile[128], key[128], drv[3];
435 int i;
436 u32 size=0;
437
438 switch (msg) {
439 case WM_INITDIALOG:
440 do_check (dlg);
441 SetDlgItemInt (dlg, IDC_CDNEW_SIZE, DISK_DEFSIZE, FALSE);
442 for (i=0; (s=ciphers[i]); i++)
443 SendDlgItemMessage (dlg, IDC_CDNEW_CIPHERS, CB_ADDSTRING,
444 0, (LPARAM)(const char *) s);
445 SendDlgItemMessage (dlg, IDC_CDNEW_CIPHERS, CB_SETCURSEL, 0, 0);
446 center_window (dlg, NULL);
447 SetForegroundWindow (dlg);
448 break;
449
450 case WM_COMMAND:
451 switch (LOWORD (wparam)) {
452 case IDOK:
453 i = GetDlgItemText (dlg, IDC_CDNEW_IMGFILE, imgfile, sizeof imgfile-1);
454 if (!i) {
455 msg_box (dlg, _("Please enter a name for the image file."),
456 _("Cryptdisk"), MB_ERR);
457 return FALSE;
458 }
459 if (file_exist_check (imgfile) == 0) {
460 i = msg_box (dlg, _("This volume file already exists.\n"
461 "Do you want to overwrite it?"),
462 _("Cryptdisk Warning"), MB_YESNO|MB_WARN);
463 if (i == IDNO)
464 return FALSE;
465 }
466 for (i=0; i < (int)strlen (imgfile); i++)
467 imgfile[i] = toupper (imgfile[i]);
468 size = GetDlgItemInt (dlg, IDC_CDNEW_SIZE, NULL, FALSE);
469 if (!size) {
470 msg_box (dlg, _("Please enter the size for the volume"),
471 _("Cryptdisk"), MB_INFO);
472 return FALSE;
473 }
474 size *= 1024; /*KB*/
475 if (check_freespace (imgfile, (size*1024))) {
476 msg_box (dlg, _("There is not enough free disk space to "
477 "store the volume."), _("Cryptdisk"), MB_ERR);
478 return FALSE;
479 }
480 i = GetDlgItemText (dlg, IDC_CDNEW_PASS, key, sizeof key-1);
481 if (!i) {
482 msg_box (dlg, _("Please enter a passphrase for the volume."),
483 _("Cryptdisk"), MB_ERR);
484 return FALSE;
485 }
486 strcpy (drv, "?:\\");
487 drv[0] = init_drives (NULL, -1);
488 i = cryptdisk_mount (last_devnum (mounted), imgfile, size, drv);
489 if (!i)
490 shfmt (dlg, drv[0] - 65, 0, 0);
491 break;
492 case IDCANCEL:
493 EndDialog (dlg, FALSE);
494 break;
495 }
496 break;
497
498 }
499
500 return FALSE;
501 }
502
503
504 BOOL CALLBACK
505 cryptdisk_mount_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
506 {
507 const char * s_imgfile;
508 char buf[8], drive[8], passwd[64], imgfile[128];
509 int n, i, devnum=0;
510 int rc;
511
512 switch (msg) {
513 case WM_INITDIALOG:
514 do_check (dlg);
515 s_imgfile = (const char *)lparam;
516 if (s_imgfile)
517 SetDlgItemText (dlg, IDC_CDMOUNT_IMGFILE, s_imgfile);
518 init_drives (dlg, IDC_CDMOUNT_DRV);
519 n = num_of_devices ();
520 if (n == -1) {
521 msg_box (dlg, _("Cannot determine the number of drives."),
522 _("Cryptdisk Error"), MB_ERR);
523 EndDialog (dlg, FALSE);
524 }
525 for (i=last_devnum (mounted); i < n; i++) {
526 sprintf (buf, "%d", i);
527 SendDlgItemMessage (dlg, IDC_CDMOUNT_ID, CB_ADDSTRING, 0,
528 (LPARAM)(const char *)buf);
529 }
530 SendDlgItemMessage (dlg, IDC_CDMOUNT_ID, CB_SETCURSEL, 0, 0);
531 center_window (dlg, NULL);
532 SetForegroundWindow (dlg);
533 break;
534
535 case WM_COMMAND:
536 switch (LOWORD (wparam)) {
537 case IDC_CDMOUNT_SELFILE:
538 s_imgfile = get_fileopen_dlg (dlg, _("Select Crypdisk Volume"),
539 NULL, NULL);
540 if (s_imgfile != NULL)
541 SetDlgItemText (dlg, IDC_CDMOUNT_IMGFILE, s_imgfile);
542 break;
543
544 case IDOK:
545 n = item_get_text_length (dlg, IDC_CDMOUNT_IMGFILE);
546 if (!n) {
547 msg_box (dlg, _("Please enter the name of the image file."),
548 _("Cryptdisk Error"), MB_ERR);
549 return FALSE;
550 }
551 n = item_get_text_length (dlg, IDC_CDMOUNT_PASS);
552 if (!n) {
553 msg_box (dlg, _("Please enter a password."),
554 _("Cryptdisk Error"), MB_ERR);
555 return FALSE;
556 }
557 devnum = GetDlgItemInt (dlg, IDC_CDMOUNT_ID, NULL, FALSE);
558 GetDlgItemText (dlg, IDC_CDMOUNT_DRV, drive, sizeof drive-1);
559 GetDlgItemText (dlg, IDC_CDMOUNT_PASS, passwd, sizeof passwd-1);
560 GetDlgItemText (dlg, IDC_CDMOUNT_IMGFILE, imgfile, sizeof imgfile-1);
561 if (file_exist_check (imgfile)) {
562 msg_box (dlg, _("Image file does not exist or could not be accessed."),
563 _("Cryptdisk Error"), MB_ERR);
564 return FALSE;
565 }
566 rc = cryptdisk_mount (devnum, imgfile, 0, drive);
567 if (!rc) {
568 mount_list_t n = new_mount_list (drive, devnum);
569 if (!mounted)
570 mounted = n;
571 else
572 add_mount_list (mounted, n);
573 EndDialog (dlg, TRUE);
574 }
575 else
576 msg_box (dlg, winpt_strerror (rc), _("Cryptdisk Error"), MB_ERR);
577 break;
578
579 case IDCANCEL:
580 EndDialog (dlg, FALSE);
581 break;
582 }
583 break;
584 }
585 return FALSE;
586 }
587
588
589 static void
590 load_devs_from_mountlist (HWND dlg, int ctlid)
591 {
592 mount_list_t n;
593 char buf[128];
594
595 if (!mounted)
596 return;
597
598 for (n=mounted; n; n=n->next) {
599 if (n->ttl == 0)
600 continue;
601 _snprintf (buf, sizeof buf-1, _("Drive %s (ID %d); Size %d MB, Readonly=%s"),
602 n->drive, n->devnum, n->size.LowPart/1024/1024,
603 n->rdonly? "true" : "false");
604 SendDlgItemMessage (dlg, ctlid, LB_ADDSTRING, 0, (LPARAM)(const char *)buf);
605 }
606
607 }
608
609
610 static void
611 do_reaping (void)
612 {
613 mount_list_t n;
614 int ndevs=0, numount=0;
615
616 for (n=mounted; n; n=n->next) {
617 if (n->ttl == 0)
618 numount++;
619 ndevs++;
620 }
621 if (ndevs == numount) {
622 free_mount_list (mounted);
623 mounted = NULL;
624 }
625 }
626
627
628 BOOL CALLBACK
629 cryptdisk_umount_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
630 {
631 mount_list_t vol;
632 char buf[128];
633 int n, rc=0;
634
635 switch (msg) {
636 case WM_INITDIALOG:
637 do_check (dlg);
638 load_devs_from_mountlist (dlg, IDC_CDUMOUNT_LIST);
639 center_window (dlg, NULL);
640 SetForegroundWindow (dlg);
641 break;
642
643 case WM_DESTROY:
644 do_reaping ();
645 break;
646
647 case WM_COMMAND:
648 switch (LOWORD (wparam)) {
649 case IDOK:
650 n = SendDlgItemMessage (dlg, IDC_CDUMOUNT_LIST, LB_GETCURSEL, 0, 0);
651 if (n == LB_ERR) {
652 msg_box (dlg, _("Please select one drive to umount."), _("Cryptdisk"), MB_INFO);
653 return FALSE;
654 }
655 SendDlgItemMessage (dlg, IDC_CDUMOUNT_LIST, LB_GETTEXT, n,
656 (LPARAM)(char *)buf);
657 strcpy (buf, buf+6);
658 buf[2] = '\0';
659 vol = find_mount_list (mounted, buf);
660 if (!vol)
661 BUG (0);
662 rc = cryptdisk_unmount (buf[0], 0);
663 //if (rc == WPTERR_CDISK_LOCK)
664 // rc = cryptdisk_unmount (buf[0], 0);
665 if (!rc) {
666 SendDlgItemMessage (dlg, IDC_CDUMOUNT_LIST, LB_DELETESTRING, (WPARAM)n, 0);
667 remove_mount_list (mounted, vol);
668 }
669 else
670 msg_box (dlg, winpt_strerror (rc), _("Cryptdisk Error"), MB_ERR);
671 break;
672 case IDCANCEL:
673 EndDialog (dlg, FALSE);
674 break;
675 }
676 break;
677 }
678
679 return FALSE;
680 }
681
682
683 int
684 cryptdisk_serv_run (void)
685 {
686 SC_HANDLE hd;
687 ENUM_SERVICE_STATUS ess[4096];
688 DWORD nservs=0, dummy=0;
689 DWORD i;
690 int rc=0;
691
692 hd = OpenSCManager (NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
693 if (!hd)
694 return 0;
695
696 EnumServicesStatus (hd, SERVICE_DRIVER, SERVICE_ACTIVE,
697 (LPENUM_SERVICE_STATUS)&ess,
698 sizeof ess-1, &dummy, &nservs, &dummy);
699
700 for (i=0; i < nservs; i++) {
701 if (!strnicmp ("FileDisk", ess[i].lpDisplayName, 8)) {
702 rc = 1;
703 break;
704 }
705 }
706
707 CloseServiceHandle (hd);
708 return rc;
709 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26