ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/cdenable/eject_nt.cpp
Revision: 1.4
Committed: 2008-01-01T09:40:34Z (16 years, 10 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * eject_nt.cpp - cd eject routines for WinNT (derived from MS samples)
3     *
4 gbeauche 1.4 * Basilisk II (C) 1997-2008 Christian Bauer
5 gbeauche 1.1 *
6     * Windows platform specific code copyright (C) Lauri Pesonen
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21     */
22    
23     #include "sysdeps.h"
24    
25     #include "windows.h"
26     #include <winioctl.h>
27    
28     // Prototypes
29    
30     extern "C" {
31    
32     #include "eject_nt.h"
33    
34     LPTSTR szVolumeFormat = TEXT("\\\\.\\%c:");
35     LPTSTR szRootFormat = TEXT("%c:\\");
36     LPTSTR szErrorFormat = TEXT("Error %d: %s\n");
37    
38     void ReportError(LPTSTR szMsg)
39     {
40     // _tprintf(szErrorFormat, GetLastError(), szMsg);
41     }
42    
43     HANDLE OpenVolume(TCHAR cDriveLetter)
44     {
45     HANDLE hVolume;
46     UINT uDriveType;
47     TCHAR szVolumeName[8];
48     TCHAR szRootName[5];
49     DWORD dwAccessFlags;
50    
51     wsprintf(szRootName, szRootFormat, cDriveLetter);
52    
53     uDriveType = GetDriveType(szRootName);
54     switch(uDriveType) {
55     case DRIVE_REMOVABLE:
56     dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
57     break;
58     case DRIVE_CDROM:
59     dwAccessFlags = GENERIC_READ;
60     break;
61     default:
62     // _tprintf(TEXT("Cannot eject. Drive type is incorrect.\n"));
63     return INVALID_HANDLE_VALUE;
64     }
65    
66     wsprintf(szVolumeName, szVolumeFormat, cDriveLetter);
67    
68     hVolume = CreateFile( szVolumeName,
69     dwAccessFlags,
70     FILE_SHARE_READ | FILE_SHARE_WRITE,
71     NULL,
72     OPEN_EXISTING,
73     0,
74     NULL );
75     if (hVolume == INVALID_HANDLE_VALUE)
76     ReportError(TEXT("CreateFile"));
77    
78     return hVolume;
79     }
80    
81     BOOL CloseVolume(HANDLE hVolume)
82     {
83     return CloseHandle(hVolume);
84     }
85    
86     #define LOCK_TIMEOUT 1000 // 1 second
87     #define LOCK_RETRIES 20
88    
89     BOOL LockVolume(HANDLE hVolume)
90     {
91     DWORD dwBytesReturned;
92     DWORD dwSleepAmount;
93     int nTryCount;
94    
95     dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES;
96    
97     // Do this in a loop until a timeout period has expired
98     for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) {
99     if (DeviceIoControl(hVolume,
100     FSCTL_LOCK_VOLUME,
101     NULL, 0,
102     NULL, 0,
103     &dwBytesReturned,
104     NULL))
105     return TRUE;
106    
107     Sleep(dwSleepAmount);
108     }
109    
110     return FALSE;
111     }
112    
113     BOOL DismountVolume(HANDLE hVolume)
114     {
115     DWORD dwBytesReturned;
116    
117     return DeviceIoControl( hVolume,
118     FSCTL_DISMOUNT_VOLUME,
119     NULL, 0,
120     NULL, 0,
121     &dwBytesReturned,
122     NULL);
123     }
124    
125     BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval)
126     {
127     DWORD dwBytesReturned;
128     PREVENT_MEDIA_REMOVAL PMRBuffer;
129    
130     PMRBuffer.PreventMediaRemoval = fPreventRemoval;
131    
132     return DeviceIoControl( hVolume,
133     IOCTL_STORAGE_MEDIA_REMOVAL,
134     &PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
135     NULL, 0,
136     &dwBytesReturned,
137     NULL);
138     }
139    
140     BOOL AutoEjectVolume( HANDLE hVolume, BOOL reload )
141     {
142     DWORD dwBytesReturned;
143    
144     return DeviceIoControl( hVolume,
145     reload ? IOCTL_STORAGE_LOAD_MEDIA : IOCTL_STORAGE_EJECT_MEDIA,
146     NULL, 0,
147     NULL, 0,
148     &dwBytesReturned,
149     NULL);
150     }
151    
152     BOOL EjectVolume( TCHAR cDriveLetter, BOOL reload )
153     {
154     HANDLE hVolume;
155    
156     BOOL fRemoveSafely = FALSE;
157     BOOL fAutoEject = FALSE;
158    
159     // Open the volume.
160     hVolume = OpenVolume(cDriveLetter);
161     if (hVolume == INVALID_HANDLE_VALUE)
162     return FALSE;
163    
164     // Lock and dismount the volume.
165     if (LockVolume(hVolume) && DismountVolume(hVolume)) {
166     fRemoveSafely = TRUE;
167    
168     // Set prevent removal to false and eject the volume.
169     if (PreventRemovalOfVolume(hVolume, FALSE) &&
170     AutoEjectVolume(hVolume,reload))
171     fAutoEject = TRUE;
172     }
173    
174     // Close the volume so other processes can use the drive.
175     if (!CloseVolume(hVolume))
176     return FALSE;
177    
178     /*
179     if (fAutoEject)
180     printf("Media in Drive %c has been ejected safely.\n", cDriveLetter);
181     else {
182     if (fRemoveSafely)
183     printf("Media in Drive %c can be safely removed.\n", cDriveLetter);
184     }
185     */
186    
187     return TRUE;
188     }
189    
190     } // extern "C"