deviceIconStore.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. #include "main.h"
  2. #include "./deviceIconStore.h"
  3. #include <strsafe.h>
  4. DeviceIconStore::DeviceIconStore()
  5. : ref(1), base(NULL)
  6. {
  7. InitializeCriticalSection(&lock);
  8. }
  9. DeviceIconStore::~DeviceIconStore()
  10. {
  11. RemoveAll();
  12. String_Free(base);
  13. DeleteCriticalSection(&lock);
  14. }
  15. HRESULT DeviceIconStore::CreateInstance(DeviceIconStore **instance)
  16. {
  17. if (NULL == instance)
  18. return E_POINTER;
  19. *instance = new DeviceIconStore();
  20. if (NULL == *instance)
  21. return E_OUTOFMEMORY;
  22. return S_OK;
  23. }
  24. size_t DeviceIconStore::AddRef()
  25. {
  26. return InterlockedIncrement((LONG*)&ref);
  27. }
  28. size_t DeviceIconStore::Release()
  29. {
  30. if (0 == ref)
  31. return ref;
  32. LONG r = InterlockedDecrement((LONG*)&ref);
  33. if (0 == r)
  34. delete(this);
  35. return r;
  36. }
  37. int DeviceIconStore::QueryInterface(GUID interface_guid, void **object)
  38. {
  39. if (NULL == object) return E_POINTER;
  40. if (IsEqualIID(interface_guid, IFC_DeviceIconStore))
  41. *object = static_cast<ifc_deviceiconstore*>(this);
  42. else
  43. {
  44. *object = NULL;
  45. return E_NOINTERFACE;
  46. }
  47. if (NULL == *object)
  48. return E_UNEXPECTED;
  49. AddRef();
  50. return S_OK;
  51. }
  52. void DeviceIconStore::Lock()
  53. {
  54. EnterCriticalSection(&lock);
  55. }
  56. void DeviceIconStore::Unlock()
  57. {
  58. LeaveCriticalSection(&lock);
  59. }
  60. HRESULT DeviceIconStore::Add(const wchar_t *path, unsigned int width, unsigned int height, BOOL replaceExisting)
  61. {
  62. if (FALSE != IS_STRING_EMPTY(path))
  63. return E_INVALIDARG;
  64. if(width < 1)
  65. width = 1;
  66. if(height < 1)
  67. height = 1;
  68. HRESULT hr = S_FALSE;
  69. Lock();
  70. size_t index = list.size();
  71. while(index--)
  72. {
  73. Record *record = &list[index];
  74. if (width == record->width &&
  75. height == record->height)
  76. {
  77. if (FALSE == replaceExisting)
  78. hr = E_FAIL;
  79. else
  80. {
  81. wchar_t *pathCopy;
  82. pathCopy = String_Duplicate(path);
  83. if (NULL == pathCopy)
  84. hr = E_OUTOFMEMORY;
  85. else
  86. {
  87. record->path = pathCopy;
  88. hr = S_OK;
  89. }
  90. }
  91. break;
  92. }
  93. }
  94. if (S_FALSE == hr)
  95. {
  96. Record newRecord;
  97. newRecord.path = String_Duplicate(path);
  98. if (NULL == newRecord.path)
  99. hr = E_OUTOFMEMORY;
  100. else
  101. {
  102. newRecord.width = width;
  103. newRecord.height = height;
  104. list.push_back(newRecord);
  105. hr = S_OK;
  106. }
  107. }
  108. Unlock();
  109. return hr;
  110. }
  111. HRESULT DeviceIconStore::Remove(unsigned int width, unsigned int height)
  112. {
  113. HRESULT hr;
  114. size_t index;
  115. Record *record;
  116. if(width < 1)
  117. width = 1;
  118. if(height < 1)
  119. height = 1;
  120. hr = S_FALSE;
  121. Lock();
  122. index = list.size();
  123. while(index--)
  124. {
  125. record = &list[index];
  126. if (record->width == width &&
  127. record->height == height)
  128. {
  129. String_Free(record->path);
  130. list.erase(list.begin() + index);
  131. hr = S_OK;
  132. break;
  133. }
  134. }
  135. Unlock();
  136. return hr;
  137. }
  138. HRESULT DeviceIconStore::RemovePath(const wchar_t *path)
  139. {
  140. HRESULT hr;
  141. size_t index;
  142. Record *record;
  143. if (FALSE != IS_STRING_EMPTY(path))
  144. return E_INVALIDARG;
  145. hr = S_FALSE;
  146. Lock();
  147. index = list.size();
  148. while(index--)
  149. {
  150. record = &list[index];
  151. if(CSTR_EQUAL == CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, record->path, -1, path, -1))
  152. {
  153. String_Free(record->path);
  154. list.erase(list.begin() + index);
  155. hr = S_OK;
  156. }
  157. }
  158. Unlock();
  159. return hr;
  160. }
  161. HRESULT DeviceIconStore::RemoveAll()
  162. {
  163. size_t index;
  164. Record *record;
  165. Lock();
  166. index = list.size();
  167. while(index--)
  168. {
  169. record = &list[index];
  170. String_Free(record->path);
  171. }
  172. list.clear();
  173. Unlock();
  174. return S_OK;
  175. }
  176. HRESULT DeviceIconStore::Get(wchar_t *buffer, size_t bufferMax, unsigned int width, unsigned int height)
  177. {
  178. HRESULT hr;
  179. Record *record;
  180. const wchar_t *path;
  181. size_t index;
  182. double widthDbl, heightDbl;
  183. double scaleMin, scaleHorz, scaleVert;
  184. if (NULL == buffer)
  185. return E_POINTER;
  186. if (width < 1)
  187. width = 1;
  188. if (height < 1)
  189. height = 1;
  190. path = NULL;
  191. widthDbl = width;
  192. heightDbl = height;
  193. Lock();
  194. index = list.size();
  195. if (index > 0)
  196. {
  197. record = &list[--index];
  198. scaleHorz = widthDbl/record->width;
  199. scaleVert = heightDbl/record->height;
  200. scaleMin = (scaleHorz < scaleVert) ? scaleHorz : scaleVert;
  201. path = record->path;
  202. if (1.0 != scaleMin)
  203. {
  204. scaleMin = fabs(1.0 - scaleMin);
  205. while(index--)
  206. {
  207. record = &list[index];
  208. scaleHorz = widthDbl/record->width;
  209. scaleVert = heightDbl/record->height;
  210. if (scaleHorz > scaleVert)
  211. scaleHorz = scaleVert;
  212. if (1.0 == scaleHorz)
  213. {
  214. path = record->path;
  215. break;
  216. }
  217. scaleHorz = fabs(1.0 - scaleHorz);
  218. if (scaleHorz < scaleMin)
  219. {
  220. scaleMin = scaleHorz;
  221. path = record->path;
  222. }
  223. }
  224. }
  225. }
  226. if (NULL == path)
  227. hr = E_FAIL;
  228. else
  229. hr = GetFullPath(buffer, bufferMax, path);
  230. Unlock();
  231. return hr;
  232. }
  233. HRESULT DeviceIconStore::GetExact(wchar_t *buffer, size_t bufferMax, unsigned int width, unsigned int height)
  234. {
  235. HRESULT hr;
  236. size_t index;
  237. Record *record;
  238. if (NULL == buffer)
  239. return E_POINTER;
  240. if(width < 1)
  241. width = 1;
  242. if(height < 1)
  243. height = 1;
  244. hr = E_FAIL;
  245. Lock();
  246. index = list.size();
  247. while(index--)
  248. {
  249. record = &list[index];
  250. if (record->width == width &&
  251. record->height == height)
  252. {
  253. hr = GetFullPath(buffer, bufferMax, record->path);
  254. break;
  255. }
  256. }
  257. Unlock();
  258. return hr;
  259. }
  260. HRESULT DeviceIconStore::SetBasePath(const wchar_t *path)
  261. {
  262. HRESULT hr;
  263. Lock();
  264. String_Free(base);
  265. base = String_Duplicate(path);
  266. if (NULL == base && NULL != path)
  267. hr = E_OUTOFMEMORY;
  268. else
  269. hr = S_OK;
  270. Unlock();
  271. return hr;
  272. }
  273. HRESULT DeviceIconStore::GetBasePath(wchar_t *buffer, size_t bufferMax)
  274. {
  275. HRESULT hr;
  276. if (NULL == buffer)
  277. return E_POINTER;
  278. Lock();
  279. if (0 == String_CopyTo(buffer, base, bufferMax) &&
  280. FALSE == IS_STRING_EMPTY(base))
  281. {
  282. hr = E_FAIL;
  283. }
  284. else
  285. hr = S_OK;
  286. Unlock();
  287. return hr;
  288. }
  289. HRESULT DeviceIconStore::Clone(ifc_deviceiconstore **instance)
  290. {
  291. HRESULT hr;
  292. DeviceIconStore *clone;
  293. if (NULL == instance)
  294. return E_POINTER;
  295. hr = DeviceIconStore::CreateInstance(&clone);
  296. if (FAILED(hr))
  297. return hr;
  298. Lock();
  299. clone->base = String_Duplicate(base);
  300. if (NULL == clone->base && NULL != base)
  301. hr = E_OUTOFMEMORY;
  302. else
  303. {
  304. size_t index, count;
  305. Record target;
  306. const Record *source;
  307. count = list.size();
  308. for(index = 0; index < count; index++)
  309. {
  310. source = &list[index];
  311. target.path = String_Duplicate(source->path);
  312. if (NULL == target.path)
  313. {
  314. hr = E_OUTOFMEMORY;
  315. break;
  316. }
  317. else
  318. {
  319. target.width = source->width;
  320. target.height = source->height;
  321. clone->list.push_back(target);
  322. }
  323. }
  324. }
  325. Unlock();
  326. if (FAILED(hr))
  327. clone->Release();
  328. else
  329. *instance = clone;
  330. return hr;
  331. }
  332. HRESULT DeviceIconStore::Enumerate(EnumeratorCallback callback, void *user)
  333. {
  334. size_t index, count;
  335. wchar_t buffer[MAX_PATH*2] = {0};
  336. Record *record;
  337. if (NULL == callback)
  338. return E_POINTER;
  339. Lock();
  340. count = list.size();
  341. for(index = 0; index < count; index++)
  342. {
  343. record = &list[index];
  344. if (SUCCEEDED(GetFullPath(buffer, ARRAYSIZE(buffer), record->path)))
  345. {
  346. if (FALSE == callback(buffer, record->width, record->height, user))
  347. {
  348. break;
  349. }
  350. }
  351. }
  352. Unlock();
  353. return S_OK;
  354. }
  355. HRESULT DeviceIconStore::GetFullPath(wchar_t *buffer, size_t bufferMax, const wchar_t *path)
  356. {
  357. HRESULT hr;
  358. if (NULL == buffer)
  359. return E_POINTER;
  360. if (FALSE != IS_STRING_EMPTY(path))
  361. return E_INVALIDARG;
  362. Lock();
  363. if (FALSE == PathIsRelative(path) ||
  364. FALSE != IS_STRING_EMPTY(base))
  365. {
  366. if (0 == String_CopyTo(buffer, path, bufferMax))
  367. hr = E_OUTOFMEMORY;
  368. else
  369. hr = S_OK;
  370. }
  371. else
  372. {
  373. if (NULL == PathCombine(buffer, base, path))
  374. hr = E_FAIL;
  375. else
  376. hr = S_OK;
  377. }
  378. Unlock();
  379. return hr;
  380. }
  381. #define CBCLASS DeviceIconStore
  382. START_DISPATCH;
  383. CB(ADDREF, AddRef)
  384. CB(RELEASE, Release)
  385. CB(QUERYINTERFACE, QueryInterface)
  386. CB(API_ADD, Add)
  387. CB(API_REMOVE, Remove)
  388. CB(API_REMOVEPATH, RemovePath)
  389. CB(API_REMOVEALL, RemoveAll)
  390. CB(API_GET, Get)
  391. CB(API_GETEXACT, GetExact)
  392. CB(API_SETBASEPATH, SetBasePath)
  393. CB(API_GETBASEPATH, GetBasePath)
  394. CB(API_CLONE, Clone)
  395. CB(API_ENUMERATE, Enumerate)
  396. END_DISPATCH;
  397. #undef CBCLASS