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

Annotation of /trunk/Src/wptCryptdisk.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (hide annotations)
Wed Oct 12 10:04:26 2005 UTC (19 years, 4 months ago) by twoaday
File size: 16478 byte(s)
First testing phase finished.
Provide bug fixes for a lot of (minor) problems.

1 twoaday 2 /* 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 twoaday 23 center_window (dlg, NULL);
442 twoaday 2 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 twoaday 23 center_window (dlg, NULL);
527 twoaday 2 SetForegroundWindow (dlg);
528     break;
529    
530     case WM_COMMAND:
531     switch (LOWORD (wparam)) {
532     case IDC_CDMOUNT_SELFILE:
533 twoaday 25 s_imgfile = get_fileopen_dlg (dlg, _("Select Crypdisk Volume"),
534 twoaday 2 NULL, NULL);
535 twoaday 23 if (s_imgfile != NULL)
536 twoaday 2 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 twoaday 23 center_window (dlg, NULL);
635 twoaday 2 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