Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2994 lines
85 KiB

  1. /*++
  2. Copyright (C) 1999- Microsoft Corporation
  3. Module Name:
  4. minidrv.cpp
  5. Abstract:
  6. This module implements main part of CWiaMiniDriver class
  7. Author:
  8. William Hsieh (williamh) created
  9. Revision History:
  10. --*/
  11. #include "pch.h"
  12. #include <atlbase.h>
  13. #include <atlconv.h>
  14. #include <wiatempl.h>
  15. #include <stiregi.h>
  16. #include "utils.h"
  17. //
  18. // Strings that will be loaded from resource
  19. //
  20. WCHAR UnknownString[MAX_PATH] = L"\0";
  21. WCHAR FolderString[MAX_PATH] = L"\0";
  22. WCHAR ScriptString[MAX_PATH] = L"\0";
  23. WCHAR ExecString[MAX_PATH] = L"\0";
  24. WCHAR TextString[MAX_PATH] = L"\0";
  25. WCHAR HtmlString[MAX_PATH] = L"\0";
  26. WCHAR DpofString[MAX_PATH] = L"\0";
  27. WCHAR AudioString[MAX_PATH] = L"\0";
  28. WCHAR VideoString[MAX_PATH] = L"\0";
  29. WCHAR UnknownImgString[MAX_PATH] = L"\0";
  30. WCHAR ImageString[MAX_PATH] = L"\0";
  31. WCHAR AlbumString[MAX_PATH] = L"\0";
  32. WCHAR BurstString[MAX_PATH] = L"\0";
  33. WCHAR PanoramaString[MAX_PATH] = L"\0";
  34. //
  35. // Structures for setting up WIA capabilities
  36. //
  37. WCHAR DeviceConnectedString[MAX_PATH] = L"\0";
  38. WCHAR DeviceDisconnectedString[MAX_PATH] = L"\0";
  39. WCHAR ItemCreatedString[MAX_PATH] = L"\0";
  40. WCHAR ItemDeletedString[MAX_PATH] = L"\0";
  41. WCHAR TakePictureString[MAX_PATH] = L"\0";
  42. WCHAR SynchronizeString[MAX_PATH] = L"\0";
  43. WCHAR TreeUpdatedString[MAX_PATH] = L"\0";
  44. WCHAR VendorEventIconString[MAX_PATH] = WIA_ICON_DEVICE_CONNECTED;
  45. const BYTE NUMEVENTCAPS = 5;
  46. const BYTE NUMCMDCAPS = 2;
  47. WIA_DEV_CAP_DRV g_EventCaps[NUMEVENTCAPS] =
  48. {
  49. {(GUID *)&WIA_EVENT_DEVICE_CONNECTED,
  50. WIA_NOTIFICATION_EVENT | WIA_ACTION_EVENT,
  51. DeviceConnectedString,
  52. DeviceConnectedString,
  53. WIA_ICON_DEVICE_CONNECTED
  54. },
  55. {(GUID *)&WIA_EVENT_DEVICE_DISCONNECTED,
  56. WIA_NOTIFICATION_EVENT,
  57. DeviceDisconnectedString,
  58. DeviceDisconnectedString,
  59. WIA_ICON_DEVICE_DISCONNECTED
  60. },
  61. {(GUID *)&WIA_EVENT_ITEM_CREATED,
  62. WIA_NOTIFICATION_EVENT,
  63. ItemCreatedString,
  64. ItemCreatedString,
  65. WIA_ICON_ITEM_CREATED
  66. },
  67. {(GUID *)&WIA_EVENT_ITEM_DELETED,
  68. WIA_NOTIFICATION_EVENT,
  69. ItemDeletedString,
  70. ItemDeletedString,
  71. WIA_ICON_ITEM_DELETED
  72. },
  73. {(GUID *)&WIA_EVENT_TREE_UPDATED,
  74. WIA_NOTIFICATION_EVENT,
  75. TreeUpdatedString,
  76. TreeUpdatedString,
  77. WIA_ICON_BUILD_DEVICE_TREE
  78. }
  79. };
  80. WIA_DEV_CAP_DRV g_CmdCaps[NUMCMDCAPS] =
  81. {
  82. {(GUID*)&WIA_CMD_SYNCHRONIZE,
  83. 0,
  84. SynchronizeString,
  85. SynchronizeString,
  86. WIA_ICON_SYNCHRONIZE
  87. },
  88. {(GUID*)&WIA_CMD_TAKE_PICTURE,
  89. 0,
  90. TakePictureString,
  91. TakePictureString,
  92. WIA_ICON_TAKE_PICTURE
  93. }
  94. };
  95. //
  96. // Constructor
  97. //
  98. CWiaMiniDriver::CWiaMiniDriver(LPUNKNOWN punkOuter) :
  99. m_Capabilities(NULL),
  100. m_nEventCaps(0),
  101. m_nCmdCaps(0),
  102. m_fInitCaptureChecked(FALSE),
  103. m_OpenApps(0),
  104. m_pDrvItemRoot(NULL),
  105. m_pPTPCamera(NULL),
  106. m_NumImages(0),
  107. m_pStiDevice(NULL),
  108. m_bstrDeviceId(NULL),
  109. m_bstrRootItemFullName(NULL),
  110. m_pDcb(NULL),
  111. m_dwObjectBeingSent(0),
  112. m_TakePictureDoneEvent(NULL),
  113. m_hPtpMutex(NULL),
  114. m_bTwoDigitsMillisecondsOutput(FALSE),
  115. m_Refs(1)
  116. {
  117. ::InterlockedIncrement(&CClassFactory::s_Objects);
  118. if (punkOuter)
  119. m_punkOuter = punkOuter;
  120. else
  121. m_punkOuter = (IUnknown *)(INonDelegatingUnknown *)this;
  122. }
  123. //
  124. // Destructor
  125. //
  126. CWiaMiniDriver::~CWiaMiniDriver()
  127. {
  128. HRESULT hr = S_OK;
  129. Shutdown();
  130. //
  131. // CWiaMap<WORD, PROP_INFO *> m_VendorPropMap - delete all PROP_INFO objects
  132. // before calling RemoveAll()
  133. //
  134. for (int i = 0; i < m_VendorPropMap.GetSize(); i++)
  135. {
  136. delete m_VendorPropMap.GetValueAt(i);
  137. m_VendorPropMap.GetValueAt(i) = NULL;
  138. }
  139. m_VendorPropMap.RemoveAll();
  140. //
  141. // CWiaMap<WORD, CVendorEventInfo*> m_VendorEventMap - delete all CVendorEventInfo
  142. // objects before calling RemoveAll()
  143. //
  144. for (i = 0; i < m_VendorEventMap.GetSize(); i++)
  145. {
  146. delete m_VendorEventMap.GetValueAt(i);
  147. m_VendorEventMap.GetValueAt(i) = NULL;
  148. }
  149. m_VendorEventMap.RemoveAll();
  150. if (m_Capabilities)
  151. {
  152. delete[] m_Capabilities;
  153. }
  154. if (m_pStiDevice)
  155. m_pStiDevice->Release();
  156. if (m_pDcb)
  157. m_pDcb->Release();
  158. UnInitializeGDIPlus();
  159. ::InterlockedDecrement(&CClassFactory::s_Objects);
  160. }
  161. //
  162. // INonDelegatingUnknown interface
  163. //
  164. STDMETHODIMP_(ULONG)
  165. CWiaMiniDriver::NonDelegatingAddRef()
  166. {
  167. ::InterlockedIncrement((LONG *)&m_Refs);
  168. return m_Refs;
  169. }
  170. STDMETHODIMP_(ULONG)
  171. CWiaMiniDriver::NonDelegatingRelease()
  172. {
  173. ::InterlockedDecrement((LONG*)&m_Refs);
  174. if (!m_Refs)
  175. {
  176. delete this;
  177. return 0;
  178. }
  179. return m_Refs;
  180. }
  181. STDMETHODIMP
  182. CWiaMiniDriver::NonDelegatingQueryInterface(
  183. REFIID riid,
  184. void **ppv
  185. )
  186. {
  187. if (!ppv)
  188. return E_INVALIDARG;
  189. *ppv = NULL;
  190. if (IsEqualIID(riid, IID_IUnknown))
  191. *ppv = static_cast<INonDelegatingUnknown *>(this);
  192. else if (IsEqualIID(riid, IID_IStiUSD))
  193. *ppv = static_cast<IStiUSD *>(this);
  194. else if (IsEqualIID(riid, IID_IWiaMiniDrv))
  195. *ppv = static_cast<IWiaMiniDrv *>(this);
  196. else
  197. {
  198. return E_NOINTERFACE;
  199. }
  200. //
  201. // Do not call NonDelegatingAddRef() ....
  202. //
  203. (reinterpret_cast<IUnknown *>(*ppv))->AddRef();
  204. return S_OK;
  205. }
  206. //
  207. // IUnknown interface
  208. //
  209. STDMETHODIMP_(ULONG)
  210. CWiaMiniDriver::AddRef()
  211. {
  212. return m_punkOuter->AddRef();
  213. }
  214. STDMETHODIMP_(ULONG)
  215. CWiaMiniDriver::Release()
  216. {
  217. return m_punkOuter->Release();
  218. }
  219. STDMETHODIMP
  220. CWiaMiniDriver::QueryInterface(
  221. REFIID riid,
  222. void **ppv
  223. )
  224. {
  225. return m_punkOuter->QueryInterface(riid, ppv);
  226. }
  227. //
  228. // IStiUSD interface
  229. //
  230. STDMETHODIMP
  231. CWiaMiniDriver::Initialize(
  232. PSTIDEVICECONTROL pDcb,
  233. DWORD dwStiVersion,
  234. HKEY hParametersKey
  235. )
  236. {
  237. USES_CONVERSION;
  238. HRESULT hr;
  239. wiauDbgInit(g_hInst);
  240. DBG_FN("CWiaMiniDriver::Initialize");
  241. if (!pDcb)
  242. return STIERR_INVALID_PARAM;
  243. //
  244. // Check STI specification version number
  245. //
  246. m_pDcb = pDcb;
  247. m_pDcb->AddRef();
  248. hr = InitVendorExtentions(hParametersKey);
  249. if (FAILED(hr))
  250. {
  251. wiauDbgError("Initialize", "vendor extensions not loaded");
  252. //
  253. // Ignore errors from loading vendor extensions
  254. //
  255. hr = S_OK;
  256. }
  257. return hr;
  258. }
  259. STDMETHODIMP
  260. CWiaMiniDriver::GetCapabilities(PSTI_USD_CAPS pUsdCaps)
  261. {
  262. DBG_FN("CWiaMiniDriver::GetCapabilities");
  263. if (!pUsdCaps)
  264. return STIERR_INVALID_PARAM;
  265. ZeroMemory(pUsdCaps, sizeof(*pUsdCaps));
  266. pUsdCaps->dwVersion = STI_VERSION;
  267. pUsdCaps->dwGenericCaps = STI_GENCAP_AUTO_PORTSELECT;
  268. return S_OK;
  269. }
  270. STDMETHODIMP
  271. CWiaMiniDriver::GetStatus(PSTI_DEVICE_STATUS pDevStatus)
  272. {
  273. DBG_FN("CWiaMiniDriver::GetStatus");
  274. if (pDevStatus->StatusMask & STI_DEVSTATUS_ONLINE_STATE)
  275. pDevStatus->dwOnlineState |= STI_ONLINESTATE_OPERATIONAL;
  276. return S_OK;
  277. }
  278. STDMETHODIMP
  279. CWiaMiniDriver::DeviceReset(VOID)
  280. {
  281. DBG_FN("CWiaMiniDriver::DeviceReset");
  282. //
  283. // Camera may not be open if this method is called before
  284. // drvInitializeWia. For now just return S_OK.
  285. // return HRESULT_FROM_WIN32(m_pPTPCamera->ResetDevice());
  286. return S_OK;
  287. }
  288. STDMETHODIMP
  289. CWiaMiniDriver::Diagnostic(LPDIAG pBuffer)
  290. {
  291. DBG_FN("CWiaMiniDriver::Diagnostic");
  292. HRESULT hr = STI_OK;
  293. // Initialize response buffer
  294. pBuffer->sErrorInfo.dwGenericError = STI_NOTCONNECTED;
  295. pBuffer->sErrorInfo.dwVendorError = 0;
  296. STI_DEVICE_STATUS DevStatus;
  297. //
  298. // Call status method to verify device is available
  299. //
  300. ::ZeroMemory(&DevStatus,sizeof(DevStatus));
  301. DevStatus.StatusMask = STI_DEVSTATUS_ONLINE_STATE;
  302. // WIAFIX-8/9/2000-davepar Should this function actually talk to the camera?
  303. hr = GetStatus(&DevStatus);
  304. if (SUCCEEDED(hr))
  305. {
  306. if (DevStatus.dwOnlineState & STI_ONLINESTATE_OPERATIONAL)
  307. {
  308. pBuffer->sErrorInfo.dwGenericError = STI_OK;
  309. }
  310. }
  311. return(hr);
  312. }
  313. STDMETHODIMP
  314. CWiaMiniDriver::SetNotificationHandle(HANDLE hEvent)
  315. {
  316. DBG_FN("CWiaMiniDriver::SetNotificationHandle");
  317. // Use wiasQueueEvent instead
  318. return(S_OK);
  319. }
  320. STDMETHODIMP
  321. CWiaMiniDriver::GetNotificationData(LPSTINOTIFY pBuffer)
  322. {
  323. DBG_FN("CWiaMiniDriver::GetNotificationData");
  324. // Use wiasQueueEvent instead
  325. return STIERR_NOEVENTS;
  326. }
  327. STDMETHODIMP
  328. CWiaMiniDriver::Escape(
  329. STI_RAW_CONTROL_CODE EscapeFunction,
  330. LPVOID pInData,
  331. DWORD cbInDataSize,
  332. LPVOID pOutData,
  333. DWORD cbOutDataSize,
  334. LPDWORD pcbActualDataSize
  335. )
  336. {
  337. DBG_FN("CWiaMiniDriver::Escape");
  338. HRESULT hr = S_OK;
  339. //
  340. // Locals
  341. //
  342. PTP_VENDOR_DATA_IN *pVendorDataIn = NULL;
  343. PTP_VENDOR_DATA_OUT *pVendorDataOut = NULL;
  344. UINT NumCommandParams = 0;
  345. INT NextPhase = 0;
  346. BYTE *pReadData = NULL;
  347. BYTE *pWriteData = NULL;
  348. UINT ReadDataSize = 0;
  349. UINT WriteDataSize = 0;
  350. DWORD dwObjectToAdd = 0;
  351. DWORD dwObjectToRemove = 0;
  352. CPtpMutex cpm(m_hPtpMutex);
  353. if (EscapeFunction & ESCAPE_PTP_VENDOR_COMMAND) {
  354. REQUIRE_ARGS(!pInData || !pOutData || !pcbActualDataSize, hr, "Escape");
  355. if (cbInDataSize < SIZEOF_REQUIRED_VENDOR_DATA_IN) {
  356. wiauDbgError("Escape", "InDataSize is too small");
  357. hr = E_FAIL;
  358. goto Cleanup;
  359. }
  360. if (cbOutDataSize < SIZEOF_REQUIRED_VENDOR_DATA_OUT) {
  361. wiauDbgError("Escape", "OutDataSize is too small");
  362. hr = E_FAIL;
  363. goto Cleanup;
  364. }
  365. //
  366. // Set up some more convenient pointers
  367. //
  368. pVendorDataIn = (PTP_VENDOR_DATA_IN *) pInData;
  369. pVendorDataOut = (PTP_VENDOR_DATA_OUT *) pOutData;
  370. if (!(pVendorDataIn->OpCode & PTP_DATACODE_VENDORMASK))
  371. {
  372. wiauDbgWarning("VendorCommand", "executing non-vendor command");
  373. }
  374. NumCommandParams = pVendorDataIn->NumParams;
  375. NextPhase = pVendorDataIn->NextPhase;
  376. //
  377. // Verify that NumCommandParams and NextPhase are correct
  378. //
  379. if (NumCommandParams > COMMAND_NUMPARAMS_MAX ||
  380. (NextPhase != PTP_NEXTPHASE_READ_DATA &&
  381. NextPhase != PTP_NEXTPHASE_WRITE_DATA &&
  382. NextPhase != PTP_NEXTPHASE_NO_DATA))
  383. {
  384. hr = E_INVALIDARG;
  385. goto Cleanup;
  386. }
  387. //
  388. // Data to write and read buffer are right after command and response,
  389. // respectively
  390. //
  391. if (cbInDataSize > SIZEOF_REQUIRED_VENDOR_DATA_IN) {
  392. pWriteData = pVendorDataIn->VendorWriteData;
  393. WriteDataSize = cbInDataSize - SIZEOF_REQUIRED_VENDOR_DATA_IN;
  394. }
  395. if (cbOutDataSize > SIZEOF_REQUIRED_VENDOR_DATA_OUT) {
  396. pReadData = pVendorDataOut->VendorReadData;
  397. ReadDataSize = cbOutDataSize - SIZEOF_REQUIRED_VENDOR_DATA_OUT;
  398. }
  399. hr = m_pPTPCamera->VendorCommand((PTP_COMMAND *) pInData, (PTP_RESPONSE *) pOutData,
  400. &ReadDataSize, pReadData,
  401. WriteDataSize, pWriteData,
  402. NumCommandParams, NextPhase);
  403. REQUIRE_SUCCESS(hr, "Escape", "VendorCommand failed");
  404. *pcbActualDataSize = SIZEOF_REQUIRED_VENDOR_DATA_OUT + ReadDataSize;
  405. //
  406. // For SendObjectInfo, hand on to handle until SendObject command
  407. //
  408. if (pVendorDataIn->OpCode == PTP_OPCODE_SENDOBJECTINFO) {
  409. m_dwObjectBeingSent = pVendorDataOut->Params[2];
  410. //
  411. // For SendObject, add object
  412. //
  413. } else if (pVendorDataIn->OpCode == PTP_OPCODE_SENDOBJECT) {
  414. dwObjectToAdd = m_dwObjectBeingSent;
  415. m_dwObjectBeingSent = 0;
  416. //
  417. // Otherwise, see if add or remove flag is set
  418. //
  419. } else {
  420. if ((EscapeFunction & 0xf) >= PTP_MAX_PARAMS) {
  421. wiauDbgError("Escape", "Parameter number too large");
  422. hr = E_FAIL;
  423. goto Cleanup;
  424. }
  425. if (EscapeFunction & ESCAPE_PTP_ADD_OBJ_CMD) {
  426. dwObjectToAdd = pVendorDataIn->Params[EscapeFunction & 0xf];
  427. }
  428. if (EscapeFunction & ESCAPE_PTP_REM_OBJ_CMD) {
  429. dwObjectToRemove = pVendorDataIn->Params[EscapeFunction & 0xf];
  430. }
  431. if (EscapeFunction & ESCAPE_PTP_ADD_OBJ_RESP) {
  432. dwObjectToAdd = pVendorDataOut->Params[EscapeFunction & 0xf];
  433. }
  434. if (EscapeFunction & ESCAPE_PTP_REM_OBJ_RESP) {
  435. dwObjectToRemove = pVendorDataOut->Params[EscapeFunction & 0xf];
  436. }
  437. }
  438. if (dwObjectToAdd) {
  439. hr = AddObject(dwObjectToAdd, TRUE);
  440. REQUIRE_SUCCESS(hr, "Escape", "AddObject failed");
  441. }
  442. if (dwObjectToRemove) {
  443. hr = RemoveObject(dwObjectToRemove);
  444. REQUIRE_SUCCESS(hr, "Escape", "DeleteObject failed");
  445. }
  446. }
  447. else if(EscapeFunction == ESCAPE_PTP_CLEAR_STALLS) {
  448. hr = m_pPTPCamera->RecoverFromError();
  449. }
  450. else
  451. hr = STIERR_UNSUPPORTED;
  452. Cleanup:
  453. return hr;
  454. }
  455. STDMETHODIMP
  456. CWiaMiniDriver::GetLastError(LPDWORD pdwLastDeviceError)
  457. {
  458. DBG_FN("CWiaMiniDriver::GetLastError");
  459. HRESULT hr = STI_OK;
  460. if (IsBadWritePtr(pdwLastDeviceError, 4))
  461. {
  462. hr = STIERR_INVALID_PARAM;
  463. }
  464. else
  465. {
  466. *pdwLastDeviceError = 0;
  467. }
  468. return(hr);
  469. }
  470. STDMETHODIMP
  471. CWiaMiniDriver::GetLastErrorInfo(STI_ERROR_INFO *pLastErrorInfo)
  472. {
  473. DBG_FN("CWiaMiniDriver::GetLastErrorInfo");
  474. HRESULT hr = STI_OK;
  475. if (IsBadWritePtr(pLastErrorInfo, 4))
  476. {
  477. hr = STIERR_INVALID_PARAM;
  478. }
  479. else
  480. {
  481. pLastErrorInfo->dwGenericError = 0;
  482. pLastErrorInfo->szExtendedErrorText[0] = L'\0';
  483. }
  484. return(hr);
  485. }
  486. STDMETHODIMP
  487. CWiaMiniDriver::LockDevice(VOID)
  488. {
  489. DBG_FN("CWiaMiniDriver::LockDevice");
  490. return(S_OK);
  491. }
  492. STDMETHODIMP
  493. CWiaMiniDriver::UnLockDevice(VOID)
  494. {
  495. DBG_FN("CWiaMiniDriver::UnLockDevice");
  496. return(S_OK);
  497. }
  498. STDMETHODIMP
  499. CWiaMiniDriver::RawReadData(
  500. LPVOID lpBuffer,
  501. LPDWORD lpdwNumberOfBytes,
  502. LPOVERLAPPED lpOverlapped
  503. )
  504. {
  505. DBG_FN("CWiaMiniDriver::RawReadData");
  506. return(STIERR_UNSUPPORTED);
  507. }
  508. STDMETHODIMP
  509. CWiaMiniDriver::RawWriteData(
  510. LPVOID lpBuffer,
  511. DWORD dwNumberOfBytes,
  512. LPOVERLAPPED lpOverlapped
  513. )
  514. {
  515. DBG_FN("CWiaMiniDriver::RawWriteData");
  516. return(STIERR_UNSUPPORTED);
  517. }
  518. STDMETHODIMP
  519. CWiaMiniDriver::RawReadCommand(
  520. LPVOID lpBuffer,
  521. LPDWORD lpdwNumberOfBytes,
  522. LPOVERLAPPED lpOverlapped
  523. )
  524. {
  525. DBG_FN("CWiaMiniDriver::RawReadCommand");
  526. return(STIERR_UNSUPPORTED);
  527. }
  528. STDMETHODIMP
  529. CWiaMiniDriver::RawWriteCommand(
  530. LPVOID lpBuffer,
  531. DWORD nNumberOfBytes,
  532. LPOVERLAPPED lpOverlapped
  533. )
  534. {
  535. DBG_FN("CWiaMiniDriver::RawWriteCommand");
  536. return(STIERR_UNSUPPORTED);
  537. }
  538. /////////////////////////////////////////////////////
  539. //
  540. // IWiaMiniDrvItem methods
  541. //
  542. /////////////////////////////////////////////////////
  543. //
  544. // This method is the first call to initialize the mini driver
  545. // This is where a mini driver establish its IWiaDrvItem tree
  546. //
  547. // Input:
  548. // pWiasContext -- context used to call Wias service
  549. // lFlags -- misc flags. Not used for now
  550. // bstrDeviceId -- the device id
  551. // bstrRootItemFullName -- the full name of root driver item
  552. // pStiDevice -- IStiDevice interface pointer
  553. // punkOuter -- not used.
  554. // ppDrvItemRoot -- to return our root IWiaDrvItem
  555. // ppunkInner -- mini driver special interface which allows
  556. // the applications to directly access.
  557. // plDevErrVal -- to return device error code.
  558. //
  559. HRESULT
  560. CWiaMiniDriver::drvInitializeWia(
  561. BYTE *pWiasContext,
  562. LONG lFlags,
  563. BSTR bstrDeviceID,
  564. BSTR bstrRootItemFullName,
  565. IUnknown *pStiDevice,
  566. IUnknown *punkOuter,
  567. IWiaDrvItem **ppDrvItemRoot,
  568. IUnknown **ppunkInner,
  569. LONG *plDevErrVal
  570. )
  571. {
  572. #define REQUIRE(x, y) if(!(x)) { wiauDbgError("drvInitializeWia", y); hr = HRESULT_FROM_WIN32(::GetLastError()); goto Cleanup; }
  573. #define REQUIRE_SUCCESS_(x, y) if(FAILED(x)) { wiauDbgError("drvInitializeWia", y); goto Cleanup; }
  574. DBG_FN("CWiaMiniDriver::drvInitializeWia");
  575. HRESULT hr = S_OK;
  576. *plDevErrVal = DEVERR_OK;
  577. if (!ppDrvItemRoot || !ppunkInner || !plDevErrVal)
  578. {
  579. wiauDbgError("drvInitializeWia", "invalid arg");
  580. return E_INVALIDARG;
  581. }
  582. *ppDrvItemRoot = NULL;
  583. *ppunkInner = NULL;
  584. m_OpenApps++;
  585. //
  586. // If this is the first app, create everything
  587. //
  588. if (m_OpenApps == 1)
  589. {
  590. //
  591. // Load the strings from the resource
  592. //
  593. hr = LoadStrings();
  594. REQUIRE_SUCCESS_(hr, "LoadStrings failed");
  595. //
  596. // Set up a mutex to guarantee exclusive access to the device and the minidriver's structures
  597. //
  598. if(!m_hPtpMutex) {
  599. m_hPtpMutex = CreateMutex(NULL, FALSE, NULL);
  600. REQUIRE(m_hPtpMutex, "CreateMutex failed");
  601. }
  602. {
  603. CPtpMutex cpm(m_hPtpMutex);
  604. *ppDrvItemRoot = NULL;
  605. //
  606. // Create event for waiting for TakePicture command to complete
  607. //
  608. if (!m_TakePictureDoneEvent)
  609. {
  610. m_TakePictureDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  611. REQUIRE(m_TakePictureDoneEvent, "CreateEvent failed");
  612. }
  613. //
  614. // Allocate strings needed for later
  615. //
  616. if (!m_bstrDeviceId)
  617. {
  618. m_bstrDeviceId = SysAllocString(bstrDeviceID);
  619. REQUIRE(m_bstrDeviceId, "failed to allocate Device ID string");
  620. }
  621. if (!m_bstrRootItemFullName)
  622. {
  623. m_bstrRootItemFullName = SysAllocString(bstrRootItemFullName);
  624. REQUIRE(m_bstrRootItemFullName, "failed to allocate root item name");
  625. }
  626. //
  627. // Create a camera object. Right now we only handle USB, but in the future this could look at the
  628. // port name to figure out what type of camera to create.
  629. //
  630. if (!m_pPTPCamera)
  631. {
  632. m_pPTPCamera = new CUsbCamera;
  633. REQUIRE(m_pPTPCamera, "failed to new CUsbCamera");
  634. }
  635. //
  636. // Open the camera
  637. //
  638. if (!m_pPTPCamera->IsCameraOpen())
  639. {
  640. //
  641. // Retrieve the port name from the ISTIDeviceControl
  642. //
  643. WCHAR wcsPortName[MAX_PATH];
  644. hr = m_pDcb->GetMyDevicePortName(wcsPortName, sizeof(wcsPortName));
  645. REQUIRE_SUCCESS_(hr, "GetMyDevicePortName failed");
  646. hr = m_pPTPCamera->Open(wcsPortName, &EventCallback, &DataCallback, (LPVOID) this);
  647. REQUIRE_SUCCESS_(hr, "Camera open failed");
  648. }
  649. //
  650. // Open a session on the camera. Doesn't matter which session ID we use, so just use 1.
  651. //
  652. if (!m_pPTPCamera->IsCameraSessionOpen())
  653. {
  654. hr = m_pPTPCamera->OpenSession(WIA_SESSION_ID);
  655. REQUIRE_SUCCESS_(hr, "OpenSession failed");
  656. }
  657. //
  658. // Get the DeviceInfo for the camera
  659. //
  660. hr = m_pPTPCamera->GetDeviceInfo(&m_DeviceInfo);
  661. REQUIRE_SUCCESS_(hr, "GetDeviceInfo failed");
  662. //
  663. // Remove properties that aren't supported by WIA. RGB gain isn't supported
  664. // because PTP defines it as a string and WIA can't handle string ranges.
  665. //
  666. m_DeviceInfo.m_SupportedProps.Remove(PTP_PROPERTYCODE_RGBGAIN);
  667. m_DeviceInfo.m_SupportedProps.Remove(PTP_PROPERTYCODE_FUNCTIONMODE);
  668. //
  669. // Special hack for the Kodak DC4800
  670. //
  671. // Some property codes (which the camera says it supports) cause the camera to
  672. // stall the endpoint when the GetDevicePropDesc command is sent
  673. // The hack can be removed only if support of DC4800 is removed
  674. //
  675. if (m_pPTPCamera->GetHackModel() == HACK_MODEL_DC4800)
  676. {
  677. wiauDbgTrace("drvInitializeWia", "removing DC4800 unsupported props");
  678. const WORD KODAK_PROPCODE_D001 = 0xD001;
  679. m_DeviceInfo.m_SupportedProps.Remove(PTP_PROPERTYCODE_RGBGAIN);
  680. m_DeviceInfo.m_SupportedProps.Remove(PTP_PROPERTYCODE_FNUMBER);
  681. m_DeviceInfo.m_SupportedProps.Remove(PTP_PROPERTYCODE_FOCUSDISTANCE);
  682. m_DeviceInfo.m_SupportedProps.Remove(PTP_PROPERTYCODE_EXPOSURETIME);
  683. m_DeviceInfo.m_SupportedProps.Remove(KODAK_PROPCODE_D001);
  684. }
  685. //
  686. // Get all the StorageInfo structures
  687. //
  688. if (m_StorageIds.GetSize() == 0)
  689. {
  690. hr = m_pPTPCamera->GetStorageIDs(&m_StorageIds);
  691. REQUIRE_SUCCESS_(hr, "GetStorageIDs failed");
  692. CPtpStorageInfo tempSI;
  693. for (int count = 0; count < m_StorageIds.GetSize(); count++)
  694. {
  695. REQUIRE(m_StorageInfos.Add(tempSI), "memory allocation failed");
  696. //
  697. // Get info about logical storages only. If we ask for info about non-logical
  698. // storage (ejected media), it may stall the camera.
  699. //
  700. if (m_StorageIds[count] & PTP_STORAGEID_LOGICAL)
  701. {
  702. hr = m_pPTPCamera->GetStorageInfo(m_StorageIds[count], &m_StorageInfos[count]);
  703. REQUIRE_SUCCESS_(hr, "GetStorageInfo failed");
  704. }
  705. //
  706. // Add an empty entry to the DCIM handle array
  707. //
  708. ULONG dummy = 0;
  709. REQUIRE(m_DcimHandle.Add(dummy), "add dcim handle failed");
  710. }
  711. }
  712. //
  713. // Get all of the property description structures supported by the device
  714. //
  715. if (m_PropDescs.GetSize() == 0)
  716. {
  717. CPtpPropDesc tempPD;
  718. int NumProps = m_DeviceInfo.m_SupportedProps.GetSize();
  719. REQUIRE(m_PropDescs.GrowTo(NumProps), "reallocation of supported properties array failed");
  720. PROP_INFO *pPropInfo = NULL;
  721. WORD PropCode = 0;
  722. for (int count = 0; count < NumProps; count++)
  723. {
  724. PropCode = m_DeviceInfo.m_SupportedProps[count];
  725. //
  726. // Remove properties that aren't supported by this driver or by
  727. // vendor entries in the INF
  728. //
  729. pPropInfo = PropCodeToPropInfo(PropCode);
  730. if (!pPropInfo->PropId &&
  731. PropCode != PTP_PROPERTYCODE_IMAGESIZE)
  732. {
  733. wiauDbgTrace("drvInitializeWia", "removing unsupported prop, 0x%04x", PropCode);
  734. m_DeviceInfo.m_SupportedProps.RemoveAt(count);
  735. NumProps--;
  736. count--;
  737. }
  738. else
  739. {
  740. //
  741. // Get the property description info from the device
  742. //
  743. REQUIRE(m_PropDescs.Add(tempPD), "add prop desc failed");
  744. hr = m_pPTPCamera->GetDevicePropDesc(PropCode, &m_PropDescs[count]);
  745. REQUIRE_SUCCESS_(hr, "GetDevicePropDesc failed");
  746. }
  747. }
  748. }
  749. //
  750. // Cache the STI interface
  751. //
  752. if (!m_pStiDevice)
  753. {
  754. m_pStiDevice = (IStiDevice *)pStiDevice;
  755. m_pStiDevice->AddRef();
  756. }
  757. //
  758. // Build the tree, if we haven't already
  759. //
  760. if (!m_pDrvItemRoot)
  761. {
  762. hr = CreateDrvItemTree(&m_pDrvItemRoot);
  763. REQUIRE_SUCCESS_(hr, "CreateDrvItemTree failed");
  764. }
  765. }
  766. }
  767. *ppDrvItemRoot = m_pDrvItemRoot;
  768. Cleanup:
  769. if(FAILED(hr)) {
  770. // force re-init to happen next time someone tries to create
  771. // device
  772. m_OpenApps = 0;
  773. }
  774. //
  775. // Update WIA on any changes in camera's state, like 'camera was reset'
  776. //
  777. NotifyWiaOnStateChanges();
  778. return hr;
  779. }
  780. //
  781. // This methods gets called when a client connection is going away.
  782. //
  783. // Input:
  784. // pWiasContext -- Pointer to the WIA Root item context of the client's item tree.
  785. //
  786. HRESULT
  787. CWiaMiniDriver::drvUnInitializeWia(BYTE *pWiasContext)
  788. {
  789. DBG_FN("CWiaMiniDriver::drvUnInitializeWia");
  790. HRESULT hr = S_OK;
  791. if (!pWiasContext)
  792. {
  793. wiauDbgError("drvUnInitializeWia", "invalid arg");
  794. return E_INVALIDARG;
  795. }
  796. m_OpenApps--;
  797. if (m_OpenApps == 0)
  798. {
  799. Shutdown();
  800. }
  801. if(m_OpenApps < 0) {
  802. // allow unmatched drvUninializeWia calls and don't ever make
  803. // m_OpenApps negative
  804. m_OpenApps = 0;
  805. }
  806. return hr;
  807. }
  808. //
  809. // This method executes a command on the device
  810. //
  811. // Input:
  812. // pWiasContext -- context used to call wias services
  813. // lFlags -- Misc flags, not used
  814. // pCommandGuid -- the command guid
  815. // ppDrvItem -- new IWiaDrvItem if the command creates new item
  816. // plDevErrVal -- to return device error code
  817. //
  818. HRESULT
  819. CWiaMiniDriver::drvDeviceCommand(
  820. BYTE *pWiasContext,
  821. LONG lFlags,
  822. const GUID *pCommandGuid,
  823. IWiaDrvItem **ppDrvItem,
  824. LONG *plDevErrVal
  825. )
  826. {
  827. DBG_FN("CWiaMiniDriver::drvDeviceCommand");
  828. HRESULT hr = S_OK;
  829. if (!pWiasContext || !pCommandGuid || !ppDrvItem || !plDevErrVal)
  830. {
  831. wiauDbgError("drvDeviceCommand", "invalid arg");
  832. return E_INVALIDARG;
  833. }
  834. *ppDrvItem = NULL;
  835. *plDevErrVal = DEVERR_OK;
  836. if (*pCommandGuid == WIA_CMD_TAKE_PICTURE && m_DeviceInfo.m_SupportedOps.Find(PTP_OPCODE_INITIATECAPTURE) >= 0)
  837. {
  838. LONG ItemType = 0;
  839. hr = wiasGetItemType(pWiasContext, &ItemType);
  840. if (FAILED(hr))
  841. {
  842. wiauDbgError("drvDeviceCommand", "wiasGetItemType failed");
  843. goto cleanup;
  844. }
  845. //
  846. // TakePicture only works on the root
  847. //
  848. if (WiaItemTypeRoot & ItemType)
  849. {
  850. hr = WriteDeviceProperties(pWiasContext);
  851. if (FAILED(hr))
  852. {
  853. wiauDbgError("drvDeviceCommand", "WriteDeviceProperties failed");
  854. goto cleanup;
  855. }
  856. hr = TakePicture(pWiasContext, ppDrvItem);
  857. if (FAILED(hr))
  858. {
  859. wiauDbgError("drvDeviceCommand", "TakePicture failed");
  860. goto cleanup;
  861. }
  862. }
  863. }
  864. else if (*pCommandGuid == WIA_CMD_SYNCHRONIZE)
  865. {
  866. //
  867. // Don't need to do anything, because the PTP driver is always in sync with the device
  868. //
  869. }
  870. else
  871. {
  872. hr = E_NOTIMPL;
  873. }
  874. cleanup:
  875. //
  876. // Update WIA on any changes in camera's state, like 'camera was reset'
  877. //
  878. NotifyWiaOnStateChanges();
  879. return hr;
  880. }
  881. //
  882. // This method deletes an object from the camera. The WIA service will ensure that
  883. // the item has no children and has access rights to be deleted, and the service will
  884. // take care of deleting the driver item and calling drvFreeItemContext.
  885. //
  886. // Input:
  887. // pWiasContext -- wias context that identifies the item
  888. // lFlags -- misc flags
  889. // plDevErrVal -- to return the device error
  890. //
  891. STDMETHODIMP
  892. CWiaMiniDriver::drvDeleteItem(
  893. BYTE *pWiasContext,
  894. LONG lFlags,
  895. LONG *plDevErrVal
  896. )
  897. {
  898. DBG_FN("CWiaMiniDriver::drvDeleteItem");
  899. HRESULT hr = S_OK;
  900. if (!pWiasContext || !plDevErrVal)
  901. {
  902. wiauDbgError("drvDeleteItem", "invalid arg");
  903. return E_INVALIDARG;
  904. }
  905. //
  906. // Verify that PTP_OPCODE_DELETEOBJECT command is supported by the camera
  907. //
  908. if (m_DeviceInfo.m_SupportedOps.Find(PTP_OPCODE_DELETEOBJECT) < 0)
  909. {
  910. wiauDbgError("drvDeleteItem", "PTP_OPCODE_DELETEOBJECT command is not supported by the camera");
  911. return E_NOTIMPL;
  912. }
  913. *plDevErrVal = DEVERR_OK;
  914. CPtpMutex cpm(m_hPtpMutex);
  915. IWiaDrvItem *pDrvItem;
  916. DRVITEM_CONTEXT *pItemCtx;
  917. hr = WiasContextToItemContext(pWiasContext, &pItemCtx, &pDrvItem);
  918. if (FAILED(hr))
  919. {
  920. wiauDbgError("drvDeleteItem", "WiasContextToItemContext failed");
  921. goto cleanup;
  922. }
  923. //
  924. // Delete the object on the camera
  925. //
  926. hr = m_pPTPCamera->DeleteObject(pItemCtx->pObjectInfo->m_ObjectHandle, 0);
  927. if (FAILED(hr))
  928. {
  929. wiauDbgError("drvDeleteItem", "DeleteObject failed");
  930. goto cleanup;
  931. }
  932. //
  933. // Keep count of the number of images
  934. //
  935. if (pItemCtx->pObjectInfo->m_FormatCode & PTP_FORMATMASK_IMAGE)
  936. {
  937. m_NumImages--;
  938. }
  939. //
  940. // Update Storage Info (we are especially interested in Free Space info)
  941. //
  942. hr = UpdateStorageInfo(pItemCtx->pObjectInfo->m_StorageId);
  943. if (FAILED(hr))
  944. {
  945. wiauDbgError("drvDeleteItem", "UpdateStorageInfo failed");
  946. // we can proceed, even if storage info can't be updated
  947. }
  948. //
  949. // Remove the item from the m_HandleItem map
  950. //
  951. m_HandleItem.Remove(pItemCtx->pObjectInfo->m_ObjectHandle);
  952. //
  953. // Get the item's full name
  954. //
  955. BSTR bstrFullName;
  956. hr = pDrvItem->GetFullItemName(&bstrFullName);
  957. if (FAILED(hr))
  958. {
  959. wiauDbgError("drvDeleteItem", "GetFullItemName failed");
  960. goto cleanup;
  961. }
  962. //
  963. // Queue an "item deleted" event
  964. //
  965. hr = wiasQueueEvent(m_bstrDeviceId,
  966. &WIA_EVENT_ITEM_DELETED,
  967. bstrFullName);
  968. if (FAILED(hr))
  969. {
  970. wiauDbgErrorHr(hr, "drvDeleteItem", "wiasQueueEvent failed");
  971. // Continue to free the string and return hr
  972. }
  973. SysFreeString(bstrFullName);
  974. cleanup:
  975. //
  976. // Update WIA on any changes in camera's state, like 'camera was reset'
  977. //
  978. NotifyWiaOnStateChanges();
  979. return hr;
  980. }
  981. //
  982. // This method updates Storage Info for the specified storage
  983. // Input:
  984. // StorageId - ID of the sorage to be updated
  985. //
  986. HRESULT CWiaMiniDriver::UpdateStorageInfo(ULONG StorageId)
  987. {
  988. HRESULT hr = S_FALSE;
  989. BOOL bDone = FALSE;
  990. for (int count = 0; (count < m_StorageIds.GetSize()) && (!bDone); count++)
  991. {
  992. if (m_StorageIds[count] == StorageId)
  993. {
  994. bDone = TRUE;
  995. hr = m_pPTPCamera->GetStorageInfo(m_StorageIds[count], &m_StorageInfos[count]);
  996. }
  997. }
  998. return hr;
  999. }
  1000. //
  1001. // This method returns the device capabilities
  1002. //
  1003. // Input:
  1004. // pWiasContext -- wias service context
  1005. // lFlags -- indicate what capabilities to return
  1006. // pCelt -- to return number of entries are returned
  1007. // ppCapbilities -- to receive the capabilities
  1008. // plDevErrVal -- to return device error
  1009. //
  1010. STDMETHODIMP
  1011. CWiaMiniDriver::drvGetCapabilities(
  1012. BYTE *pWiasContext,
  1013. LONG lFlags,
  1014. LONG *pCelt,
  1015. WIA_DEV_CAP_DRV **ppCapabilities,
  1016. LONG *plDevErrVal
  1017. )
  1018. {
  1019. DBG_FN("CWiaMiniDriver::drvGetCapabilities");
  1020. HRESULT hr = S_OK;
  1021. if (!pCelt || !ppCapabilities || !plDevErrVal)
  1022. {
  1023. wiauDbgError("drvGetCapabilities", "invalid arg");
  1024. return E_INVALIDARG;
  1025. }
  1026. *plDevErrVal = DEVERR_OK;
  1027. //
  1028. // Load the strings from the resource
  1029. //
  1030. hr = LoadStrings();
  1031. if (FAILED(hr))
  1032. {
  1033. wiauDbgError("drvGetCapabilities", "LoadStrings failed");
  1034. return E_FAIL;
  1035. }
  1036. //
  1037. // check if we have already built the list of capabilities. If not, build it
  1038. // It will have the following structure:
  1039. //
  1040. // XXXXXXXXXXXXXXXXXXXXXXXXX YYYYYYYYYYYYYYYYYYYYYYYYYYY ZZZZZZZZZZZZZZZZZZZZZZZ
  1041. // (predefined events) (vendor events) (predefined commands)
  1042. //
  1043. if (m_Capabilities == NULL)
  1044. {
  1045. UINT nVendorEvents = m_VendorEventMap.GetSize();
  1046. if (nVendorEvents > MAX_VENDOR_EVENTS)
  1047. {
  1048. wiauDbgWarning("drvGetCapabilities", "vendor events limit exceeded, ignoring events over limit");
  1049. nVendorEvents = MAX_VENDOR_EVENTS;
  1050. }
  1051. m_nEventCaps = NUMEVENTCAPS + nVendorEvents;
  1052. m_nCmdCaps = NUMCMDCAPS; // we don't need to put vendor commands in the list. they are called through escape function
  1053. m_Capabilities = new WIA_DEV_CAP_DRV[m_nEventCaps + m_nCmdCaps]; // WIA uses this array instead of copying, don't delete it
  1054. if (m_Capabilities == NULL)
  1055. {
  1056. return E_OUTOFMEMORY;
  1057. }
  1058. //
  1059. // create events first
  1060. //
  1061. memcpy(m_Capabilities, g_EventCaps, sizeof(g_EventCaps)); // default events
  1062. for (UINT i = 0; i < nVendorEvents; i++) // vendor events
  1063. {
  1064. CVendorEventInfo *pEventInfo = m_VendorEventMap.GetValueAt(i);
  1065. m_Capabilities[NUMEVENTCAPS + i].guid = pEventInfo->pGuid;
  1066. m_Capabilities[NUMEVENTCAPS + i].ulFlags = WIA_NOTIFICATION_EVENT | WIA_ACTION_EVENT;
  1067. m_Capabilities[NUMEVENTCAPS + i].wszIcon = VendorEventIconString;
  1068. m_Capabilities[NUMEVENTCAPS + i].wszName = pEventInfo->EventName;
  1069. m_Capabilities[NUMEVENTCAPS + i].wszDescription = pEventInfo->EventName;
  1070. }
  1071. //
  1072. // add commands
  1073. //
  1074. memcpy(m_Capabilities + m_nEventCaps, g_CmdCaps, sizeof(g_CmdCaps));
  1075. }
  1076. //
  1077. // eventing code calls this entry point without first going
  1078. // through drvInitializeWia
  1079. //
  1080. if(lFlags == WIA_DEVICE_EVENTS)
  1081. {
  1082. *pCelt = m_nEventCaps;
  1083. *ppCapabilities = m_Capabilities;
  1084. return S_OK;
  1085. }
  1086. //
  1087. // query if camera supports InitiateCapture command (if we hadn't already)
  1088. //
  1089. if (!m_fInitCaptureChecked)
  1090. {
  1091. m_fInitCaptureChecked = TRUE;
  1092. CPtpMutex cpm(m_hPtpMutex);
  1093. if (m_DeviceInfo.m_SupportedOps.Find(PTP_OPCODE_INITIATECAPTURE) < 0)
  1094. {
  1095. m_nCmdCaps--;
  1096. }
  1097. }
  1098. //
  1099. // Report commands or (events and commands)
  1100. //
  1101. switch (lFlags)
  1102. {
  1103. case WIA_DEVICE_COMMANDS:
  1104. *pCelt = m_nCmdCaps;
  1105. //
  1106. // Command capability list is right behind the event list
  1107. //
  1108. *ppCapabilities = m_Capabilities + m_nEventCaps;
  1109. break;
  1110. case (WIA_DEVICE_EVENTS | WIA_DEVICE_COMMANDS):
  1111. *pCelt = m_nEventCaps + m_nCmdCaps;
  1112. *ppCapabilities = m_Capabilities;
  1113. break;
  1114. default:
  1115. break;
  1116. }
  1117. //
  1118. // Update WIA on any changes in camera's state, like 'camera was reset'
  1119. //
  1120. NotifyWiaOnStateChanges();
  1121. return hr;
  1122. }
  1123. //
  1124. // This method initializes an item's properties. If the item is the
  1125. // root item, this function initializes the device properties.
  1126. //
  1127. // Input:
  1128. // pWiasContext -- wias service context
  1129. // lFlags -- misc flags
  1130. // plDevErrVal -- to return device error
  1131. //
  1132. STDMETHODIMP
  1133. CWiaMiniDriver::drvInitItemProperties(
  1134. BYTE *pWiasContext,
  1135. LONG lFlags,
  1136. LONG *plDevErrVal
  1137. )
  1138. {
  1139. DBG_FN("CWiaMiniDriver::drvInitItemProperties");
  1140. HRESULT hr = S_OK;
  1141. if (!pWiasContext || !plDevErrVal)
  1142. {
  1143. wiauDbgError("drvInitItemProperties", "invalid arg");
  1144. return E_INVALIDARG;
  1145. }
  1146. *plDevErrVal = DEVERR_OK;
  1147. CPtpMutex cpm(m_hPtpMutex);
  1148. LONG ItemType;
  1149. hr = wiasGetItemType(pWiasContext, &ItemType);
  1150. if (FAILED(hr))
  1151. {
  1152. wiauDbgErrorHr(hr, "drvInitItemProperties", "wiasGetItemType failed");
  1153. goto cleanup;
  1154. }
  1155. if (ItemType & WiaItemTypeRoot)
  1156. {
  1157. hr = InitDeviceProperties(pWiasContext);
  1158. if (FAILED(hr))
  1159. {
  1160. wiauDbgError("drvInitItemProperties", "InitDeviceProperties failed");
  1161. goto cleanup;
  1162. }
  1163. }
  1164. else
  1165. {
  1166. hr = InitItemProperties(pWiasContext);
  1167. if (FAILED(hr))
  1168. {
  1169. wiauDbgError("drvInitItemProperties", "InitItemProperties failed");
  1170. goto cleanup;
  1171. }
  1172. }
  1173. cleanup:
  1174. //
  1175. // Update WIA on any changes in camera's state, like 'camera was reset'
  1176. //
  1177. NotifyWiaOnStateChanges();
  1178. return hr;
  1179. }
  1180. //
  1181. // This method locks the device for exclusive use for the caller
  1182. //
  1183. // Input:
  1184. // pWiasContext -- wias context
  1185. // lFlags -- misc flags
  1186. // Output:
  1187. // plDevErrVal -- to return device error
  1188. //
  1189. STDMETHODIMP
  1190. CWiaMiniDriver::drvLockWiaDevice(
  1191. BYTE *pWiasContext,
  1192. LONG lFlags,
  1193. LONG *plDevErrVal
  1194. )
  1195. {
  1196. DBG_FN("CWiaMiniDriver::drvLockWiaDevice");
  1197. *plDevErrVal = DEVERR_OK;
  1198. return S_OK;
  1199. }
  1200. //
  1201. // This method unlocks the device
  1202. //
  1203. // Input:
  1204. // pWiasContext -- wias context
  1205. // lFlags -- misc flags
  1206. // Output:
  1207. // plDevErrVal -- to return device error
  1208. //
  1209. STDMETHODIMP
  1210. CWiaMiniDriver::drvUnLockWiaDevice(
  1211. BYTE *pWiasContext,
  1212. LONG lFlags,
  1213. LONG *plDevErrVal
  1214. )
  1215. {
  1216. DBG_FN("CWiaMiniDriver::drvUnLockWiaDevice");
  1217. *plDevErrVal = DEVERR_OK;
  1218. return S_OK;
  1219. }
  1220. //
  1221. // This method analyizes the given driver item. It is not implemented for cameras.
  1222. //
  1223. // Input:
  1224. // pWiasContext -- wias context
  1225. // lFlags -- misc flags
  1226. // Output:
  1227. // plDevErrVal -- to return device error
  1228. //
  1229. STDMETHODIMP
  1230. CWiaMiniDriver::drvAnalyzeItem(
  1231. BYTE *pWiasContext,
  1232. LONG lFlags,
  1233. LONG *plDevErrVal
  1234. )
  1235. {
  1236. DBG_FN("CWiaMiniDriver::drvAnalyzeItem");
  1237. if (!pWiasContext || !plDevErrVal)
  1238. {
  1239. wiauDbgError("drvAnalyzeItem", "invalid arg");
  1240. return E_INVALIDARG;
  1241. }
  1242. *plDevErrVal = DEVERR_OK;
  1243. return E_NOTIMPL;
  1244. }
  1245. //
  1246. // This method returns the item's available format information. Every WIA
  1247. // minidriver must support WiaImgFmt_BMP and WiaImgFmt_MEMORYBMP. This could
  1248. // be a problem, because this driver can only decode JPEG and TIFF currently.
  1249. // For other formats, we will not advertise BMP formats.
  1250. //
  1251. // Input:
  1252. // pWiasContext -- wias service context
  1253. // lFlags -- misc flags
  1254. // pcelt -- to return how many format info the item has
  1255. // ppwfi -- to hold a pointer to the format info
  1256. // Output:
  1257. // plDevErrVal -- to return device error code
  1258. //
  1259. STDMETHODIMP
  1260. CWiaMiniDriver::drvGetWiaFormatInfo(
  1261. BYTE *pWiasContext,
  1262. LONG lFlags,
  1263. LONG *pcelt,
  1264. WIA_FORMAT_INFO **ppwfi,
  1265. LONG *plDevErrVal
  1266. )
  1267. {
  1268. DBG_FN("CWiaMiniDriver::drvGetWiaFormatInfo");
  1269. HRESULT hr = S_OK;
  1270. if (!pWiasContext || !pcelt || !ppwfi || !plDevErrVal)
  1271. {
  1272. wiauDbgError("drvGetWiaFormatInfo", "invalid arg");
  1273. return E_INVALIDARG;
  1274. }
  1275. *plDevErrVal = DEVERR_OK;
  1276. CPtpMutex cpm(m_hPtpMutex);
  1277. *pcelt = 0;
  1278. *ppwfi = NULL;
  1279. DRVITEM_CONTEXT *pItemCtx = NULL;
  1280. hr = WiasContextToItemContext(pWiasContext, &pItemCtx);
  1281. if (FAILED(hr))
  1282. {
  1283. wiauDbgError("drvGetWiaFormatInfo", "WiasContextToItemContext failed");
  1284. goto cleanup;
  1285. }
  1286. if (!pItemCtx)
  1287. {
  1288. wiauDbgError("drvGetWiaFormatInfo", "item context is null");
  1289. hr = E_FAIL;
  1290. goto cleanup;
  1291. }
  1292. if (!pItemCtx->pFormatInfos)
  1293. {
  1294. //
  1295. // The format info list is not intialized. Do it now.
  1296. //
  1297. LONG ItemType;
  1298. DWORD ui32;
  1299. hr = wiasGetItemType(pWiasContext, &ItemType);
  1300. if (FAILED(hr))
  1301. {
  1302. wiauDbgErrorHr(hr, "drvGetWiaFormatInfo", "wiasGetItemType failed");
  1303. goto cleanup;
  1304. }
  1305. if (ItemType & WiaItemTypeFile)
  1306. {
  1307. //
  1308. // Create the supported format for the item, based on the format stored in the
  1309. // ObjectInfo structure.
  1310. //
  1311. if (!pItemCtx->pObjectInfo)
  1312. {
  1313. wiauDbgError("drvGetWiaFormatInfo", "pObjectInfo not initialized");
  1314. hr = E_FAIL;
  1315. goto cleanup;
  1316. }
  1317. //
  1318. // If the format is JPEG or TIFF based, add the BMP types to the format array,
  1319. // since this driver can convert those to BMP
  1320. //
  1321. WORD FormatCode = pItemCtx->pObjectInfo->m_FormatCode;
  1322. BOOL bAddBmp = (FormatCode == PTP_FORMATCODE_IMAGE_EXIF) ||
  1323. (FormatCode == PTP_FORMATCODE_IMAGE_TIFFEP) ||
  1324. (FormatCode == PTP_FORMATCODE_IMAGE_TIFF) ||
  1325. (FormatCode == PTP_FORMATCODE_IMAGE_JFIF) ||
  1326. (FormatCode == PTP_FORMATCODE_IMAGE_FLASHPIX) ||
  1327. (FormatCode == PTP_FORMATCODE_IMAGE_BMP) ||
  1328. (FormatCode == PTP_FORMATCODE_IMAGE_CIFF) ||
  1329. (FormatCode == PTP_FORMATCODE_IMAGE_GIF) ||
  1330. (FormatCode == PTP_FORMATCODE_IMAGE_JFIF) ||
  1331. (FormatCode == PTP_FORMATCODE_IMAGE_PCD) ||
  1332. (FormatCode == PTP_FORMATCODE_IMAGE_PICT) ||
  1333. (FormatCode == PTP_FORMATCODE_IMAGE_PNG) ||
  1334. (FormatCode == PTP_FORMATCODE_IMAGE_TIFFIT) ||
  1335. (FormatCode == PTP_FORMATCODE_IMAGE_JP2) ||
  1336. (FormatCode == PTP_FORMATCODE_IMAGE_JPX);
  1337. ULONG NumWfi = bAddBmp ? 2 : 1;
  1338. //
  1339. // Allocate two entries for each format, one for file transfer and one for callback
  1340. //
  1341. WIA_FORMAT_INFO *pwfi = new WIA_FORMAT_INFO[2 * NumWfi];
  1342. if (!pwfi)
  1343. {
  1344. wiauDbgError("drvGetWiaFormatInfo", "memory allocation failed");
  1345. hr = E_OUTOFMEMORY;
  1346. goto cleanup;
  1347. }
  1348. FORMAT_INFO *pFormatInfo = FormatCodeToFormatInfo(FormatCode);
  1349. pwfi[0].lTymed = TYMED_FILE;
  1350. pwfi[1].lTymed = TYMED_CALLBACK;
  1351. if(pFormatInfo->FormatGuid) {
  1352. pwfi[0].guidFormatID = *pFormatInfo->FormatGuid;
  1353. pwfi[1].guidFormatID = *pFormatInfo->FormatGuid;
  1354. } else {
  1355. pwfi[0].guidFormatID = WiaImgFmt_UNDEFINED;
  1356. pwfi[1].guidFormatID = WiaImgFmt_UNDEFINED;
  1357. }
  1358. //
  1359. // Add the BMP entries when appropriate
  1360. //
  1361. if (bAddBmp)
  1362. {
  1363. pwfi[2].guidFormatID = WiaImgFmt_BMP;
  1364. pwfi[2].lTymed = TYMED_FILE;
  1365. pwfi[3].guidFormatID = WiaImgFmt_MEMORYBMP;
  1366. pwfi[3].lTymed = TYMED_CALLBACK;
  1367. }
  1368. pItemCtx->NumFormatInfos = 2 * NumWfi;
  1369. pItemCtx->pFormatInfos = pwfi;
  1370. }
  1371. else if ((ItemType & WiaItemTypeFolder) ||
  1372. (ItemType & WiaItemTypeRoot))
  1373. {
  1374. //
  1375. // Folders and the root don't really need format info, but some apps may fail
  1376. // without it. Create a fake list just in case.
  1377. //
  1378. pItemCtx->pFormatInfos = new WIA_FORMAT_INFO[2];
  1379. if (!pItemCtx->pFormatInfos)
  1380. {
  1381. wiauDbgError("drvGetWiaFormatInfo", "memory allocation failed");
  1382. hr = E_OUTOFMEMORY;
  1383. goto cleanup;
  1384. }
  1385. pItemCtx->NumFormatInfos = 2;
  1386. pItemCtx->pFormatInfos[0].lTymed = TYMED_FILE;
  1387. pItemCtx->pFormatInfos[0].guidFormatID = FMT_NOTHING;
  1388. pItemCtx->pFormatInfos[1].lTymed = TYMED_CALLBACK;
  1389. pItemCtx->pFormatInfos[1].guidFormatID = FMT_NOTHING;
  1390. }
  1391. }
  1392. *pcelt = pItemCtx->NumFormatInfos;
  1393. *ppwfi = pItemCtx->pFormatInfos;
  1394. cleanup:
  1395. //
  1396. // Update WIA on any changes in camera's state, like 'camera was reset'
  1397. //
  1398. NotifyWiaOnStateChanges();
  1399. return hr;
  1400. }
  1401. //
  1402. // This method processes pnp events
  1403. //
  1404. // Input:
  1405. // pEventGuid -- the event identifier
  1406. // bstrDeviceId -- the designated device
  1407. // ulReserved -- reserved
  1408. //
  1409. STDMETHODIMP
  1410. CWiaMiniDriver::drvNotifyPnpEvent(
  1411. const GUID *pEventGuid,
  1412. BSTR bstrDeviceId,
  1413. ULONG ulReserved
  1414. )
  1415. {
  1416. return S_OK;
  1417. }
  1418. //
  1419. // This method reads the item properties
  1420. //
  1421. // Input:
  1422. // pWiasContext -- wias context
  1423. // lFlags -- misc flags
  1424. // NumPropSpecs -- number of properties to be read
  1425. // pPropSpecs -- an array of PROPSPEC that specifies
  1426. // what properties should be read
  1427. // plDevErrVal -- to return device error
  1428. //
  1429. STDMETHODIMP
  1430. CWiaMiniDriver::drvReadItemProperties(
  1431. BYTE *pWiasContext,
  1432. LONG lFlags,
  1433. ULONG NumPropSpecs,
  1434. const PROPSPEC *pPropSpecs,
  1435. LONG *plDevErrVal
  1436. )
  1437. {
  1438. DBG_FN("CWiaMiniDriver::drvReadItemProperties");
  1439. HRESULT hr = S_OK;
  1440. if (!pWiasContext || !pPropSpecs || !plDevErrVal)
  1441. {
  1442. wiauDbgError("drvReadItemProperties", "invalid arg");
  1443. return E_INVALIDARG;
  1444. }
  1445. *plDevErrVal = DEVERR_OK;
  1446. CPtpMutex cpm(m_hPtpMutex);
  1447. LONG ItemType = 0;
  1448. hr = wiasGetItemType(pWiasContext, &ItemType);
  1449. if (FAILED(hr))
  1450. {
  1451. wiauDbgError("drvReadItemProperties", "wiasGetItemType failed");
  1452. goto cleanup;
  1453. }
  1454. if (WiaItemTypeRoot & ItemType)
  1455. hr = ReadDeviceProperties(pWiasContext, NumPropSpecs, pPropSpecs);
  1456. else
  1457. hr = ReadItemProperties(pWiasContext, NumPropSpecs, pPropSpecs);
  1458. cleanup:
  1459. //
  1460. // Update WIA on any changes in camera's state, like 'camera was reset'
  1461. //
  1462. NotifyWiaOnStateChanges();
  1463. return hr;
  1464. }
  1465. //
  1466. // This method writes the item properties
  1467. //
  1468. // Input:
  1469. // pWiasContext -- wias context
  1470. // lFlags -- misc flags
  1471. // pmdtc -- mini driver transfer context
  1472. // plDevErrVal -- to return device error
  1473. //
  1474. STDMETHODIMP
  1475. CWiaMiniDriver::drvWriteItemProperties(
  1476. BYTE *pWiasContext,
  1477. LONG lFlags,
  1478. PMINIDRV_TRANSFER_CONTEXT pmdtc,
  1479. LONG *plDevErrVal
  1480. )
  1481. {
  1482. DBG_FN("CWiaMiniDriver::drvWriteItemProperties");
  1483. HRESULT hr = S_OK;
  1484. if (!pWiasContext || !pmdtc || !plDevErrVal)
  1485. {
  1486. wiauDbgError("drvWriteItemProperties", "invalid arg");
  1487. return E_INVALIDARG;
  1488. }
  1489. *plDevErrVal = DEVERR_OK;
  1490. CPtpMutex cpm(m_hPtpMutex);
  1491. LONG ItemType = 0;
  1492. hr = wiasGetItemType(pWiasContext, &ItemType);
  1493. if (FAILED(hr))
  1494. {
  1495. wiauDbgError("drvWriteItemProperties", "wiasGetItemType failed");
  1496. goto cleanup;
  1497. }
  1498. //
  1499. // Only properties to write are on the root
  1500. //
  1501. if (WiaItemTypeRoot & ItemType)
  1502. {
  1503. hr = WriteDeviceProperties(pWiasContext);
  1504. if (FAILED(hr))
  1505. {
  1506. wiauDbgError("drvWriteItemProperties", "WriteDeviceProperties failed");
  1507. goto cleanup;
  1508. }
  1509. }
  1510. cleanup:
  1511. //
  1512. // Update WIA on any changes in camera's state, like 'camera was reset'
  1513. //
  1514. NotifyWiaOnStateChanges();
  1515. return hr;
  1516. }
  1517. //
  1518. // This method validates the item properties
  1519. //
  1520. // Input:
  1521. // pWiasContext -- wias context
  1522. // lFlags -- misc flags
  1523. // NumPropSpecs -- number of properties to be read
  1524. // pPropSpecs -- an array of PROPSPEC that specifies
  1525. // what properties should be read
  1526. // plDevErrVal -- to return device error
  1527. //
  1528. STDMETHODIMP
  1529. CWiaMiniDriver::drvValidateItemProperties(
  1530. BYTE *pWiasContext,
  1531. LONG lFlags,
  1532. ULONG NumPropSpecs,
  1533. const PROPSPEC *pPropSpecs,
  1534. LONG *plDevErrVal
  1535. )
  1536. {
  1537. DBG_FN("CWiaMiniDriver::drvValidateItemProperties");
  1538. HRESULT hr = S_OK;
  1539. if (!pWiasContext || !pPropSpecs || !plDevErrVal)
  1540. {
  1541. wiauDbgError("drvValidateItemProperties", "invalid arg");
  1542. return E_INVALIDARG;
  1543. }
  1544. *plDevErrVal = DEVERR_OK;
  1545. CPtpMutex cpm(m_hPtpMutex);
  1546. LONG ItemType = 0;
  1547. hr = wiasGetItemType(pWiasContext, &ItemType);
  1548. if (FAILED(hr))
  1549. {
  1550. wiauDbgError("drvValidateItemProperties", "wiasGetItemType failed");
  1551. goto cleanup;
  1552. }
  1553. if (WiaItemTypeRoot & ItemType)
  1554. {
  1555. hr = ValidateDeviceProperties(pWiasContext, NumPropSpecs, pPropSpecs);
  1556. if (FAILED(hr))
  1557. {
  1558. wiauDbgError("drvValidateItemProperties", "ValidateDeviceProperties failed");
  1559. goto cleanup;
  1560. }
  1561. }
  1562. else
  1563. {
  1564. hr = ValidateItemProperties(pWiasContext, NumPropSpecs, pPropSpecs, ItemType);
  1565. if (FAILED(hr))
  1566. {
  1567. wiauDbgError("drvValidateItemProperties", "ValidateItemProperties failed");
  1568. goto cleanup;
  1569. }
  1570. }
  1571. cleanup:
  1572. //
  1573. // Update WIA on any changes in camera's state, like 'camera was reset'
  1574. //
  1575. NotifyWiaOnStateChanges();
  1576. return hr;
  1577. }
  1578. //
  1579. // This method acquires the item's data
  1580. //
  1581. // Input:
  1582. // pWiasContext -- wias context
  1583. // lFlags -- misc flags
  1584. // pmdtc -- mini driver transfer context
  1585. // plDevErrVal -- to return device error
  1586. //
  1587. STDMETHODIMP
  1588. CWiaMiniDriver::drvAcquireItemData(
  1589. BYTE *pWiasContext,
  1590. LONG lFlags,
  1591. PMINIDRV_TRANSFER_CONTEXT pmdtc,
  1592. LONG *plDevErrVal
  1593. )
  1594. {
  1595. DBG_FN("CWiaMiniDriver::drvAcquireItemData");
  1596. HRESULT hr = S_OK;
  1597. if (!pWiasContext || !pmdtc || !plDevErrVal)
  1598. {
  1599. wiauDbgError("drvAcquireItemData", "invalid arg");
  1600. return E_INVALIDARG;
  1601. }
  1602. *plDevErrVal = DEVERR_OK;
  1603. CPtpMutex cpm(m_hPtpMutex);
  1604. LONG ItemType = 0;
  1605. hr = wiasGetItemType(pWiasContext, &ItemType);
  1606. if (FAILED(hr))
  1607. {
  1608. wiauDbgError("drvAcquireItemData", "wiasGetItemType failed");
  1609. goto cleanup;
  1610. }
  1611. DRVITEM_CONTEXT *pItemCtx;
  1612. hr = WiasContextToItemContext(pWiasContext, &pItemCtx);
  1613. if (FAILED(hr))
  1614. {
  1615. wiauDbgError("AcquireData", "WiasContextToItemContext failed");
  1616. goto cleanup;
  1617. }
  1618. wiauDbgTrace("drvAcquireItemData", "transferring image with tymed, 0x%08x", pmdtc->tymed);
  1619. //
  1620. // Translate to BMP, if needed. Otherwise just transfer the data.
  1621. //
  1622. if ((IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_BMP) ||
  1623. IsEqualGUID(pmdtc->guidFormatID, WiaImgFmt_MEMORYBMP)) &&
  1624. (pItemCtx->pObjectInfo->m_FormatCode != PTP_FORMATCODE_IMAGE_BMP))
  1625. {
  1626. hr = AcquireDataAndTranslate(pWiasContext, pItemCtx, pmdtc);
  1627. if (FAILED(hr))
  1628. {
  1629. wiauDbgError("drvAcquireItemData", "AcquireDataAndTranslate failed");
  1630. goto cleanup;
  1631. }
  1632. }
  1633. else
  1634. {
  1635. hr = AcquireData(pItemCtx, pmdtc);
  1636. if (FAILED(hr))
  1637. {
  1638. wiauDbgError("drvAcquireItemData", "AcquireData failed");
  1639. goto cleanup;
  1640. }
  1641. }
  1642. cleanup:
  1643. //
  1644. // Update WIA on any changes in camera's state, like 'camera was reset'
  1645. //
  1646. NotifyWiaOnStateChanges();
  1647. return hr;
  1648. }
  1649. //
  1650. // This method returns a description about the given device error code
  1651. //
  1652. // Input:
  1653. // lFlags -- misc flags
  1654. // lDevErrVal -- the designated error code
  1655. // ppDevErrStr -- to receive a string pointer to the description
  1656. // plDevErrVal -- device error code(used to report error if this method
  1657. // need to retreive the string from the device
  1658. //
  1659. STDMETHODIMP
  1660. CWiaMiniDriver::drvGetDeviceErrorStr(
  1661. LONG lFlags,
  1662. LONG lDevErrVal,
  1663. LPOLESTR *ppDevErrStr,
  1664. LONG *plDevErrVal
  1665. )
  1666. {
  1667. DBG_FN("CWiaMiniDriver::drvGetDeviceErrorStr");
  1668. HRESULT hr = S_OK;
  1669. if (!ppDevErrStr || !plDevErrVal)
  1670. {
  1671. wiauDbgError("drvGetDeviceErrorStr", "invalid arg");
  1672. return E_INVALIDARG;
  1673. }
  1674. *plDevErrVal = DEVERR_OK;
  1675. //
  1676. // WIAFIX-10/2/2000-davepar No device-specific errors at this time
  1677. //
  1678. return E_NOTIMPL;
  1679. }
  1680. //
  1681. // This method frees the given driver item context
  1682. //
  1683. // Input:
  1684. // lFlags -- misc flags
  1685. // pItemCtx -- the item context to be freed
  1686. // plDevErrVal -- to return device error
  1687. //
  1688. STDMETHODIMP
  1689. CWiaMiniDriver::drvFreeDrvItemContext(
  1690. LONG lFlags,
  1691. BYTE *pContext,
  1692. LONG *plDevErrVal
  1693. )
  1694. {
  1695. DBG_FN("CWiaMiniDriver::drvFreeDrvItemContext");
  1696. HRESULT hr = S_OK;
  1697. if (!pContext || !plDevErrVal)
  1698. {
  1699. wiauDbgError("drvFreeDrvItemContext", "invalid arg");
  1700. return E_INVALIDARG;
  1701. }
  1702. *plDevErrVal = DEVERR_OK;
  1703. DRVITEM_CONTEXT *pItemCtx = (DRVITEM_CONTEXT *)pContext;
  1704. if (pItemCtx)
  1705. {
  1706. if (pItemCtx->pThumb)
  1707. {
  1708. delete []pItemCtx->pThumb;
  1709. pItemCtx->pThumb = NULL;
  1710. }
  1711. if (pItemCtx->pFormatInfos)
  1712. {
  1713. delete [] pItemCtx->pFormatInfos;
  1714. pItemCtx->pFormatInfos = NULL;
  1715. }
  1716. if (pItemCtx->pObjectInfo)
  1717. {
  1718. delete pItemCtx->pObjectInfo;
  1719. }
  1720. }
  1721. return hr;
  1722. }
  1723. //
  1724. // This function will shutdown the driver
  1725. //
  1726. HRESULT
  1727. CWiaMiniDriver::Shutdown()
  1728. {
  1729. DBG_FN("CWiaMiniDriver::Shutdown");
  1730. HRESULT hr = S_OK;
  1731. //
  1732. // Close the camera
  1733. //
  1734. wiauDbgTrace("Shutdown", "closing connection with camera");
  1735. if (m_pPTPCamera) {
  1736. hr = m_pPTPCamera->Close();
  1737. if (FAILED(hr))
  1738. {
  1739. wiauDbgError("Shutdown", "Close failed");
  1740. }
  1741. }
  1742. //
  1743. // Free data structures
  1744. //
  1745. if (m_pDrvItemRoot)
  1746. {
  1747. m_pDrvItemRoot->UnlinkItemTree(WiaItemTypeDisconnected);
  1748. m_pDrvItemRoot->Release();
  1749. m_pDrvItemRoot = NULL;
  1750. }
  1751. if (m_pPTPCamera)
  1752. {
  1753. delete m_pPTPCamera;
  1754. m_pPTPCamera = NULL;
  1755. }
  1756. m_StorageIds.RemoveAll();
  1757. m_StorageInfos.RemoveAll();
  1758. m_PropDescs.RemoveAll();
  1759. //
  1760. // CWiaMap<ULONG, IWiaDrvItem *> m_HandleItem - we don't need to delete IWiaDrvItem
  1761. // objects here, they are destroyed when items tree is unlinked
  1762. //
  1763. m_HandleItem.RemoveAll();
  1764. m_NumImages = 0;
  1765. if (m_bstrDeviceId)
  1766. {
  1767. SysFreeString(m_bstrDeviceId);
  1768. m_bstrDeviceId = NULL;
  1769. }
  1770. if (m_bstrRootItemFullName)
  1771. {
  1772. SysFreeString(m_bstrRootItemFullName);
  1773. m_bstrRootItemFullName = NULL;
  1774. }
  1775. if (m_TakePictureDoneEvent) {
  1776. CloseHandle(m_TakePictureDoneEvent);
  1777. m_TakePictureDoneEvent = NULL;
  1778. }
  1779. if (m_hPtpMutex) {
  1780. CloseHandle(m_hPtpMutex);
  1781. m_hPtpMutex = NULL;
  1782. }
  1783. m_DcimHandle.RemoveAll();
  1784. //
  1785. // CWiaMap<ULONG, IWiaDrvItem *> m_AncAssocParent - we don't need to delete IWiaDrvItem
  1786. // objects here, they are destroyed when items tree is unlinked
  1787. //
  1788. m_AncAssocParent.RemoveAll();
  1789. return hr;
  1790. }
  1791. //
  1792. // This function asks the camera to take a picture. It also inserts
  1793. // the new picture into the drive item tree.
  1794. //
  1795. // Input:
  1796. // pWiasContext -- wias context
  1797. // lFlags -- misc flags
  1798. // plDevErrVal -- to return device error code
  1799. //
  1800. HRESULT
  1801. CWiaMiniDriver::TakePicture(
  1802. BYTE *pWiasContext,
  1803. IWiaDrvItem **ppNewItem
  1804. )
  1805. {
  1806. DBG_FN("CWiaMiniDriver::TakePicture");
  1807. HRESULT hr = S_OK;
  1808. if (!pWiasContext || !ppNewItem)
  1809. {
  1810. wiauDbgError("TakePicture", "invalid arg");
  1811. return E_INVALIDARG;
  1812. }
  1813. IWiaDrvItem *pDrvItem, *pParentItem;
  1814. DRVITEM_CONTEXT *pItemCtx = NULL;
  1815. *ppNewItem = NULL;
  1816. WORD FormatCode = 0;
  1817. //
  1818. // Kodak DC4800 must have the format code parameter set to zero
  1819. // This hack can be removed only if support of Kodak DC4800 is removed
  1820. //
  1821. if (m_pPTPCamera->GetHackModel() == HACK_MODEL_DC4800)
  1822. {
  1823. FormatCode = 0;
  1824. }
  1825. else
  1826. {
  1827. //
  1828. // Determine which format to capture
  1829. //
  1830. GUID FormatGuid;
  1831. hr = wiasReadPropGuid(pWiasContext, WIA_IPA_FORMAT, &FormatGuid, NULL, TRUE);
  1832. if (FAILED(hr))
  1833. {
  1834. wiauDbgError("TakePicture", "wiasReadPropLong failed");
  1835. return hr;
  1836. }
  1837. FormatCode = FormatGuidToFormatCode(&FormatGuid);
  1838. }
  1839. {
  1840. CPtpMutex cpm(m_hPtpMutex);
  1841. //
  1842. // Reset the event that is waited upon below
  1843. //
  1844. if (!ResetEvent(m_TakePictureDoneEvent))
  1845. {
  1846. hr = HRESULT_FROM_WIN32(::GetLastError());
  1847. wiauDbgErrorHr(hr, "TakePicture", "ResetEvent failed");
  1848. return hr;
  1849. }
  1850. //
  1851. // Clear the list of captured objects
  1852. //
  1853. m_CapturedObjects.RemoveAll();
  1854. //
  1855. // Start the image capture
  1856. //
  1857. hr = m_pPTPCamera->InitiateCapture(PTP_STORAGEID_DEFAULT, FormatCode);
  1858. if (FAILED(hr))
  1859. {
  1860. wiauDbgError("TakePicture", "InitiateCapture failed");
  1861. return hr;
  1862. }
  1863. }
  1864. //
  1865. // Estimate how long the capture may take. Assume 30 seconds for a simple single shot.
  1866. //
  1867. DWORD dwCaptureTimeout = 30000;
  1868. //
  1869. // Check if there is CaptureDelay, and add it to timeout
  1870. //
  1871. int nIndex = m_DeviceInfo.m_SupportedProps.Find(PTP_PROPERTYCODE_CAPTUREDELAY);
  1872. if (nIndex != -1)
  1873. {
  1874. DWORD dwCaptureDelay = m_PropDescs[nIndex].m_lCurrent;
  1875. dwCaptureTimeout += dwCaptureDelay;
  1876. }
  1877. //
  1878. // Check if the camera is in Burst or Timelapse mode
  1879. //
  1880. nIndex = m_DeviceInfo.m_SupportedProps.Find(PTP_PROPERTYCODE_STILLCAPTUREMODE);
  1881. if (nIndex != -1)
  1882. {
  1883. DWORD dwFuncMode = m_PropDescs[nIndex].m_lCurrent;
  1884. if (dwFuncMode == PTP_CAPTUREMODE_BURST)
  1885. {
  1886. //
  1887. // Calculate how much time burst operation may take ((BurstNumber - 1) * BurstInterval)
  1888. //
  1889. DWORD dwBurstNumber = 1;
  1890. DWORD dwBurstInterval = 1000; // assume 1 second per picture, if device does not specify interval
  1891. nIndex = m_DeviceInfo.m_SupportedProps.Find(PTP_PROPERTYCODE_BURSTNUMBER);
  1892. if (nIndex != -1)
  1893. {
  1894. dwBurstNumber = m_PropDescs[nIndex].m_lCurrent;
  1895. }
  1896. nIndex = m_DeviceInfo.m_SupportedProps.Find(PTP_PROPERTYCODE_BURSTINTERVAL);
  1897. if (nIndex != -1)
  1898. {
  1899. dwBurstInterval = m_PropDescs[nIndex].m_lCurrent;
  1900. }
  1901. dwCaptureTimeout += (dwBurstNumber - 1) * dwBurstInterval;
  1902. }
  1903. else if (dwFuncMode == PTP_CAPTUREMODE_TIMELAPSE)
  1904. {
  1905. //
  1906. // Calculate how much time timelapse operation may take ((TimelapseNumber - 1) * TimelapseInterval)
  1907. //
  1908. DWORD dwTimelapseNumber = 1;
  1909. DWORD dwTimelapseInterval = 1000; // assume 1 second per picture, if device does not specify interval
  1910. nIndex = m_DeviceInfo.m_SupportedProps.Find(PTP_PROPERTYCODE_TIMELAPSENUMBER);
  1911. if (nIndex != -1)
  1912. {
  1913. dwTimelapseNumber = m_PropDescs[nIndex].m_lCurrent;
  1914. }
  1915. nIndex = m_DeviceInfo.m_SupportedProps.Find(PTP_PROPERTYCODE_TIMELAPSEINTERVAL);
  1916. if (nIndex != -1)
  1917. {
  1918. dwTimelapseInterval = m_PropDescs[nIndex].m_lCurrent;
  1919. }
  1920. dwCaptureTimeout += (dwTimelapseNumber - 1) * dwTimelapseInterval;
  1921. }
  1922. }
  1923. //
  1924. // Wait for the TakePicture command to be done, indicated by CaptureComplete or StoreFull event.
  1925. //
  1926. wiauDbgTrace("TakePicture", "Calling WaitForSingleObject with %d ms timeout", dwCaptureTimeout);
  1927. if (WaitForSingleObject(m_TakePictureDoneEvent, dwCaptureTimeout) != WAIT_OBJECT_0)
  1928. {
  1929. wiauDbgWarning("TakePicture", "WaitForSingleObject timed out");
  1930. return S_FALSE;
  1931. }
  1932. //
  1933. // Process all objects reported during the capture (there may be many if camera supports burst capture)
  1934. //
  1935. CPtpMutex cpm(m_hPtpMutex); // Grab mutex until the end of the function
  1936. int nCapturedObjects = m_CapturedObjects.GetSize();
  1937. if (nCapturedObjects > 0)
  1938. {
  1939. wiauDbgTrace("TakePicture", "Processing %d objects", nCapturedObjects);
  1940. //
  1941. // Add the first object (in case of burst capture it should folder)
  1942. //
  1943. hr = AddObject(m_CapturedObjects[0], TRUE);
  1944. if (FAILED(hr))
  1945. {
  1946. wiauDbgErrorHr(hr, "TakePicture", "AddObject failed");
  1947. return hr;
  1948. }
  1949. //
  1950. // The last item added to the m_HandleItem map will be the new object
  1951. //
  1952. // In case of burst capture, new images will be stored in a folder (TimeSequence association)
  1953. // Handle of the folder must come first. Return the corresponding WIA item as a result of TakePicture.
  1954. //
  1955. wiauDbgTrace("TakePicture", "new item is 0x%08x", m_HandleItem.GetKeyAt(m_HandleItem.GetSize() - 1));
  1956. *ppNewItem = m_HandleItem.GetValueAt(m_HandleItem.GetSize() - 1);
  1957. //
  1958. // Add the remaining objects
  1959. //
  1960. for (int i = 1; i < nCapturedObjects; i++)
  1961. {
  1962. hr = AddObject(m_CapturedObjects[i], TRUE);
  1963. if (FAILED(hr))
  1964. {
  1965. wiauDbgErrorHr(hr, "TakePicture", "AddObject failed");
  1966. return hr;
  1967. }
  1968. }
  1969. }
  1970. else
  1971. {
  1972. //
  1973. // There are no new objects, storage filled up too quickly
  1974. //
  1975. wiauDbgError("TakePicture", "InitiateCapture did not produce any new objects");
  1976. return HRESULT_FROM_PTP(PTP_RESPONSECODE_STOREFULL);
  1977. }
  1978. return hr;
  1979. }
  1980. //
  1981. // This function add up all the free image space on each storage.
  1982. //
  1983. LONG
  1984. CWiaMiniDriver::GetTotalFreeImageSpace()
  1985. {
  1986. DBG_FN("CWiaMiniDriver::GetTotalFreeImageSpace");
  1987. int count;
  1988. LONG imageSpace = 0;
  1989. for (count = 0; count < m_StorageInfos.GetSize(); count++)
  1990. {
  1991. imageSpace += m_StorageInfos[count].m_FreeSpaceInImages;
  1992. }
  1993. return imageSpace;
  1994. }
  1995. //
  1996. // This function gets the item context from the given wias context and
  1997. // optionally return the target IWiaDrvItem. At least one of ppItemContext
  1998. // and ppDrvItem must be valid.
  1999. //
  2000. // Input:
  2001. // pWiasContext -- wias context obtained from every drvxxxx method
  2002. // ppItemContext -- optional parameter to receive the item context
  2003. // ppDrvItem -- optional parameter to receive the IWiaDrvItem
  2004. //
  2005. HRESULT
  2006. CWiaMiniDriver::WiasContextToItemContext(
  2007. BYTE *pWiasContext,
  2008. DRVITEM_CONTEXT **ppItemContext,
  2009. IWiaDrvItem **ppDrvItem
  2010. )
  2011. {
  2012. DBG_FN("CWiaMiniDriver::WiasContextToItemContext");
  2013. HRESULT hr = S_OK;
  2014. IWiaDrvItem *pWiaDrvItem;
  2015. if (!pWiasContext || (!ppItemContext && !ppDrvItem))
  2016. {
  2017. wiauDbgError("WiasContextToItemContext", "invalid arg");
  2018. return E_INVALIDARG;
  2019. }
  2020. if (ppDrvItem)
  2021. *ppDrvItem = NULL;
  2022. hr = wiasGetDrvItem(pWiasContext, &pWiaDrvItem);
  2023. if (FAILED(hr))
  2024. {
  2025. wiauDbgErrorHr(hr, "WiasContextToItemContext", "wiasGetDrvItem failed");
  2026. return hr;
  2027. }
  2028. if (ppDrvItem)
  2029. *ppDrvItem = pWiaDrvItem;
  2030. if (ppItemContext)
  2031. {
  2032. *ppItemContext = NULL;
  2033. hr = pWiaDrvItem->GetDeviceSpecContext((BYTE **)ppItemContext);
  2034. if (FAILED(hr))
  2035. {
  2036. wiauDbgError("WiasContextToItemContext", "GetDeviceSpecContext failed");
  2037. return hr;
  2038. }
  2039. }
  2040. return hr;
  2041. }
  2042. //
  2043. // This function loads all the object name strings
  2044. //
  2045. HRESULT
  2046. CWiaMiniDriver::LoadStrings()
  2047. {
  2048. HRESULT hr = S_OK;
  2049. if (UnknownString[0] != L'\0')
  2050. {
  2051. //
  2052. // The strings are already loaded
  2053. //
  2054. return hr;
  2055. }
  2056. hr = GetResourceString(IDS_UNKNOWNSTRING, UnknownString, MAX_PATH);
  2057. if (FAILED(hr)) return hr;
  2058. hr = GetResourceString(IDS_FOLDERSTRING, FolderString, MAX_PATH);
  2059. if (FAILED(hr)) return hr;
  2060. hr = GetResourceString(IDS_SCRIPTSTRING, ScriptString, MAX_PATH);
  2061. if (FAILED(hr)) return hr;
  2062. hr = GetResourceString(IDS_EXECSTRING, ExecString, MAX_PATH);
  2063. if (FAILED(hr)) return hr;
  2064. hr = GetResourceString(IDS_TEXTSTRING, TextString, MAX_PATH);
  2065. if (FAILED(hr)) return hr;
  2066. hr = GetResourceString(IDS_HTMLSTRING, HtmlString, MAX_PATH);
  2067. if (FAILED(hr)) return hr;
  2068. hr = GetResourceString(IDS_DPOFSTRING, DpofString, MAX_PATH);
  2069. if (FAILED(hr)) return hr;
  2070. hr = GetResourceString(IDS_AUDIOSTRING, AudioString, MAX_PATH);
  2071. if (FAILED(hr)) return hr;
  2072. hr = GetResourceString(IDS_VIDEOSTRING, VideoString, MAX_PATH);
  2073. if (FAILED(hr)) return hr;
  2074. hr = GetResourceString(IDS_UNKNOWNIMGSTRING, UnknownImgString, MAX_PATH);
  2075. if (FAILED(hr)) return hr;
  2076. hr = GetResourceString(IDS_IMAGESTRING, ImageString, MAX_PATH);
  2077. if (FAILED(hr)) return hr;
  2078. hr = GetResourceString(IDS_ALBUMSTRING, AlbumString, MAX_PATH);
  2079. if (FAILED(hr)) return hr;
  2080. hr = GetResourceString(IDS_BURSTSTRING, BurstString, MAX_PATH);
  2081. if (FAILED(hr)) return hr;
  2082. hr = GetResourceString(IDS_PANORAMASTRING, PanoramaString, MAX_PATH);
  2083. if (FAILED(hr)) return hr;
  2084. hr = GetResourceString(IDS_DEVICECONNECTED, DeviceConnectedString, MAX_PATH);
  2085. if (FAILED(hr)) return hr;
  2086. hr = GetResourceString(IDS_DEVICEDISCONNECTED, DeviceDisconnectedString, MAX_PATH);
  2087. if (FAILED(hr)) return hr;
  2088. hr = GetResourceString(IDS_ITEMCREATED, ItemCreatedString, MAX_PATH);
  2089. if (FAILED(hr)) return hr;
  2090. hr = GetResourceString(IDS_ITEMDELETED, ItemDeletedString, MAX_PATH);
  2091. if (FAILED(hr)) return hr;
  2092. hr = GetResourceString(IDS_TAKEPICTURE, TakePictureString, MAX_PATH);
  2093. if (FAILED(hr)) return hr;
  2094. hr = GetResourceString(IDS_SYNCHRONIZE, SynchronizeString, MAX_PATH);
  2095. if (FAILED(hr)) return hr;
  2096. hr = GetResourceString(IDS_TREEUPDATED, TreeUpdatedString, MAX_PATH);
  2097. if (FAILED(hr)) return hr;
  2098. //
  2099. // Concatenate %ld on the end of each object name string so they can be used in a sprintf statement
  2100. //
  2101. hr = StringCchCatW(UnknownString, ARRAYSIZE(UnknownString), L"%ld");
  2102. if (SUCCEEDED(hr)) hr = StringCchCatW(UnknownString, ARRAYSIZE(UnknownString), L"%ld");
  2103. if (SUCCEEDED(hr)) hr = StringCchCatW(FolderString, ARRAYSIZE(FolderString), L"%ld");
  2104. if (SUCCEEDED(hr)) hr = StringCchCatW(ScriptString, ARRAYSIZE(ScriptString), L"%ld");
  2105. if (SUCCEEDED(hr)) hr = StringCchCatW(ExecString, ARRAYSIZE(ExecString), L"%ld");
  2106. if (SUCCEEDED(hr)) hr = StringCchCatW(TextString, ARRAYSIZE(TextString), L"%ld");
  2107. if (SUCCEEDED(hr)) hr = StringCchCatW(HtmlString, ARRAYSIZE(HtmlString), L"%ld");
  2108. if (SUCCEEDED(hr)) hr = StringCchCatW(DpofString, ARRAYSIZE(DpofString), L"%ld");
  2109. if (SUCCEEDED(hr)) hr = StringCchCatW(AudioString, ARRAYSIZE(AudioString), L"%ld");
  2110. if (SUCCEEDED(hr)) hr = StringCchCatW(VideoString, ARRAYSIZE(VideoString), L"%ld");
  2111. if (SUCCEEDED(hr)) hr = StringCchCatW(UnknownImgString, ARRAYSIZE(UnknownImgString), L"%ld");
  2112. if (SUCCEEDED(hr)) hr = StringCchCatW(ImageString, ARRAYSIZE(ImageString), L"%ld");
  2113. if (SUCCEEDED(hr)) hr = StringCchCatW(AlbumString, ARRAYSIZE(AlbumString), L"%ld");
  2114. if (SUCCEEDED(hr)) hr = StringCchCatW(BurstString, ARRAYSIZE(BurstString), L"%ld");
  2115. if (SUCCEEDED(hr)) hr = StringCchCatW(PanoramaString, ARRAYSIZE(PanoramaString), L"%ld");
  2116. return hr;
  2117. }
  2118. //
  2119. // This function retrieves a string from the resource file and returns a Unicode string. The caller
  2120. // is responsible for allocating space for the string before calling this function.
  2121. //
  2122. // Input:
  2123. // lResourceID -- resource id of the string
  2124. // pString -- pointer to receive the string
  2125. // length -- length of the string in characters
  2126. //
  2127. HRESULT
  2128. CWiaMiniDriver::GetResourceString(
  2129. LONG lResourceID,
  2130. WCHAR *pString,
  2131. int length
  2132. )
  2133. {
  2134. HRESULT hr = S_OK;
  2135. #ifdef UNICODE
  2136. if (::LoadString(g_hInst, lResourceID, pString, length) == 0)
  2137. {
  2138. hr = HRESULT_FROM_WIN32(::GetLastError());
  2139. wiauDbgErrorHr(hr, "GetResourceString", "LoadString failed");
  2140. return hr;
  2141. }
  2142. #else
  2143. TCHAR szStringValue[255];
  2144. if (::LoadString(g_hInst,lResourceID,szStringValue,255) == 0)
  2145. {
  2146. hr = HRESULT_FROM_WIN32(::GetLastError());
  2147. wiauDbgErrorHr(hr, "GetResourceString", "LoadString failed");
  2148. return hr;
  2149. }
  2150. //
  2151. // convert szStringValue from char* to unsigned short* (ANSI only)
  2152. //
  2153. MultiByteToWideChar(CP_ACP,
  2154. MB_PRECOMPOSED,
  2155. szStringValue,
  2156. lstrlenA(szStringValue)+1,
  2157. pString,
  2158. sizeof(length));
  2159. #endif
  2160. return hr;
  2161. }
  2162. //
  2163. // To support vendor extension, new registry entries are defined under the
  2164. // DeviceData subkey. These entries are created from the vendor INF
  2165. // during device setup. Sample INF entries:
  2166. //
  2167. // [DeviceData]
  2168. // VendorExtID=0x12345678
  2169. // PropCode="0xD001,0xD002,0xD003"
  2170. // PropCodeD001="0x1C01,Vendor property 1"
  2171. // PropCodeD002="0x1C02,Vendor property 2"
  2172. // PropCodeD003="0x1C03,Vendor property 3"
  2173. // EventCode="0xC001,0xC002"
  2174. // EventCodeC001={191D9AE7-EE8C-443c-B3E8-A3F87E0CF3CC}
  2175. // EventCodeC002={8162F5ED-62B7-42c5-9C2B-B1625AC0DB93}
  2176. //
  2177. // The VendorExtID entry should be the PIMA assigned vendor extension code.
  2178. //
  2179. // The PropCode entry must list all of the vendor extended PropCodes.
  2180. // For each value in PropCode, an entry of the form PropCodeXXXX must be
  2181. // present, where XXXX is the hex value of the prop code (uppercase). The
  2182. // value for that entry is the WIA property ID and description (which does not
  2183. // need to be localized).
  2184. //
  2185. // The EventCode entry work similarly, where each EventCodeXXXX entry lists the event
  2186. // GUID that will be posted when the event occurs.
  2187. //
  2188. const TCHAR REGSTR_DEVICEDATA[] = TEXT("DeviceData");
  2189. const TCHAR REGSTR_VENDORID[] = TEXT("VendorExtID");
  2190. const TCHAR REGSTR_TWODIGITSMILLISECONDS[] = TEXT("TwoDigitsMillisecondsOutput");
  2191. const TCHAR REGSTR_PROPCODE[] = TEXT("PropCode");
  2192. const TCHAR REGSTR_PROPCODE_MASK[] = TEXT("PropCode%04X");
  2193. const TCHAR REGSTR_EVENTCODE[] = TEXT("EventCode");
  2194. const TCHAR REGSTR_EVENTCODE_MASK[] = TEXT("EventCode%04X");
  2195. const TCHAR REGSTR_EVENTS_MASK[] = TEXT("Events\\%s");
  2196. //
  2197. // This function initializes vendor extentions from the provided
  2198. // registry key
  2199. //
  2200. // Input:
  2201. // hkDevParams -- the registry key under which the vendor extentions are defined.
  2202. //
  2203. HRESULT
  2204. CWiaMiniDriver::InitVendorExtentions(HKEY hkDevParams)
  2205. {
  2206. USES_CONVERSION;
  2207. DBG_FN("CWiaMiniDriver::InitVendorExtentions");
  2208. HRESULT hr = S_OK;
  2209. if (!hkDevParams)
  2210. {
  2211. wiauDbgError("InitVendorExtentions", "invalid arg");
  2212. return E_INVALIDARG;
  2213. }
  2214. CPTPRegistry regDevData;
  2215. hr = regDevData.Open(hkDevParams, REGSTR_DEVICEDATA);
  2216. if (FAILED(hr))
  2217. {
  2218. wiauDbgError("InitVendorExtentions", "Open DeviceData failed");
  2219. return hr;
  2220. }
  2221. //
  2222. // Check if this device requires two digits for milliseconds in DATETIME string
  2223. //
  2224. DWORD dwTwoDigitsMs = 0;
  2225. hr = regDevData.GetValueDword(REGSTR_TWODIGITSMILLISECONDS, &dwTwoDigitsMs);
  2226. if (SUCCEEDED(hr) && dwTwoDigitsMs)
  2227. {
  2228. wiauDbgTrace("InitVendorExtensions", "This device requires two digits for milliseconds in DATETIME string");
  2229. m_bTwoDigitsMillisecondsOutput = TRUE;
  2230. }
  2231. //
  2232. // Get the vendor extension ID
  2233. //
  2234. hr = regDevData.GetValueDword(REGSTR_VENDORID, &m_VendorExtId);
  2235. if (FAILED(hr))
  2236. wiauDbgWarning("InitVendorExtentions", "couldn't read vendor extension id");
  2237. wiauDbgTrace("InitVendorExtentions", "vendor extension id = 0x%08x", m_VendorExtId);
  2238. //
  2239. // Get the list of vendor extended property codes
  2240. //
  2241. CArray16 VendorPropCodes;
  2242. hr = regDevData.GetValueCodes(REGSTR_PROPCODE, &VendorPropCodes);
  2243. wiauDbgTrace("InitVendorExtentions", "%d vendor prop codes found", VendorPropCodes.GetSize());
  2244. //
  2245. // For each property code, get it's information, i.e. the WIA prop id and string
  2246. //
  2247. int count = 0;
  2248. TCHAR name[MAX_PATH];
  2249. TCHAR nameFormat[MAX_PATH];
  2250. TCHAR value[MAX_PATH];
  2251. DWORD valueLen = MAX_PATH;
  2252. PROP_INFO *pPropInfo = NULL;
  2253. WCHAR *pPropStr = NULL;
  2254. const cchPropStrBuf = MAX_PATH;
  2255. #ifndef UNICODE
  2256. TCHAR PropStrBuf[cchPropStrBuf];
  2257. #else
  2258. #define PropStrBuf pPropStr
  2259. #endif
  2260. int num;
  2261. if (SUCCEEDED(hr))
  2262. {
  2263. //
  2264. // Read vendor property info.
  2265. // sample key = "PropCodeD001", sample value = "0x00009802,Vendor property 1"
  2266. //
  2267. for (count = 0; count < VendorPropCodes.GetSize(); count++)
  2268. {
  2269. hr = StringCchPrintf(name, ARRAYSIZE(name), REGSTR_PROPCODE_MASK, VendorPropCodes[count]);
  2270. if (FAILED(hr))
  2271. {
  2272. wiauDbgErrorHr(hr, "InitVendorExtensions", "StringCchPrintf failed");
  2273. return hr;
  2274. }
  2275. valueLen = sizeof(value);
  2276. hr = regDevData.GetValueStr(name, value, &valueLen);
  2277. if (FAILED(hr))
  2278. {
  2279. wiauDbgError("InitVendorExtentions", "vendor extended PropCode not found 0x%04x", VendorPropCodes[count]);
  2280. return hr;
  2281. }
  2282. pPropInfo = new PROP_INFO;
  2283. pPropStr = new WCHAR[cchPropStrBuf];
  2284. if (!pPropInfo || !pPropStr)
  2285. {
  2286. wiauDbgError("InitVendorExtentions", "memory allocation failed");
  2287. return E_OUTOFMEMORY;
  2288. }
  2289. pPropInfo->PropName = pPropStr;
  2290. *PropStrBuf = TEXT('\0');
  2291. //
  2292. // Parse property info
  2293. //
  2294. hr = E_FAIL; // assume string is bad
  2295. TCHAR *pTemp = NULL;
  2296. pPropInfo->PropId = _tcstoul(value, &pTemp, 0); // determine number base automatically
  2297. if (pPropInfo->PropId != 0)
  2298. {
  2299. pTemp = _tcschr(value, TEXT(','));
  2300. if (pTemp != NULL && *(pTemp + 1) != TEXT('\0')) // empty property name is bad
  2301. {
  2302. hr = StringCchCopy(PropStrBuf, cchPropStrBuf, pTemp + 1);
  2303. }
  2304. }
  2305. if (FAILED(hr))
  2306. {
  2307. wiauDbgError("InitVendorExtentions", "invalid vendor property format");
  2308. delete pPropInfo;
  2309. delete [] pPropStr;
  2310. return hr;
  2311. }
  2312. #ifndef UNICODE
  2313. wcscpy(pPropStr, A2W(PropStrBuf));
  2314. #endif
  2315. m_VendorPropMap.Add(VendorPropCodes[count], pPropInfo);
  2316. }
  2317. }
  2318. else
  2319. wiauDbgWarning("InitVendorExtentions", "couldn't read vendor prop codes");
  2320. //
  2321. // Get the list of vendor extended event codes
  2322. //
  2323. hr = S_OK;
  2324. CArray16 VendorEventCodes;
  2325. regDevData.GetValueCodes(REGSTR_EVENTCODE, &VendorEventCodes);
  2326. wiauDbgTrace("InitVendorExtentions", "%d vendor event codes found", VendorEventCodes.GetSize());
  2327. int nVendorEvents = VendorEventCodes.GetSize();
  2328. if (nVendorEvents > MAX_VENDOR_EVENTS)
  2329. {
  2330. wiauDbgWarning("InitVendorExtensions", "vendor events limit exceeded, ignoring events over limit");
  2331. nVendorEvents = MAX_VENDOR_EVENTS;
  2332. }
  2333. //
  2334. // For each event code, get it's information, i.e. the WIA event GUID and event name
  2335. //
  2336. for (count = 0; count < nVendorEvents; count++)
  2337. {
  2338. hr = StringCchPrintf(name, ARRAYSIZE(name), REGSTR_EVENTCODE_MASK, VendorEventCodes[count]);
  2339. if (FAILED(hr))
  2340. {
  2341. wiauDbgErrorHr(hr, "InitVendorExtensions", "StringCchPrintf failed");
  2342. return hr;
  2343. }
  2344. valueLen = sizeof(value);
  2345. hr = regDevData.GetValueStr(name, value, &valueLen);
  2346. if (FAILED(hr))
  2347. {
  2348. wiauDbgError("InitVendorExtentions", "vendor extended EventCode not found 0x%04x", VendorEventCodes[count]);
  2349. return hr;
  2350. }
  2351. CVendorEventInfo *pEventInfo = new CVendorEventInfo;
  2352. if (!pEventInfo)
  2353. {
  2354. wiauDbgError("InitVendorExtentions", "memory allocation failed");
  2355. return E_OUTOFMEMORY;
  2356. }
  2357. pEventInfo->pGuid = new GUID;
  2358. if (!pEventInfo->pGuid)
  2359. {
  2360. wiauDbgError("InitVendorExtentions", "memory allocation failed");
  2361. delete pEventInfo;
  2362. pEventInfo = NULL;
  2363. return E_OUTOFMEMORY;
  2364. }
  2365. hr = CLSIDFromString(T2W(value), pEventInfo->pGuid);
  2366. if (FAILED(hr))
  2367. {
  2368. wiauDbgError("InitVendorExtentions", "invalid guid format");
  2369. delete pEventInfo;
  2370. pEventInfo = NULL;
  2371. return hr;
  2372. }
  2373. //
  2374. // Open DevParams\Events\EventCodeXXXX key and read event's name - default value of the key
  2375. //
  2376. TCHAR szEventKey[MAX_PATH] = TEXT("");
  2377. CPTPRegistry regEventKey;
  2378. hr = StringCchPrintf(szEventKey, ARRAYSIZE(szEventKey), REGSTR_EVENTS_MASK, name);
  2379. if (SUCCEEDED(hr))
  2380. {
  2381. hr = regEventKey.Open(hkDevParams, szEventKey);
  2382. if (SUCCEEDED(hr))
  2383. {
  2384. valueLen = sizeof(value);
  2385. hr = regEventKey.GetValueStr(_T(""), value, &valueLen);
  2386. if (SUCCEEDED(hr))
  2387. {
  2388. pEventInfo->EventName = SysAllocString(T2W(value));
  2389. if (pEventInfo->EventName == NULL)
  2390. {
  2391. hr = E_OUTOFMEMORY;
  2392. }
  2393. }
  2394. }
  2395. }
  2396. if (FAILED(hr))
  2397. {
  2398. //
  2399. // if event name is not provided, the event info will not be added to the map
  2400. // just proceed to the next event in VendorEventCodes
  2401. //
  2402. wiauDbgError("InitVendorExtensions", "can't read vendor event name");
  2403. delete pEventInfo;
  2404. pEventInfo = NULL;
  2405. hr = S_OK;
  2406. }
  2407. else
  2408. {
  2409. //
  2410. // Add the EventInfo to the map. Map will be responsible for freeing EventInfo
  2411. //
  2412. m_VendorEventMap.Add(VendorEventCodes[count], pEventInfo);
  2413. }
  2414. }
  2415. return hr;
  2416. }
  2417. //
  2418. // Event callback function
  2419. //
  2420. HRESULT
  2421. EventCallback(
  2422. LPVOID pCallbackParam,
  2423. PPTP_EVENT pEvent
  2424. )
  2425. {
  2426. HRESULT hr = S_OK;
  2427. if (pEvent == NULL)
  2428. {
  2429. hr = CoInitialize(NULL);
  2430. wiauDbgTrace("EventCallback", "CoInitialize called");
  2431. }
  2432. else
  2433. {
  2434. DBG_FN("EventCallback");
  2435. CWiaMiniDriver *pDriver = (CWiaMiniDriver *) pCallbackParam;
  2436. if (pDriver)
  2437. {
  2438. hr = pDriver->EventCallbackDispatch(pEvent);
  2439. if (FAILED(hr))
  2440. {
  2441. wiauDbgError("EventCallback", "ProcessEvent failed");
  2442. return hr;
  2443. }
  2444. }
  2445. }
  2446. return hr;
  2447. }
  2448. //
  2449. // Constructor
  2450. //
  2451. CPtpMutex::CPtpMutex(HANDLE hMutex) :
  2452. m_hMutex(hMutex)
  2453. {
  2454. DWORD ret = 0;
  2455. const DWORD MUTEX_WAIT = 30 * 1000; // 30 seconds
  2456. ret = WaitForSingleObject(hMutex, MUTEX_WAIT);
  2457. if (ret == WAIT_TIMEOUT)
  2458. wiauDbgError("CPtpMutex", "wait for mutex expired");
  2459. else if (ret == WAIT_FAILED)
  2460. wiauDbgError("CPtpMutex", "WaitForSingleObject failed");
  2461. wiauDbgTrace("CPtpMutex", "Entering mutex");
  2462. }
  2463. //
  2464. // Destructor
  2465. //
  2466. CPtpMutex::~CPtpMutex()
  2467. {
  2468. wiauDbgTrace("~CPtpMutex", "Leaving mutex");
  2469. if (!ReleaseMutex(m_hMutex))
  2470. wiauDbgError("~CPtpMutex", "ReleaseMutex failed");
  2471. }
  2472. //
  2473. // Notify WIA server on changes in camera's state, like "camera was reset"
  2474. //
  2475. HRESULT CWiaMiniDriver::NotifyWiaOnStateChanges()
  2476. {
  2477. HRESULT hr = S_OK;
  2478. if (m_pPTPCamera == NULL)
  2479. {
  2480. return E_UNEXPECTED;
  2481. }
  2482. //
  2483. // Check if camera was reset
  2484. //
  2485. PBOOL pbWasReset = m_pPTPCamera->CameraWasReset();
  2486. if (*pbWasReset)
  2487. {
  2488. //
  2489. // Since device was reset, its context is invalid now
  2490. // First, remove all objects
  2491. //
  2492. while (m_StorageIds.GetSize() > 0)
  2493. {
  2494. hr = RemoveStorage(m_StorageIds[0]);
  2495. if (FAILED(hr))
  2496. {
  2497. wiauDbgError("NotifyWiaOnStateChanges", "Failed to remove storage");
  2498. }
  2499. }
  2500. //
  2501. // Unlink tree.
  2502. //
  2503. if (m_pDrvItemRoot)
  2504. {
  2505. hr = m_pDrvItemRoot->UnlinkItemTree(WiaItemTypeDisconnected);
  2506. if (FAILED(hr))
  2507. {
  2508. wiauDbgError("NotifyWiaOnStateChanges", "Failed to unlink tree");
  2509. }
  2510. m_pDrvItemRoot->Release();
  2511. m_pDrvItemRoot = NULL;
  2512. }
  2513. //
  2514. // Invalidate all property values
  2515. //
  2516. m_PropDescs.RemoveAll();
  2517. //
  2518. // Next call to drvInitializeWia should be able to re-initialize camera
  2519. //
  2520. m_OpenApps = 0;
  2521. //
  2522. // Notify WIA service and application that camera needs to be reinitialized
  2523. //
  2524. hr = wiasQueueEvent(m_bstrDeviceId, &WIA_EVENT_TREE_UPDATED, NULL);
  2525. if (FAILED(hr))
  2526. {
  2527. wiauDbgError("NotifyWiaOnStateChanges", "Failed to queue WIA_EVENT_TREE_UPDATED event");
  2528. }
  2529. *pbWasReset = FALSE;
  2530. }
  2531. return hr;
  2532. }