1dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine/*
2dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine * Copyright (C) 2006 The Android Open Source Project
3dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine *
4dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine * Licensed under the Apache License, Version 2.0 (the "License");
5dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine * you may not use this file except in compliance with the License.
6dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine * You may obtain a copy of the License at
7dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine *
8dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine *      http://www.apache.org/licenses/LICENSE-2.0
9dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine *
10dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine * Unless required by applicable law or agreed to in writing, software
11dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine * distributed under the License is distributed on an "AS IS" BASIS,
12dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine * See the License for the specific language governing permissions and
14dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine * limitations under the License.
15dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine */
16dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
17dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine/** \file
18dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  This file consists of implementation of a class AdbObjectHandle that
19dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  encapsulates an internal API object that is visible to the outside
20dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  of the API through a handle.
21dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine*/
22dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
23dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine#include "stdafx.h"
24dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine#include "adb_api.h"
25dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine#include "adb_object_handle.h"
26dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
27dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine/// Global ADBAPIHANDLE -> AdbObjectHandle* map
28dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkineAdbObjectHandleMap      the_map;
29dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
30dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine/// Locker for the AdbObjectHandleMap instance
31dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkineCComAutoCriticalSection the_map_locker;
32dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
33dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine/// Next adb handle value generator
34dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkineULONG_PTR               next_adb_handle_value = 0;
35dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
36dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkineAdbObjectHandle::AdbObjectHandle(AdbObjectType obj_type)
37dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    : adb_handle_(NULL),
38dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      object_type_(obj_type),
39dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      ref_count_(1) {
40dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  ATLASSERT(obj_type < AdbObjectTypeMax);
41dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine}
42dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
43dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkineAdbObjectHandle::~AdbObjectHandle() {
44dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  ATLASSERT(0 == ref_count_);
45dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  ATLASSERT(NULL == adb_handle_);
46dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine}
47dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
48dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkineLONG AdbObjectHandle::AddRef() {
49dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  ATLASSERT(ref_count_ > 0);
50dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  return InterlockedIncrement(&ref_count_);
51dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine}
52dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
53dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkineLONG AdbObjectHandle::Release() {
54dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  ATLASSERT(ref_count_ > 0);
55dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  LONG ret = InterlockedDecrement(&ref_count_);
56dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  ATLASSERT(ret >= 0);
57dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  if (0 == ret) {
58dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    LastReferenceReleased();
59dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    delete this;
60dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  }
61dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  return ret;
62dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine}
63dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
64dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkineADBAPIHANDLE AdbObjectHandle::CreateHandle() {
65dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  ADBAPIHANDLE ret = NULL;
66dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
67dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  // We have to hold this lock while we're dealing with the handle
68dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  // and the table
69dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  the_map_locker.Lock();
70dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
71dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  ATLASSERT(!IsOpened());
72dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
73dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  if (!IsOpened()) {
74dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    try {
75dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      // Generate next handle value
76dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      next_adb_handle_value++;
77dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      ret = reinterpret_cast<ADBAPIHANDLE>(next_adb_handle_value);
78dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
79dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      // Add ourselves to the map
80dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      the_map[ret] = this;
81dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
82dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      // Save handle, addref and return
83dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      adb_handle_ = ret;
84dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      AddRef();
85dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    } catch (...) {
86dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      ret = NULL;
87dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      SetLastError(ERROR_OUTOFMEMORY);
88dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    }
89dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  } else {
90dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    // Signaling that this object is already opened
91dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    SetLastError(ERROR_GEN_FAILURE);
92dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  }
93dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
94dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  the_map_locker.Unlock();
95dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
96dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  return ret;
97dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine}
98dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
99dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkinebool AdbObjectHandle::CloseHandle() {
100dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  bool ret = false;
101dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
102dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  // Addref just in case that last reference to this object is being
103dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  // held in the map
104dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  AddRef();
105dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
106dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  the_map_locker.Lock();
107dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
108dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  ATLASSERT(IsOpened());
109dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
110dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  if (IsOpened()) {
111dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    try {
112dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      // Look us up in the map.
113dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      AdbObjectHandleMap::iterator found = the_map.find(adb_handle());
114dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      ATLASSERT((found != the_map.end()) && (this == found->second));
115dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
116dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      if ((found != the_map.end()) && (this == found->second)) {
117dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine        // Remove ourselves from the map, close and release the object
118dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine        the_map.erase(found);
119dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine        adb_handle_ = NULL;
120dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine        Release();
121dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine        ret = true;
122dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      } else {
123dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine        SetLastError(ERROR_INVALID_HANDLE);
124dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      }
125dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    } catch (...) {
126dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      ret = false;
127dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      SetLastError(ERROR_OUTOFMEMORY);
128dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    }
129dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  } else {
130dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    SetLastError(ERROR_INVALID_HANDLE);
131dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  }
132dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
133dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  the_map_locker.Unlock();
134dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
135dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  Release();
136dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
137dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  return ret;
138dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine}
139dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
140dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkinebool AdbObjectHandle::IsObjectOfType(AdbObjectType obj_type) const {
141dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  return (obj_type == object_type());
142dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine}
143dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
144dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkinevoid AdbObjectHandle::LastReferenceReleased() {
145dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  ATLASSERT(!IsOpened());
146dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine}
147dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
148dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkineAdbObjectHandle* AdbObjectHandle::Lookup(ADBAPIHANDLE adb_hndl) {
149dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  AdbObjectHandle* ret = NULL;
150dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
151dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  the_map_locker.Lock();
152dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
153dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  try {
154dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    // Look us up in the map.
155dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    AdbObjectHandleMap::iterator found = the_map.find(adb_hndl);
156dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    if (found != the_map.end()) {
157dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      ret = found->second;
158dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine      ret->AddRef();
159dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    }
160dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  } catch (...) {
161dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine    SetLastError(ERROR_OUTOFMEMORY);
162dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  }
163dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
164dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  the_map_locker.Unlock();
165dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine
166dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine  return ret;
167dceaaa52cec11631c72cfea5fb74ee607602ecdevchtchetkine}
168