1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 
7 /// Initial drive selection from command line.
8 CHAR szDisc[4] = "";
9 BOOL bChanger = FALSE;
10 
11 /// Return CD-RW device type
12 JS_DEVICE_TYPE
CheckCDType(PCHAR m_szFile,PCHAR VendorId)13 CheckCDType(
14     PCHAR m_szFile,
15     PCHAR VendorId
16     )
17 {
18     HANDLE hDevice;
19     CHAR szDeviceName[256];
20     CHAR ioBuf[4096];
21     ULONG RC;
22     BOOL DvdRW  = false;
23     BOOL DvdpRW = false;
24     BOOL DvdRAM = false;
25     BOOL DvdpR = false;
26     BOOL DvdR = false;
27 
28     bChanger = FALSE;
29 
30     // Make string representing full path
31     sprintf(szDeviceName, "\\\\.\\%s", m_szFile);
32     if (szDeviceName[strlen(szDeviceName)-1] == '\\') szDeviceName[strlen(szDeviceName)-1] = '\0';
33 
34     // Open device volume
35     hDevice = OpenOurVolume(szDeviceName);
36 
37     if (hDevice == ((HANDLE)-1)) {
38         strcpy(VendorId,"");
39         return BUSY;
40     } else {
41 
42         // Get our cdrw.sys signature
43         RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_SIGNATURE,hDevice,
44                             &ioBuf,sizeof(GET_SIGNATURE_USER_OUT),
45                             &ioBuf,sizeof(GET_SIGNATURE_USER_OUT),FALSE,NULL);
46 
47         if (RC == 1) {
48             // Get device information
49             RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_DEVICE_INFO,hDevice,
50                                &ioBuf,sizeof(GET_DEVICE_INFO_USER_OUT),
51                                &ioBuf,sizeof(GET_DEVICE_INFO_USER_OUT),FALSE,NULL);
52             if (RC != 1) {
53                 strcpy(VendorId,"Unknown Vendor");
54             } else {
55                 if(((PGET_DEVICE_INFO_USER_OUT)&ioBuf)->Features & CDRW_FEATURE_CHANGER)
56                     bChanger = TRUE;
57                 strcpy(VendorId,(PCHAR)&(((PGET_DEVICE_INFO_USER_OUT)&ioBuf)->VendorId[0]));
58                 if (((PGET_DEVICE_INFO_USER_OUT)&ioBuf)->Features & CDRW_FEATURE_GET_CFG) {
59                     DvdRW = (((PGET_DEVICE_INFO_USER_OUT)&ioBuf)->Features2[0] >> PFNUM_DVDRW_RESTRICTED_OVERWRITE) & 1;
60                     DvdRAM = (((PGET_DEVICE_INFO_USER_OUT)&ioBuf)->Features2[0] >> PFNUM_DVDRAM) & 1;
61                     DvdpRW = (((PGET_DEVICE_INFO_USER_OUT)&ioBuf)->Features2[0] >> PFNUM_DVDpRW) & 1;
62                     DvdR = (((PGET_DEVICE_INFO_USER_OUT)&ioBuf)->Features2[0] >> PFNUM_DVDR) & 1;
63                     DvdpR = (((PGET_DEVICE_INFO_USER_OUT)&ioBuf)->Features2[0] >> PFNUM_DVDpR) & 1;
64                 }
65             }
66 
67             // Get device capabilities
68             RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_CAPABILITIES,hDevice,
69                                 &ioBuf,sizeof(GET_CAPABILITIES_USER_OUT),
70                                 &ioBuf,sizeof(GET_CAPABILITIES_USER_OUT),FALSE,NULL);
71             if(RC != 1) {
72                 CloseHandle(hDevice);
73                 return OTHER;
74             }
75 
76             // Check capabilities
77             if(((PGET_CAPABILITIES_USER_OUT)&ioBuf)->WriteCap & (DevCap_write_cd_r | DevCap_write_cd_rw | DevCap_write_dvd_ram | DevCap_write_dvd_r) ||
78               DvdRW || DvdpRW || DvdRAM) {
79 
80                 if (DvdRAM || ((PGET_CAPABILITIES_USER_OUT)&ioBuf)->WriteCap & DevCap_write_dvd_ram) {
81                     CloseHandle(hDevice);
82                     return DVDRAM;
83                 }
84 /*                if (DvdR) {
85                     CloseHandle(hDevice);
86                     return DVDR;
87                 }*/
88                 if (DvdRW) {
89                     CloseHandle(hDevice);
90                     return DVDRW;
91                 }
92                 if (DvdpRW) {
93                     CloseHandle(hDevice);
94                     return DVDPRW;
95                 }
96 /*                if (DvdpR) {
97                     CloseHandle(hDevice);
98                     return DVDPR;
99                 }*/
100                 if (((PGET_CAPABILITIES_USER_OUT)&ioBuf)->WriteCap & DevCap_write_dvd_r) {
101                     CloseHandle(hDevice);
102                     return DVDR;
103                 }
104                 if (((PGET_CAPABILITIES_USER_OUT)&ioBuf)->WriteCap & DevCap_write_cd_rw) {
105                     CloseHandle(hDevice);
106                     return CDRW;
107                 }
108                 if (((PGET_CAPABILITIES_USER_OUT)&ioBuf)->WriteCap & DevCap_write_cd_r) {
109                     CloseHandle(hDevice);
110                     return CDR;
111                 }
112             }
113             else {
114                 CloseHandle(hDevice);
115                 return OTHER;
116             }
117         } else {
118             strcpy(VendorId,"Unknown Vendor");
119         }
120         CloseHandle(hDevice);
121     }
122 
123     return OTHER;
124 } // end CheckCDType()
125 
126 /** Intialize asbtract device list via calls to CallBack function.
127     \param hDlg Not used.
128     \param hwndControl Passed to the CallBack function. See #PADD_DEVICE.
129     \param CallBack Callback function. Called on each CD device in system.
130 */
131 void
InitDeviceList(HWND hDlg,HWND hwndControl,PADD_DEVICE CallBack)132 InitDeviceList(
133     HWND hDlg,
134     HWND hwndControl,
135     PADD_DEVICE CallBack
136     )
137 {
138     char    Buffer[MAX_PATH] = "";
139     char    VendorId[25];
140     char    seps[] = ",";
141     char*   token;
142     char    info[MAX_PATH];
143     bool    add_drive = false;
144 
145     JS_DEVICE_TYPE  drive_type;
146 
147     // Get all device letter in system
148     GetLogicalDriveStrings((DWORD)MAX_PATH,(LPTSTR)&Buffer);
149     token = (char *)&Buffer;
150     // Replace all zeroes with comma.
151     while (token != NULL) {
152         token = (char *)memchr(Buffer,'\0',MAX_PATH);
153         if (token) {
154             if (*(token-1) == ',') {
155                 token = NULL;
156             } else {
157                 *token=',';
158             }
159         }
160     }
161     // Parse string of drive letters separated by comma
162     token = strtok((char *)&Buffer,seps);
163     while (token != NULL) {
164         add_drive = false;
165         switch (GetDriveType(token)) {
166 /*
167             case DRIVE_FIXED:
168                 add_drive = true;
169                 break;
170 */
171             case DRIVE_CDROM:
172                 // Determine CD/DVD-ROM type (R,RW,RAM,other)
173                 drive_type = CheckCDType(token,&VendorId[0]);
174                 add_drive = true;
175                 break;
176         }
177         if (add_drive) {
178 
179             // Append to drive letter VendorId
180             strncpy(info,token,strlen(token)-1);
181             info[strlen(token)-1]='\0';
182             strcat(info,"  ");
183             strcat(info,VendorId);
184 
185             BOOL bSelect = !strcmp(strupr(szDisc),strupr(token));
186             if (drive_type != OTHER) {
187                 CallBack(hwndControl,token,info,MediaTypeStrings[drive_type],bSelect);
188             } else {
189                 CallBack(hwndControl,token,info,"[Unsupported]",FALSE);
190             }
191 
192         }
193         // Move to the next drive letter in string
194         token = strtok(NULL,seps);
195     }
196 } // end InitDeviceList()
197 
198 HANDLE
FmtAcquireDrive_(PCHAR _Drive,CHAR Level)199 FmtAcquireDrive_(
200     PCHAR _Drive,
201     CHAR Level
202     )
203 {
204     WCHAR LockName[32];
205     HANDLE evt;
206 
207     WCHAR Drive[1];
208     Drive[0] = _Drive[0] & ~('a' ^ 'A');
209 
210     swprintf(LockName, L"DwFmtLock_%1.1S%d", Drive, Level);
211     evt = CreatePublicEvent(LockName);
212     if(!evt) {
213         return NULL;
214     }
215     if(GetLastError() == ERROR_ALREADY_EXISTS) {
216         CloseHandle(evt);
217         return INVALID_HANDLE_VALUE;
218     }
219     return evt;
220 } // end FmtAcquireDrive_()
221 
222 HANDLE
FmtAcquireDrive(PCHAR Drive,CHAR Level)223 FmtAcquireDrive(
224     PCHAR Drive,
225     CHAR Level
226     )
227 {
228     HANDLE evt;
229 
230     evt = FmtAcquireDrive_(Drive, Level);
231     if(!evt || evt == INVALID_HANDLE_VALUE) {
232         return NULL;
233     }
234     return evt;
235 } // end FmtAcquireDrive()
236 
237 BOOLEAN
FmtIsDriveAcquired(PCHAR Drive,CHAR Level)238 FmtIsDriveAcquired(
239     PCHAR Drive,
240     CHAR Level
241     )
242 {
243     HANDLE evt;
244 
245     evt = FmtAcquireDrive_(Drive, Level);
246     if(evt == INVALID_HANDLE_VALUE) {
247         return TRUE;
248     }
249     if(evt) {
250         CloseHandle(evt);
251     }
252     return FALSE;
253 } // end FmtIsDriveAcquired()
254 
255 VOID
FmtReleaseDrive(HANDLE evt)256 FmtReleaseDrive(
257     HANDLE evt
258     )
259 {
260     if(evt) {
261         CloseHandle(evt);
262     }
263 } // end FmtReleaseDrive()
264