sbIPDSysDevice.cpp
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 :miv */
3 /*
4 //=BEGIN SONGBIRD GPL
5 //
6 // This file is part of the Songbird web player.
7 //
8 // Copyright(c) 2005-2009 POTI, Inc.
9 // http://www.songbirdnest.com
10 //
11 // This file may be licensed under the terms of of the
12 // GNU General Public License Version 2 (the GPL).
13 //
14 // Software distributed under the License is distributed
15 // on an AS IS basis, WITHOUT WARRANTY OF ANY KIND, either
16 // express or implied. See the GPL for the specific language
17 // governing rights and limitations.
18 //
19 // You should have received a copy of the GPL along with this
20 // program. If not, go to http://www.gnu.org/licenses/gpl.html
21 // or write to the Free Software Foundation, Inc.,
22 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 //
24 //=END SONGBIRD GPL
25 */
26 
27 //------------------------------------------------------------------------------
28 //
29 // iPod system dependent device services.
30 //
31 //------------------------------------------------------------------------------
32 
38 //------------------------------------------------------------------------------
39 //
40 // iPod system dependent device imported services.
41 //
42 //------------------------------------------------------------------------------
43 
44 // Self imports.
45 #include "sbIPDSysDevice.h"
46 
47 // Local imports.
48 #include "sbIPDLog.h"
49 
50 // Mozilla imports.
51 #include <nsIPropertyBag2.h>
52 #include <nsIWritablePropertyBag.h>
53 #include <prprf.h>
54 
55 // Win32 imports.
56 #include <devioctl.h>
57 
58 #include <ntddstor.h>
59 
60 // Songbird imports
62 #include <sbDebugUtils.h>
63 
64 //------------------------------------------------------------------------------
65 //
66 // iPod system dependent device sbIDevice services.
67 //
68 //------------------------------------------------------------------------------
69 
74 NS_IMETHODIMP
76 {
77  CONFIGRET cfgRet;
78  nsresult rv;
79 
80  // call the parent
81  rv = sbIPDDevice::Eject();
82  NS_ENSURE_SUCCESS(rv, rv);
83 
84  // Get the parent device instance data record.
85  DEVINST parentDevInst;
86  cfgRet = CM_Get_Parent(&parentDevInst, mDevInst, 0);
87  NS_ENSURE_TRUE(cfgRet == CR_SUCCESS, NS_ERROR_FAILURE);
88 
89  // Try ejecting the device three times.
90  WCHAR vetoName[MAX_PATH];
91  PNP_VETO_TYPE vetoType;
92  PRBool ejected = PR_FALSE;
93  for (int i = 0; i < 3; i++) {
94  // Try ejecting using CM_Query_And_Remove_SubTree.
95  cfgRet = CM_Query_And_Remove_SubTreeW(parentDevInst,
96  &vetoType,
97  vetoName,
98  MAX_PATH,
99  0);
100  if (cfgRet == CR_SUCCESS) {
101  ejected = PR_TRUE;
102  break;
103  }
104 
105  // Try ejecting using CM_Request_DeviceEject.
106  cfgRet = CM_Request_Device_Eject(parentDevInst,
107  &vetoType,
108  vetoName,
109  MAX_PATH,
110  0);
111  if (cfgRet == CR_SUCCESS) {
112  ejected = PR_TRUE;
113  break;
114  }
115  }
116 
117  // Try one last time and let the PnP manager notify the user of failure.
118  if (!ejected) {
119  cfgRet = CM_Request_Device_Eject(parentDevInst,
120  NULL,
121  NULL,
122  0,
123  0);
124  NS_ENSURE_TRUE(cfgRet == CR_SUCCESS, NS_ERROR_FAILURE);
125  }
126 
127  return NS_OK;
128 }
129 
130 
131 //------------------------------------------------------------------------------
132 //
133 // iPod system dependent device services
134 //
135 //------------------------------------------------------------------------------
136 
144 sbIPDSysDevice::sbIPDSysDevice(const nsID& aControllerID,
145  nsIPropertyBag* aProperties) :
146  sbIPDDevice(aControllerID, aProperties),
147  mProperties(aProperties)
148 {
150 
151  // Log progress.
152  LOG("Enter: sbIPDSysDevice::sbIPDSysDevice\n");
153 
154  // Validate parameters.
155  NS_ASSERTION(aProperties, "aProperties is null");
156 }
157 
158 
164 {
165  // Log progress.
166  LOG("Enter: sbIPDSysDevice::~sbIPDSysDevice\n");
167 
168  // Finalize the iPod system dependent device object.
169  Finalize();
170 }
171 
172 
177 nsresult
179 {
180  nsresult rv;
181 
182  // Get the device properties.
183  nsCOMPtr<nsIPropertyBag2> properties = do_QueryInterface(mProperties, &rv);
184  NS_ENSURE_SUCCESS(rv, rv);
185  nsCOMPtr<nsIWritablePropertyBag> writeProperties =
186  do_QueryInterface(mProperties, &rv);
187  NS_ENSURE_SUCCESS(rv, rv);
188 
189  // Get the device drive letter.
190  char driveLetter;
191  nsCAutoString nsDriveLetter;
192  rv = properties->GetPropertyAsACString(NS_LITERAL_STRING("DriveLetter"),
193  nsDriveLetter);
194  NS_ENSURE_SUCCESS(rv, rv);
195  driveLetter = nsDriveLetter.get()[0];
196 
197  // Get the device instance.
198  rv = GetDevInst(driveLetter, &mDevInst);
199  NS_ENSURE_SUCCESS(rv, rv);
200 
201  // Add the device mount path property.
202  nsAutoString mountPath;
203  mountPath.Assign(NS_ConvertUTF8toUTF16(nsDriveLetter));
204  mountPath.AppendLiteral(":\\");
205  rv = writeProperties->SetProperty(NS_LITERAL_STRING("MountPath"),
206  sbIPDVariant(mountPath).get());
207  NS_ENSURE_SUCCESS(rv, rv);
208 
209  // Get the Firewire GUID property.
210  nsAutoString firewireGUID;
211  rv = GetFirewireGUID(firewireGUID);
212  NS_ENSURE_SUCCESS(rv, rv);
213  rv = writeProperties->SetProperty(NS_LITERAL_STRING("FirewireGUID"),
214  sbIPDVariant(firewireGUID).get());
215  NS_ENSURE_SUCCESS(rv, rv);
216 
217  // Add the device manufacturer and model number properties.
218  rv = writeProperties->SetProperty
219  (NS_LITERAL_STRING(SB_DEVICE_PROPERTY_MANUFACTURER),
220  sbIPDVariant("Apple").get());
221  NS_ENSURE_SUCCESS(rv, rv);
222  rv = writeProperties->SetProperty(NS_LITERAL_STRING(SB_DEVICE_PROPERTY_MODEL),
223  sbIPDVariant("iPod").get());
224  NS_ENSURE_SUCCESS(rv, rv);
225 
226  // Add the device serial number property.
227  //XXXeps use Firewire GUID for now.
228  rv = writeProperties->SetProperty
229  (NS_LITERAL_STRING(SB_DEVICE_PROPERTY_SERIAL_NUMBER),
230  sbIPDVariant(firewireGUID).get());
231  NS_ENSURE_SUCCESS(rv, rv);
232 
233  // Initialize the iPod device object.
235  NS_ENSURE_SUCCESS(rv, rv);
236 
237  return NS_OK;
238 }
239 
240 
245 void
247 {
248  // Finalize the iPod device object.
250 }
251 
252 
253 //------------------------------------------------------------------------------
254 //
255 // Internal iPod system dependent device services
256 //
257 //------------------------------------------------------------------------------
258 
265 nsresult
266 sbIPDSysDevice::GetFirewireGUID(nsAString& aFirewireGUID)
267 {
268  CONFIGRET cfgRet;
269 
270  // Get the parent device instance data record.
271  DEVINST devInst;
272  cfgRet = CM_Get_Parent(&devInst, mDevInst, 0);
273  NS_ENSURE_TRUE(cfgRet == CR_SUCCESS, NS_ERROR_FAILURE);
274 
275  // Get the device ID.
276  WCHAR wDeviceID[256];
277  nsAutoString deviceID;
278  cfgRet = CM_Get_Device_IDW(devInst, wDeviceID, sizeof (wDeviceID), 0);
279  NS_ENSURE_TRUE(cfgRet == CR_SUCCESS, NS_ERROR_FAILURE);
280  deviceID.Assign(wDeviceID);
281 
282  // Get the Firewire GUID from the serial number.
283  PRInt32 pos = deviceID.RFindChar('\\');
284  NS_ENSURE_TRUE(pos != -1, NS_ERROR_FAILURE);
285  aFirewireGUID = Substring(deviceID, pos + 1, 16);
286 
287  return NS_OK;
288 }
289 
290 
299 nsresult
300 sbIPDSysDevice::GetDevInst(char aDriveLetter,
301  DEVINST* aDevInst)
302 {
303  // Validate arguments.
304  NS_ASSERTION(aDevInst, "aDevInst is null");
305 
306  // Function variables.
307  GUID guid = GUID_DEVINTERFACE_DISK;
308  nsresult rv;
309 
310  // Produce the device path.
311  char cDevPath[8];
312  nsAutoString devPath;
313  PR_snprintf(cDevPath, sizeof(cDevPath), "\\\\.\\%c:", aDriveLetter);
314  devPath.AssignLiteral(cDevPath);
315 
316  // Get the target device number.
317  ULONG targetDevNum;
318  rv = GetDevNum(devPath.get(), &targetDevNum);
319  NS_ENSURE_SUCCESS(rv, rv);
320 
321  // Get the volume interface device class info and set up for auto-disposal.
322  HDEVINFO devInfo = SetupDiGetClassDevsW
323  (&guid,
324  NULL,
325  NULL,
326  DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
327  NS_ENSURE_TRUE(devInfo != INVALID_HANDLE_VALUE, NS_ERROR_FAILURE);
328  sbIPDAutoDevInfo autoDevInfo(devInfo);
329 
330  // Search for the device instance with a matching device number.
331  DEVINST devInst;
332  for (DWORD devIndex = 0; ; devIndex++) {
333  // Get the next device detail data and set it up for auto-disposal.
334  PSP_DEVICE_INTERFACE_DETAIL_DATA devIfDetailData;
335  SP_DEVINFO_DATA devInfoData;
336  rv = GetDevDetail(&devIfDetailData,
337  &devInfoData,
338  devInfo,
339  &guid,
340  devIndex);
341  NS_ENSURE_TRUE(rv != NS_ERROR_NOT_AVAILABLE, NS_ERROR_NOT_AVAILABLE);
342  if (NS_FAILED(rv))
343  continue;
345  (devIfDetailData);
346 
347  // Get the next device number.
348  ULONG devNum;
349  rv = GetDevNum(devIfDetailData->DevicePath, &devNum);
350  NS_ENSURE_SUCCESS(rv, rv);
351 
352  // Check if the device number matches the iPod device number.
353  if (devNum == targetDevNum) {
354  devInst = devInfoData.DevInst;
355  break;
356  }
357  }
358 
359  // Return results.
360  *aDevInst = devInst;
361 
362  return NS_OK;
363 }
364 
365 
374 nsresult
375 sbIPDSysDevice::GetDevNum(LPCTSTR aDevPath,
376  ULONG* aDevNum)
377 {
378  // Validate arguments.
379  NS_ASSERTION(aDevPath, "aDevPath is null");
380  NS_ASSERTION(aDevNum, "aDevNum is null");
381 
382  // Function variables.
383  BOOL success;
384 
385  // Create a device file and set it up for auto-disposal.
386  HANDLE devFile = CreateFileW(aDevPath,
387  0,
388  FILE_SHARE_READ | FILE_SHARE_WRITE,
389  NULL,
390  OPEN_EXISTING,
391  0,
392  NULL);
393  NS_ENSURE_TRUE(devFile != INVALID_HANDLE_VALUE, NS_ERROR_FAILURE);
394  sbIPDAutoFile autoDevFile(devFile);
395 
396  // Get the device number.
397  STORAGE_DEVICE_NUMBER getDevNumParams;
398  DWORD byteCount;
399  success = DeviceIoControl(devFile,
400  IOCTL_STORAGE_GET_DEVICE_NUMBER,
401  NULL,
402  0,
403  &getDevNumParams,
404  sizeof(getDevNumParams),
405  &byteCount,
406  NULL);
407  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
408  NS_ENSURE_TRUE(getDevNumParams.DeviceNumber != 0xFFFFFFFF,
409  NS_ERROR_FAILURE);
410 
411  // Return results.
412  *aDevNum = getDevNumParams.DeviceNumber;
413 
414  return NS_OK;
415 }
416 
417 
431 nsresult
432 sbIPDSysDevice::GetDevDetail(PSP_DEVICE_INTERFACE_DETAIL_DATA* aDevIfDetailData,
433  SP_DEVINFO_DATA* aDevInfoData,
434  HDEVINFO aDevInfo,
435  GUID* aGUID,
436  DWORD aDevIndex)
437 {
438  // Validate arguments.
439  NS_ASSERTION(aDevIfDetailData, "aDevIfDetailData is null");
440  NS_ASSERTION(aDevInfoData, "aDevInfoData is null");
441  NS_ASSERTION(aGUID, "aGUID is null");
442 
443  // Function variables.
444  BOOL success;
445 
446  // Set up to get the device interface detail data. If not successful, there's
447  // no more device interfaces to enumerate.
448  SP_DEVICE_INTERFACE_DATA devIfData;
449  ZeroMemory(&devIfData, sizeof(SP_DEVICE_INTERFACE_DATA));
450  devIfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
451  success = SetupDiEnumDeviceInterfaces(aDevInfo,
452  NULL,
453  aGUID,
454  aDevIndex,
455  &devIfData);
456  if (!success)
457  return NS_ERROR_NOT_AVAILABLE;
458 
459  // Get the required size of the device interface detail data.
460  DWORD size = 0;
461  success = SetupDiGetDeviceInterfaceDetailW(aDevInfo,
462  &devIfData,
463  NULL,
464  0,
465  &size,
466  NULL);
467  NS_ENSURE_TRUE(size > 0, NS_ERROR_FAILURE);
468 
469  // Allocate the device interface detail data record and set it up for
470  // auto-disposal.
471  PSP_DEVICE_INTERFACE_DETAIL_DATA devIfDetailData;
472  devIfDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(size);
473  NS_ENSURE_TRUE(devIfDetailData, NS_ERROR_OUT_OF_MEMORY);
475  (devIfDetailData);
476  devIfDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
477 
478  // Get the device interface details.
479  ZeroMemory(aDevInfoData, sizeof(SP_DEVINFO_DATA));
480  aDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
481  success = SetupDiGetDeviceInterfaceDetailW(aDevInfo,
482  &devIfData,
483  devIfDetailData,
484  size,
485  NULL,
486  aDevInfoData);
487  NS_ENSURE_SUCCESS(success, NS_ERROR_FAILURE);
488 
489  // Return results.
490  *aDevIfDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
491  autoDevIfDetailData.forget();
492 
493  return NS_OK;
494 }
495 
496 
#define SB_PRLOG_SETUP(x)
Definition: sbDebugUtils.h:115
return NS_OK
#define LOG(args)
_dialogDatepicker pos
nsCOMPtr< nsIArray > mProperties
#define SB_DEVICE_PROPERTY_MANUFACTURER
sbIPDSysDevice(const nsID &aControllerID, nsIPropertyBag *aProperties)
NS_IMETHOD Eject(void)
Songbird iPod Device Logging Definitions.
readonly attribute sbIDeviceProperties properties
Definition: sbIDevice.idl:168
nsresult Eject()
#define SB_DEVICE_PROPERTY_SERIAL_NUMBER
nsresult Initialize()
nsresult Initialize()
#define SB_DEVICE_PROPERTY_MODEL
_getSelectedPageStyle s i