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

Contents of /trunk/Src/wptCryptdisk.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations)
Mon Jan 31 11:02:21 2005 UTC (20 years, 1 month ago) by twoaday
File size: 16496 byte(s)
WinPT initial checkin.


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26