adb_helper_routines.cpp revision 52d4c30ca52320ec92d1d1ddc8db3f07f69c4f98
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/** \file
18  This file consists of implementation of helper routines used
19  in the API.
20*/
21
22#include "stdafx.h"
23#include "adb_api.h"
24#include "adb_helper_routines.h"
25#include "adb_interface_enum.h"
26
27bool GetSDKComplientParam(AdbOpenAccessType access_type,
28                          AdbOpenSharingMode sharing_mode,
29                          ULONG* desired_access,
30                          ULONG* desired_sharing) {
31  if (NULL != desired_access) {
32    switch (access_type) {
33      case AdbOpenAccessTypeReadWrite:
34        *desired_access = GENERIC_READ | GENERIC_WRITE;
35        break;
36
37      case AdbOpenAccessTypeRead:
38        *desired_access = GENERIC_READ;
39        break;
40
41      case AdbOpenAccessTypeWrite:
42        *desired_access = GENERIC_WRITE;
43        break;
44
45      case AdbOpenAccessTypeQueryInfo:
46        *desired_access = FILE_READ_ATTRIBUTES | FILE_READ_EA;
47        break;
48
49      default:
50        AtlTrace("\n!!!!! ADB API -> GetSDKComplientParam %u is unknown access type",
51                 access_type);
52        SetLastError(ERROR_INVALID_ACCESS);
53        return false;
54    }
55  }
56
57  if (NULL != desired_sharing) {
58    switch (sharing_mode) {
59      case AdbOpenSharingModeReadWrite:
60        *desired_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
61        break;
62
63      case AdbOpenSharingModeRead:
64        *desired_sharing = FILE_SHARE_READ;
65        break;
66
67      case AdbOpenSharingModeWrite:
68        *desired_sharing = FILE_SHARE_WRITE;
69        break;
70
71      case AdbOpenSharingModeExclusive:
72        *desired_sharing = 0;
73        break;
74
75      default:
76        AtlTrace("\n!!!!! ADB API -> GetSDKComplientParam %u is unknown share mode",
77                 sharing_mode);
78        SetLastError(ERROR_INVALID_PARAMETER);
79        return false;
80    }
81  }
82
83  return true;
84}
85
86bool EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info,
87                               GUID class_id,
88                               bool exclude_removed,
89                               bool active_only,
90                               AdbEnumInterfaceArray* interfaces) {
91  AdbEnumInterfaceArray tmp;
92  bool ret = false;
93
94  // Enumerate interfaces on this device
95  for (ULONG index = 0; ; index++) {
96    SP_DEVICE_INTERFACE_DATA interface_data;
97    interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
98
99    // SetupDiEnumDeviceInterfaces() returns information about device
100    // interfaces exposed by one or more devices defined by our interface
101    // class. Each call returns information about one interface. The routine
102    // can be called repeatedly to get information about several interfaces
103    // exposed by one or more devices.
104    if (SetupDiEnumDeviceInterfaces(hardware_dev_info,
105                                    0,
106                                    &class_id,
107                                    index,
108                                    &interface_data)) {
109      // Satisfy "exclude removed" and "active only" filters.
110      if ((!exclude_removed || (0 == (interface_data.Flags & SPINT_REMOVED))) &&
111          (!active_only || (interface_data.Flags & SPINT_ACTIVE))) {
112        std::wstring dev_name;
113
114        if (GetUsbDeviceName(hardware_dev_info, &interface_data, &dev_name)) {
115          try {
116            // Add new entry to the array
117            tmp.push_back(AdbInstanceEnumEntry(dev_name.c_str(),
118                                               interface_data.InterfaceClassGuid,
119                                               interface_data.Flags));
120          } catch (... ) {
121            SetLastError(ERROR_OUTOFMEMORY);
122            break;
123          }
124        } else {
125          // Something went wrong in getting device name
126          break;
127        }
128      }
129    } else {
130      if (ERROR_NO_MORE_ITEMS == GetLastError()) {
131        // There are no more items in the list. Enum is completed.
132        ret = true;
133        break;
134      } else {
135        // Something went wrong in SDK enum
136        break;
137      }
138    }
139  }
140
141  // On success, swap temp array with the returning one
142  if (ret)
143    interfaces->swap(tmp);
144
145  return ret;
146}
147
148bool EnumerateDeviceInterfaces(GUID class_id,
149                               ULONG flags,
150                               bool exclude_removed,
151                               bool active_only,
152                               AdbEnumInterfaceArray* interfaces) {
153  // Open a handle to the plug and play dev node.
154  // SetupDiGetClassDevs() returns a device information set that
155  // contains info on all installed devices of a specified class.
156  HDEVINFO hardware_dev_info =
157    SetupDiGetClassDevs(&class_id, NULL, NULL, flags);
158
159  bool ret = false;
160
161  if (INVALID_HANDLE_VALUE != hardware_dev_info) {
162    // Do the enum
163    ret = EnumerateDeviceInterfaces(hardware_dev_info,
164                                    class_id,
165                                    exclude_removed,
166                                    active_only,
167                                    interfaces);
168
169    // Preserve last error accross hardware_dev_info destruction
170    ULONG error_to_report = ret ? NO_ERROR : GetLastError();
171
172    SetupDiDestroyDeviceInfoList(hardware_dev_info);
173
174    if (NO_ERROR != error_to_report)
175      SetLastError(error_to_report);
176  }
177
178  return ret;
179}
180
181bool GetUsbDeviceDetails(
182    HDEVINFO hardware_dev_info,
183    PSP_DEVICE_INTERFACE_DATA dev_info_data,
184    PSP_DEVICE_INTERFACE_DETAIL_DATA* dev_info_detail_data) {
185  ULONG required_len = 0;
186
187  // First query for the structure size. At this point we expect this call
188  // to fail with ERROR_INSUFFICIENT_BUFFER error code.
189  if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info,
190                                      dev_info_data,
191                                      NULL,
192                                      0,
193                                      &required_len,
194                                      NULL)) {
195    return false;
196  }
197
198  if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
199    return false;
200
201  // Allocate buffer for the structure
202  PSP_DEVICE_INTERFACE_DETAIL_DATA buffer =
203    reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(required_len));
204
205  if (NULL == buffer) {
206    SetLastError(ERROR_OUTOFMEMORY);
207    return false;
208  }
209
210  buffer->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
211
212  // Retrieve the information from Plug and Play.
213  if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info,
214                                      dev_info_data,
215                                      buffer,
216                                      required_len,
217                                      &required_len,
218                                      NULL)) {
219    *dev_info_detail_data = buffer;
220    return true;
221  } else {
222    // Free the buffer if this call failed
223    free(buffer);
224
225    return false;
226  }
227}
228
229bool GetUsbDeviceName(HDEVINFO hardware_dev_info,
230                      PSP_DEVICE_INTERFACE_DATA dev_info_data,
231                      std::wstring* name) {
232  PSP_DEVICE_INTERFACE_DETAIL_DATA func_class_dev_data = NULL;
233  if (!GetUsbDeviceDetails(hardware_dev_info,
234                           dev_info_data,
235                           &func_class_dev_data)) {
236    return false;
237  }
238
239  try {
240    *name = func_class_dev_data->DevicePath;
241  } catch (...) {
242    SetLastError(ERROR_OUTOFMEMORY);
243  }
244
245  free(func_class_dev_data);
246
247  return !name->empty();
248}
249