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

Annotation of /trunk/Src/wptCryptdisk.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 36 - (hide 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 werner 36 /* 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