device.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. #include "main.h"
  2. #include "./device.h"
  3. #include <strsafe.h>
  4. Device::Device()
  5. : ref(1), name(NULL), type(NULL), connection(NULL), displayName(NULL),
  6. totalSpace(0), usedSpace(0), attached(FALSE), hidden(FALSE),
  7. connected(FALSE), activity(NULL), model(NULL), status(NULL)
  8. {
  9. InitializeCriticalSection(&lock);
  10. if (NULL == WASABI_API_DEVICES ||
  11. FAILED(WASABI_API_DEVICES->CreateDeviceEventManager(&eventManager)))
  12. {
  13. eventManager = NULL;
  14. }
  15. if (NULL == WASABI_API_DEVICES ||
  16. FAILED(WASABI_API_DEVICES->CreateIconStore(&iconStore)))
  17. {
  18. iconStore = NULL;
  19. }
  20. if (NULL == WASABI_API_DEVICES ||
  21. FAILED(WASABI_API_DEVICES->CreateSupportedCommandStore(&commands)))
  22. {
  23. commands = NULL;
  24. }
  25. }
  26. Device::~Device()
  27. {
  28. DeviceActivity *activityCopy;
  29. Lock();
  30. if (NULL != activity)
  31. {
  32. activity->SetUser(NULL);
  33. activityCopy = activity;
  34. activityCopy->AddRef();
  35. }
  36. else
  37. activityCopy = NULL;
  38. AnsiString_Free(name);
  39. AnsiString_Free(type);
  40. AnsiString_Free(connection);
  41. String_Free(displayName);
  42. String_Free(model);
  43. String_Free(status);
  44. if (NULL != commands)
  45. commands->Release();
  46. if (NULL != iconStore)
  47. iconStore->Release();
  48. if (NULL != eventManager)
  49. eventManager->Release();
  50. Unlock();
  51. if (NULL != activityCopy)
  52. {
  53. activityCopy->Stop();
  54. activityCopy->Release();
  55. }
  56. DeleteCriticalSection(&lock);
  57. }
  58. HRESULT Device::CreateInstance(const char *name, const char *type, const char *connection, Device**instance)
  59. {
  60. Device *self;
  61. if (NULL == instance)
  62. return E_POINTER;
  63. *instance = NULL;
  64. self = new Device();
  65. if (NULL == self)
  66. return E_OUTOFMEMORY;
  67. self->name = AnsiString_Duplicate(name);
  68. self->type = AnsiString_Duplicate(type);
  69. self->connection = AnsiString_Duplicate(connection);
  70. *instance = self;
  71. return S_OK;
  72. }
  73. size_t Device::AddRef()
  74. {
  75. return InterlockedIncrement((LONG*)&ref);
  76. }
  77. size_t Device::Release()
  78. {
  79. if (0 == ref)
  80. return ref;
  81. LONG r = InterlockedDecrement((LONG*)&ref);
  82. if (0 == r)
  83. delete(this);
  84. return r;
  85. }
  86. int Device::QueryInterface(GUID interface_guid, void **object)
  87. {
  88. if (NULL == object)
  89. return E_POINTER;
  90. if (IsEqualIID(interface_guid, IFC_Device))
  91. *object = static_cast<ifc_device*>(this);
  92. else
  93. {
  94. *object = NULL;
  95. return E_NOINTERFACE;
  96. }
  97. if (NULL == *object)
  98. return E_UNEXPECTED;
  99. AddRef();
  100. return S_OK;
  101. }
  102. void Device::Lock()
  103. {
  104. EnterCriticalSection(&lock);
  105. }
  106. void Device::Unlock()
  107. {
  108. LeaveCriticalSection(&lock);
  109. }
  110. const char *Device::GetName()
  111. {
  112. return name;
  113. }
  114. const char *Device::GetType()
  115. {
  116. return type;
  117. }
  118. const char *Device::GetConnection()
  119. {
  120. return connection;
  121. }
  122. HRESULT Device::GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height)
  123. {
  124. if (NULL == buffer)
  125. return E_POINTER;
  126. if (NULL == iconStore)
  127. return E_UNEXPECTED;
  128. return iconStore->Get(buffer, bufferSize, width, height);
  129. }
  130. HRESULT Device::GetDisplayName(wchar_t *buffer, size_t bufferSize)
  131. {
  132. HRESULT hr;
  133. if (NULL == buffer)
  134. return E_POINTER;
  135. Lock();
  136. if (0 == String_CopyTo(buffer, displayName, bufferSize) &&
  137. FALSE == IS_STRING_EMPTY(displayName))
  138. {
  139. hr = E_FAIL;
  140. }
  141. else
  142. hr = S_OK;
  143. Unlock();
  144. return hr;
  145. }
  146. BOOL Device::GetHidden()
  147. {
  148. return hidden;
  149. }
  150. HRESULT Device::GetTotalSpace(uint64_t *size)
  151. {
  152. if (NULL == size)
  153. return E_POINTER;
  154. Lock();
  155. *size = totalSpace;
  156. Unlock();
  157. return S_OK;
  158. }
  159. HRESULT Device::GetUsedSpace(uint64_t *size)
  160. {
  161. if (NULL == size)
  162. return E_POINTER;
  163. Lock();
  164. *size = usedSpace;
  165. Unlock();
  166. return S_OK;
  167. }
  168. BOOL Device::GetAttached()
  169. {
  170. return attached;
  171. }
  172. HRESULT Device::Attach(HWND hostWindow)
  173. {
  174. HRESULT hr;
  175. Lock();
  176. if (FALSE != attached)
  177. hr = S_FALSE;
  178. else
  179. {
  180. attached = TRUE;
  181. hr = S_OK;
  182. }
  183. Unlock();
  184. if (S_OK == hr && NULL != eventManager)
  185. eventManager->Notify_AttachmentChanged(this, attached);
  186. return hr;
  187. }
  188. HRESULT Device::Detach(HWND hostWindow)
  189. {
  190. HRESULT hr;
  191. Lock();
  192. if (FALSE == attached)
  193. hr = S_FALSE;
  194. else
  195. {
  196. attached = FALSE;
  197. hr = S_OK;
  198. }
  199. Unlock();
  200. if (S_OK == hr && NULL != eventManager)
  201. eventManager->Notify_AttachmentChanged(this, attached);
  202. return hr;
  203. }
  204. HRESULT Device::EnumerateCommands(ifc_devicesupportedcommandenum **enumerator, DeviceCommandContext context)
  205. {
  206. if (NULL == commands)
  207. return E_UNEXPECTED;
  208. return commands->Enumerate(enumerator);
  209. }
  210. HRESULT Device::SendCommand(const char *command, HWND hostWindow, ULONG_PTR param)
  211. {
  212. const wchar_t *commandName;
  213. wchar_t message[1024];
  214. if (NULL == command)
  215. return E_POINTER;
  216. if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, command, -1, "sync", -1))
  217. {
  218. StartSyncActivity(hostWindow);
  219. return S_OK;
  220. }
  221. else if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, command, -1, "eject", -1))
  222. commandName = L"Eject";
  223. else if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, command, -1, "detach", -1))
  224. {
  225. Detach(hostWindow);
  226. return S_OK;
  227. }
  228. else if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, command, -1, "settings", -1))
  229. commandName = L"Settings";
  230. else
  231. return E_NOTIMPL;
  232. StringCchPrintf(message, ARRAYSIZE(message), L"%s command received", commandName);
  233. MessageBox(hostWindow, message, L"Device command test", MB_OK | MB_ICONINFORMATION);
  234. return S_OK;
  235. }
  236. HRESULT Device::GetCommandFlags(const char *command, DeviceCommandFlags *flags)
  237. {
  238. if (NULL == commands)
  239. return E_UNEXPECTED;
  240. return commands->GetFlags(command, flags);
  241. }
  242. HRESULT Device::GetActivity(ifc_deviceactivity **activityOut)
  243. {
  244. HRESULT hr;
  245. if (NULL == activityOut)
  246. return E_POINTER;
  247. Lock();
  248. *activityOut = activity;
  249. if (NULL != activity)
  250. {
  251. activity->AddRef();
  252. hr = S_OK;
  253. }
  254. else
  255. hr = S_FALSE;
  256. Unlock();
  257. return hr;
  258. }
  259. HRESULT Device::Advise(ifc_deviceevent *handler)
  260. {
  261. if (NULL == eventManager)
  262. return E_UNEXPECTED;
  263. return eventManager->Advise(handler);
  264. }
  265. HRESULT Device::Unadvise(ifc_deviceevent *handler)
  266. {
  267. if (NULL == eventManager)
  268. return E_UNEXPECTED;
  269. return eventManager->Unadvise(handler);
  270. }
  271. HWND Device::CreateView(HWND parentWindow)
  272. {
  273. return DeviceView_CreateWindow(parentWindow, this);
  274. }
  275. void Device::SetNavigationItem(void *navigationItem)
  276. {
  277. }
  278. HRESULT Device::GetModel(wchar_t *buffer, size_t bufferSize)
  279. {
  280. HRESULT hr;
  281. if (NULL == buffer)
  282. return E_POINTER;
  283. Lock();
  284. if (0 == String_CopyTo(buffer, model, bufferSize) &&
  285. FALSE == IS_STRING_EMPTY(model))
  286. {
  287. hr = E_FAIL;
  288. }
  289. else
  290. hr = S_OK;
  291. Unlock();
  292. return hr;
  293. }
  294. HRESULT Device::GetStatus(wchar_t *buffer, size_t bufferSize)
  295. {
  296. HRESULT hr;
  297. if (NULL == buffer)
  298. return E_POINTER;
  299. Lock();
  300. if (0 == String_CopyTo(buffer, status, bufferSize) &&
  301. FALSE == IS_STRING_EMPTY(status))
  302. {
  303. hr = E_FAIL;
  304. }
  305. else
  306. hr = S_OK;
  307. Unlock();
  308. return hr;
  309. }
  310. HRESULT Device::SetConnection(const char *con)
  311. {
  312. Lock();
  313. AnsiString_Free(connection);
  314. connection = AnsiString_Duplicate(con);
  315. Unlock();
  316. return S_OK;
  317. }
  318. HRESULT Device::SetDisplayName(const wchar_t *name)
  319. {
  320. HRESULT hr;
  321. Lock();
  322. if (NULL == name && NULL == displayName)
  323. hr = S_FALSE;
  324. else
  325. {
  326. if (NULL != displayName &&
  327. CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, name, -1, displayName, -1))
  328. {
  329. hr = S_FALSE;
  330. }
  331. else
  332. {
  333. wchar_t *string;
  334. string = String_Duplicate(name);
  335. if (NULL == string && NULL != name)
  336. hr = E_FAIL;
  337. else
  338. {
  339. String_Free(displayName);
  340. displayName = string;
  341. if (NULL != eventManager)
  342. eventManager->Notify_DisplayNameChanged(this, displayName);
  343. hr = S_OK;
  344. }
  345. }
  346. }
  347. Unlock();
  348. return hr;
  349. }
  350. HRESULT Device::SetTotalSpace(uint64_t size)
  351. {
  352. Lock();
  353. totalSpace = size;
  354. if (NULL != eventManager)
  355. eventManager->Notify_TotalSpaceChanged(this, totalSpace);
  356. Unlock();
  357. return S_OK;
  358. }
  359. HRESULT Device::SetUsedSpace(uint64_t size)
  360. {
  361. Lock();
  362. usedSpace = size;
  363. if (NULL != eventManager)
  364. eventManager->Notify_UsedSpaceChanged(this, usedSpace);
  365. Unlock();
  366. return S_OK;
  367. }
  368. HRESULT Device::SetModel(const wchar_t *deviceModel)
  369. {
  370. HRESULT hr;
  371. Lock();
  372. if (NULL == deviceModel && NULL == model)
  373. hr = S_FALSE;
  374. else
  375. {
  376. if (NULL != model &&
  377. CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, deviceModel, -1, model, -1))
  378. {
  379. hr = S_FALSE;
  380. }
  381. else
  382. {
  383. wchar_t *string;
  384. string = String_Duplicate(deviceModel);
  385. if (NULL == string && NULL != deviceModel)
  386. hr = E_FAIL;
  387. else
  388. {
  389. String_Free(model);
  390. model = string;
  391. if (NULL != eventManager)
  392. eventManager->Notify_ModelChanged(this, model);
  393. hr = S_OK;
  394. }
  395. }
  396. }
  397. Unlock();
  398. return hr;
  399. }
  400. HRESULT Device::SetStatus(const wchar_t *deviceStatus)
  401. {
  402. HRESULT hr;
  403. Lock();
  404. if (NULL == deviceStatus && NULL == status)
  405. hr = S_FALSE;
  406. else
  407. {
  408. if (NULL != status &&
  409. CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, deviceStatus, -1, status, -1))
  410. {
  411. hr = S_FALSE;
  412. }
  413. else
  414. {
  415. wchar_t *string;
  416. string = String_Duplicate(deviceStatus);
  417. if (NULL == string && NULL != deviceStatus)
  418. hr = E_FAIL;
  419. else
  420. {
  421. String_Free(status);
  422. status = string;
  423. if (NULL != eventManager)
  424. eventManager->Notify_StatusChanged(this, status);
  425. hr = S_OK;
  426. }
  427. }
  428. }
  429. Unlock();
  430. return hr;
  431. }
  432. HRESULT Device::AddIcon(const wchar_t *path, unsigned int width, unsigned int height)
  433. {
  434. HRESULT hr;
  435. if (NULL == iconStore)
  436. return E_UNEXPECTED;
  437. hr = iconStore->Add(path, width, height, TRUE);
  438. if (SUCCEEDED(hr))
  439. {
  440. if (NULL != eventManager)
  441. eventManager->Notify_IconChanged(this);
  442. }
  443. return hr;
  444. }
  445. HRESULT Device::EnumerateIcons(ifc_deviceiconstore::EnumeratorCallback callback, void *user)
  446. {
  447. if (NULL == iconStore)
  448. return E_UNEXPECTED;
  449. return iconStore->Enumerate(callback, user);
  450. }
  451. HRESULT Device::RemoveIcon(unsigned int width, unsigned int height)
  452. {
  453. HRESULT hr;
  454. if (NULL == iconStore)
  455. return E_UNEXPECTED;
  456. hr = iconStore->Remove(width, height);
  457. if (SUCCEEDED(hr))
  458. {
  459. if (NULL != eventManager)
  460. eventManager->Notify_IconChanged(this);
  461. }
  462. return hr;
  463. }
  464. HRESULT Device::SetHidden(BOOL hiddenState)
  465. {
  466. HRESULT hr;
  467. Lock();
  468. if (hidden == (FALSE != hiddenState))
  469. hr = S_FALSE;
  470. else
  471. {
  472. hidden = (FALSE != hiddenState);
  473. hr = S_OK;
  474. }
  475. Unlock();
  476. if (S_OK == hr && NULL != eventManager)
  477. eventManager->Notify_VisibilityChanged(this, TRUE);
  478. return hr;
  479. }
  480. HRESULT Device::IsConnected()
  481. {
  482. HRESULT hr;
  483. Lock();
  484. hr = (FALSE != connected) ? S_OK : S_FALSE;
  485. Unlock();
  486. return hr;
  487. }
  488. HRESULT Device::Connect()
  489. {
  490. HRESULT hr;
  491. Lock();
  492. if (FALSE != connected)
  493. hr = S_FALSE;
  494. else
  495. {
  496. connected = TRUE;
  497. hr = S_OK;
  498. }
  499. Unlock();
  500. return hr;
  501. }
  502. HRESULT Device::Disconnect()
  503. {
  504. HRESULT hr;
  505. Lock();
  506. if (FALSE == connected)
  507. hr = S_FALSE;
  508. else
  509. {
  510. connected = FALSE;
  511. hr = S_OK;
  512. }
  513. Unlock();
  514. return hr;
  515. }
  516. HRESULT Device::CopyTo(Device *target)
  517. {
  518. if (NULL == target)
  519. return E_POINTER;
  520. Lock();
  521. target->SetDisplayName(displayName);
  522. if (NULL != target->iconStore)
  523. target->iconStore->Release();
  524. if (NULL == iconStore || FAILED(iconStore->Clone(&target->iconStore)))
  525. target->iconStore = NULL;
  526. target->usedSpace = usedSpace;
  527. target->totalSpace = totalSpace;
  528. target->hidden = hidden;
  529. target->attached = attached;
  530. target->connected = connected;
  531. if (NULL != target->commands)
  532. target->commands->Release();
  533. if (NULL == commands || FAILED(commands->Clone(&target->commands, TRUE)))
  534. target->commands = NULL;
  535. Unlock();
  536. return S_OK;
  537. }
  538. HRESULT Device::SetIconBase(const wchar_t *path)
  539. {
  540. if (NULL == iconStore)
  541. return E_UNEXPECTED;
  542. return iconStore->SetBasePath(path);
  543. }
  544. HRESULT Device::AddCommand(const char *command, DeviceCommandFlags flags)
  545. {
  546. if (NULL == commands)
  547. return E_UNEXPECTED;
  548. return commands->Add(command, flags);
  549. }
  550. HRESULT Device::RemoveCommand(const char *command)
  551. {
  552. if (NULL == commands)
  553. return E_UNEXPECTED;
  554. return commands->Remove(command);
  555. }
  556. HRESULT Device::SetCommandFlags(const char *command, DeviceCommandFlags mask, DeviceCommandFlags flags)
  557. {
  558. if (NULL == commands)
  559. return E_UNEXPECTED;
  560. return commands->SetFlags(command, mask, flags);
  561. }
  562. void Device::ActivityStartedCb(DeviceActivity *activity)
  563. {
  564. Device *device;
  565. if(FAILED(activity->GetUser((void**)&device)) || NULL == device)
  566. return;
  567. if (NULL != device->eventManager)
  568. device->eventManager->Notify_ActivityStarted(device, activity);
  569. }
  570. void Device::ActivityFinishedCb(DeviceActivity *activity)
  571. {
  572. Device *device;
  573. if(FAILED(activity->GetUser((void**)&device)) || NULL == device)
  574. return;
  575. device->Lock();
  576. if (activity == device->activity)
  577. device->activity = NULL;
  578. device->Unlock();
  579. if (NULL != device->eventManager)
  580. device->eventManager->Notify_ActivityFinished(device, activity);
  581. activity->Release();
  582. }
  583. void Device::ActivityProgressCb(DeviceActivity *activity, unsigned int progress, unsigned int duration)
  584. {
  585. Device *device;
  586. uint64_t space;
  587. if(FAILED(activity->GetUser((void**)&device)) || NULL == device)
  588. return;
  589. device->Lock();
  590. space = device->usedSpace;
  591. space++;
  592. if (space > device->totalSpace)
  593. space = 0;
  594. device->Unlock();
  595. device->SetUsedSpace(space);
  596. if (NULL != device->eventManager)
  597. device->eventManager->Notify_ActivityChanged(device, activity);
  598. }
  599. HRESULT Device::StartSyncActivity(HWND hostWindow)
  600. {
  601. HRESULT hr;
  602. Lock();
  603. if (NULL != activity)
  604. hr = E_PENDING;
  605. else
  606. {
  607. hr = DeviceActivity::CreateInstance(DeviceActivityFlag_Cancelable | DeviceActivityFlag_SupportProgress,
  608. ActivityStartedCb, ActivityFinishedCb, ActivityProgressCb,
  609. this, &activity);
  610. if (SUCCEEDED(hr))
  611. {
  612. activity->SetDisplayName(L"Synchronizing...");
  613. activity->SetStatus(L"Performing synchronization...");
  614. hr = activity->Start(60000, 20);
  615. if (FAILED(hr))
  616. {
  617. activity->Release();
  618. activity = NULL;
  619. }
  620. }
  621. }
  622. Unlock();
  623. return S_OK;
  624. }
  625. #define CBCLASS Device
  626. START_DISPATCH;
  627. CB(ADDREF, AddRef)
  628. CB(RELEASE, Release)
  629. CB(QUERYINTERFACE, QueryInterface)
  630. CB(API_GETNAME, GetName)
  631. CB(API_GETTYPE, GetType)
  632. CB(API_GETCONNECTION, GetConnection)
  633. CB(API_GETICON, GetIcon)
  634. CB(API_GETDISPLAYNAME, GetDisplayName)
  635. CB(API_GETHIDDEN, GetHidden)
  636. CB(API_GETTOTALSPACE, GetTotalSpace)
  637. CB(API_GETUSEDSPACE, GetUsedSpace)
  638. CB(API_GETATTACHED, GetAttached)
  639. CB(API_ATTACH, Attach)
  640. CB(API_DETACH, Detach)
  641. CB(API_ENUMERATECOMMANDS, EnumerateCommands)
  642. CB(API_SENDCOMMAND, SendCommand)
  643. CB(API_GETCOMMANDFLAGS, GetCommandFlags)
  644. CB(API_GETACTIVITY, GetActivity)
  645. CB(API_ADVISE, Advise)
  646. CB(API_UNADVISE, Unadvise)
  647. CB(API_CREATEVIEW, CreateView)
  648. VCB(API_SETNAVIGATIONITEM, SetNavigationItem)
  649. CB(API_SETDISPLAYNAME, SetDisplayName)
  650. CB(API_GETMODEL, GetModel)
  651. CB(API_GETSTATUS, GetStatus)
  652. END_DISPATCH;
  653. #undef CBCLASS