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 a class AdbObjectHandle that
19   encapsulates an internal API object that is visible to the outside
20   of the API through a handle.
21 */
22 
23 #include "stdafx.h"
24 #include "adb_api.h"
25 #include "adb_object_handle.h"
26 
27 /// Global ADBAPIHANDLE -> AdbObjectHandle* map
28 AdbObjectHandleMap      the_map;
29 
30 /// Locker for the AdbObjectHandleMap instance
31 CComAutoCriticalSection the_map_locker;
32 
33 /// Next adb handle value generator
34 ULONG_PTR               next_adb_handle_value = 0;
35 
AdbObjectHandle(AdbObjectType obj_type)36 AdbObjectHandle::AdbObjectHandle(AdbObjectType obj_type)
37     : adb_handle_(NULL),
38       object_type_(obj_type),
39       ref_count_(1) {
40   ATLASSERT(obj_type < AdbObjectTypeMax);
41 }
42 
~AdbObjectHandle()43 AdbObjectHandle::~AdbObjectHandle() {
44   ATLASSERT(0 == ref_count_);
45   ATLASSERT(NULL == adb_handle_);
46 }
47 
AddRef()48 LONG AdbObjectHandle::AddRef() {
49   ATLASSERT(ref_count_ > 0);
50   return InterlockedIncrement(&ref_count_);
51 }
52 
Release()53 LONG AdbObjectHandle::Release() {
54   ATLASSERT(ref_count_ > 0);
55   LONG ret = InterlockedDecrement(&ref_count_);
56   ATLASSERT(ret >= 0);
57   if (0 == ret) {
58     LastReferenceReleased();
59     delete this;
60   }
61   return ret;
62 }
63 
CreateHandle()64 ADBAPIHANDLE AdbObjectHandle::CreateHandle() {
65   ADBAPIHANDLE ret = NULL;
66 
67   // We have to hold this lock while we're dealing with the handle
68   // and the table
69   the_map_locker.Lock();
70 
71   ATLASSERT(!IsOpened());
72 
73   if (!IsOpened()) {
74     try {
75       // Generate next handle value
76       next_adb_handle_value++;
77       ret = reinterpret_cast<ADBAPIHANDLE>(next_adb_handle_value);
78 
79       // Add ourselves to the map
80       the_map[ret] = this;
81 
82       // Save handle, addref and return
83       adb_handle_ = ret;
84       AddRef();
85     } catch (...) {
86       ret = NULL;
87       SetLastError(ERROR_OUTOFMEMORY);
88     }
89   } else {
90     // Signaling that this object is already opened
91     SetLastError(ERROR_GEN_FAILURE);
92   }
93 
94   the_map_locker.Unlock();
95 
96   return ret;
97 }
98 
CloseHandle()99 bool AdbObjectHandle::CloseHandle() {
100   bool ret = false;
101 
102   // Addref just in case that last reference to this object is being
103   // held in the map
104   AddRef();
105 
106   the_map_locker.Lock();
107 
108   ATLASSERT(IsOpened());
109 
110   if (IsOpened()) {
111     try {
112       // Look us up in the map.
113       AdbObjectHandleMap::iterator found = the_map.find(adb_handle());
114       ATLASSERT((found != the_map.end()) && (this == found->second));
115 
116       if ((found != the_map.end()) && (this == found->second)) {
117         // Remove ourselves from the map, close and release the object
118         the_map.erase(found);
119         adb_handle_ = NULL;
120         Release();
121         ret = true;
122       } else {
123         SetLastError(ERROR_INVALID_HANDLE);
124       }
125     } catch (...) {
126       ret = false;
127       SetLastError(ERROR_OUTOFMEMORY);
128     }
129   } else {
130     SetLastError(ERROR_INVALID_HANDLE);
131   }
132 
133   the_map_locker.Unlock();
134 
135   Release();
136 
137   return ret;
138 }
139 
IsObjectOfType(AdbObjectType obj_type) const140 bool AdbObjectHandle::IsObjectOfType(AdbObjectType obj_type) const {
141   return (obj_type == object_type());
142 }
143 
LastReferenceReleased()144 void AdbObjectHandle::LastReferenceReleased() {
145   ATLASSERT(!IsOpened());
146 }
147 
Lookup(ADBAPIHANDLE adb_hndl)148 AdbObjectHandle* AdbObjectHandle::Lookup(ADBAPIHANDLE adb_hndl) {
149   AdbObjectHandle* ret = NULL;
150 
151   the_map_locker.Lock();
152 
153   try {
154     // Look us up in the map.
155     AdbObjectHandleMap::iterator found = the_map.find(adb_hndl);
156     if (found != the_map.end()) {
157       ret = found->second;
158       ret->AddRef();
159     }
160   } catch (...) {
161     SetLastError(ERROR_OUTOFMEMORY);
162   }
163 
164   the_map_locker.Unlock();
165 
166   return ret;
167 }
168