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.

1569 lines
45 KiB

  1. /**************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 2001
  4. *
  5. * TITLE: FSCam.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * DATE: 15 Nov, 2000
  10. *
  11. * DESCRIPTION:
  12. * File System Device object function implementations.
  13. *
  14. ***************************************************************************/
  15. #include "pch.h"
  16. #include "private.h"
  17. #include "gdiplus.h"
  18. #ifdef USE_SHELLAPI
  19. #include "shlguid.h"
  20. #include "shlobj.h"
  21. #endif
  22. using namespace Gdiplus;
  23. // extern FORMAT_INFO *g_FormatInfo;
  24. // extern UINT g_NumFormatInfo;
  25. //
  26. // Constructor
  27. //
  28. FakeCamera::FakeCamera() :
  29. m_NumImages(0),
  30. m_NumItems(0),
  31. m_hFile(NULL),
  32. m_pIWiaLog(NULL),
  33. m_FormatInfo(NULL),
  34. m_NumFormatInfo(0)
  35. {
  36. }
  37. //
  38. // Destructor
  39. //
  40. FakeCamera::~FakeCamera()
  41. {
  42. if( m_pIWiaLog )
  43. m_pIWiaLog->Release();
  44. }
  45. ULONG FakeCamera::GetImageTypeFromFilename(WCHAR *pFilename, UINT *pFormatCode)
  46. {
  47. WCHAR *pExt;
  48. pExt = wcsrchr(pFilename, L'.');
  49. if( pExt )
  50. {
  51. for(UINT i=0; i<m_NumFormatInfo; i++)
  52. {
  53. if( CSTR_EQUAL == CompareString(LOCALE_SYSTEM_DEFAULT,
  54. NORM_IGNORECASE,
  55. pExt+1,
  56. -1,
  57. m_FormatInfo[i].ExtensionString,
  58. -1))
  59. {
  60. *pFormatCode = i;
  61. return (m_FormatInfo[i].ItemType);
  62. }
  63. }
  64. }
  65. *pFormatCode = 0;
  66. return (m_FormatInfo[0].ItemType);
  67. }
  68. HRESULT GetClsidOfEncoder(REFGUID guidFormatID, CLSID *pClsid = 0)
  69. {
  70. UINT nCodecs = -1;
  71. ImageCodecInfo *pCodecs = 0;
  72. HRESULT hr;
  73. if(!pClsid)
  74. {
  75. return S_FALSE;
  76. }
  77. if (nCodecs == -1)
  78. {
  79. UINT cbCodecs;
  80. GetImageEncodersSize(&nCodecs, &cbCodecs);
  81. if (nCodecs)
  82. {
  83. pCodecs = new ImageCodecInfo [cbCodecs];
  84. if (!pCodecs)
  85. {
  86. return E_OUTOFMEMORY;
  87. }
  88. GetImageEncoders(nCodecs, cbCodecs, pCodecs);
  89. }
  90. }
  91. hr = S_FALSE;
  92. for (UINT i = 0; i < nCodecs; ++i)
  93. {
  94. if (pCodecs[i].FormatID == guidFormatID)
  95. {
  96. // *pClsid = pCodecs[i].Clsid;
  97. memcpy((BYTE *)pClsid, (BYTE *)&(pCodecs[i].Clsid), sizeof(CLSID));
  98. hr = S_OK;
  99. }
  100. }
  101. if( pCodecs )
  102. {
  103. delete [] pCodecs;
  104. }
  105. return hr;
  106. }
  107. BOOL IsFormatSupportedByGDIPlus(REFGUID guidFormatID)
  108. {
  109. UINT nCodecs = -1;
  110. ImageCodecInfo *pCodecs = 0;
  111. BOOL bRet=FALSE;
  112. UINT cbCodecs;
  113. GetImageEncodersSize(&nCodecs, &cbCodecs);
  114. if (nCodecs)
  115. {
  116. pCodecs = new ImageCodecInfo [cbCodecs];
  117. GetImageEncoders(nCodecs, cbCodecs, pCodecs);
  118. }
  119. for (UINT i = 0; i < nCodecs; ++i)
  120. {
  121. if (pCodecs[i].FormatID == guidFormatID)
  122. {
  123. bRet=TRUE;
  124. break;
  125. }
  126. }
  127. if( pCodecs )
  128. {
  129. delete [] pCodecs;
  130. }
  131. return bRet;
  132. }
  133. //
  134. // Initializes access to the camera
  135. //
  136. HRESULT FakeCamera::Open(LPWSTR pPortName)
  137. {
  138. StringCbCopyW(m_RootPath, sizeof(m_RootPath), pPortName);
  139. HRESULT hr = S_OK;
  140. DWORD FileAttr = 0;
  141. if (-1 == (FileAttr = GetFileAttributes(m_RootPath)))
  142. {
  143. hr = HRESULT_FROM_WIN32(::GetLastError());
  144. if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
  145. {
  146. hr = S_OK;
  147. if (!CreateDirectory(m_RootPath, NULL))
  148. {
  149. hr = HRESULT_FROM_WIN32(::GetLastError());
  150. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Open, CreateDirectory failed"));
  151. WIAS_LHRESULT(m_pIWiaLog, hr);
  152. return hr;
  153. }
  154. }
  155. else
  156. {
  157. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Open, GetFileAttributes failed %S, 0x%08x", m_RootPath, hr));
  158. WIAS_LHRESULT(m_pIWiaLog, hr);
  159. return hr;
  160. }
  161. }
  162. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL1,("Open, path set to %S", m_RootPath));
  163. return hr;
  164. }
  165. //
  166. // Closes the connection with the camera
  167. //
  168. HRESULT FakeCamera::Close()
  169. {
  170. HRESULT hr = S_OK;
  171. return hr;
  172. }
  173. //
  174. // Returns information about the camera
  175. //
  176. HRESULT FakeCamera::GetDeviceInfo(DEVICE_INFO *pDeviceInfo)
  177. {
  178. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  179. WIALOG_NO_RESOURCE_ID,
  180. WIALOG_LEVEL1,
  181. "FakeCamera::GetDeviceInfo");
  182. HRESULT hr = S_OK;
  183. //
  184. // Build a list of all items available
  185. //
  186. //m_ItemHandles.RemoveAll();
  187. hr = SearchDirEx(&m_ItemHandles, ROOT_ITEM_HANDLE, m_RootPath);
  188. if (FAILED(hr))
  189. {
  190. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetDeviceInfo, SearchDir failed"));
  191. return hr;
  192. }
  193. pDeviceInfo->FirmwareVersion = SysAllocString(L"04.18.65");
  194. // ISSUE-8/4/2000-davepar Put properties into an INI file
  195. pDeviceInfo->PicturesTaken = m_NumImages;
  196. pDeviceInfo->PicturesRemaining = 100 - pDeviceInfo->PicturesTaken;
  197. pDeviceInfo->TotalItems = m_NumItems;
  198. GetLocalTime(&pDeviceInfo->Time);
  199. pDeviceInfo->ExposureMode = EXPOSUREMODE_MANUAL;
  200. pDeviceInfo->ExposureComp = 0;
  201. return hr;
  202. }
  203. //
  204. // Frees the item info structure
  205. //
  206. VOID FakeCamera::FreeDeviceInfo(DEVICE_INFO *pDeviceInfo)
  207. {
  208. if (pDeviceInfo)
  209. {
  210. if (pDeviceInfo->FirmwareVersion)
  211. {
  212. SysFreeString(pDeviceInfo->FirmwareVersion);
  213. pDeviceInfo->FirmwareVersion = NULL;
  214. }
  215. }
  216. }
  217. //
  218. // This function searches a directory on the hard drive for
  219. // items.
  220. //
  221. HRESULT FakeCamera::GetItemList(ITEM_HANDLE *pItemArray)
  222. {
  223. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  224. WIALOG_NO_RESOURCE_ID,
  225. WIALOG_LEVEL1,
  226. "FakeCamera::GetItemList");
  227. HRESULT hr = S_OK;
  228. memcpy(pItemArray, m_ItemHandles.GetData(), sizeof(ITEM_HANDLE) * m_NumItems);
  229. return hr;
  230. }
  231. //
  232. // This function searches a directory on the hard drive for
  233. // items.
  234. //
  235. // ***NOTE:***
  236. // This function assumes that one or more attachments
  237. // associated with an image will be in the same folder
  238. // as the image. So, for example, if an image is found
  239. // in one folder and its attachment is found in a subfolder
  240. // this algorithm will not associate the image with that
  241. // attachment. This is not a serious limitation since
  242. // all cameras store their attachments in the same
  243. // folder as their image.
  244. //
  245. HRESULT FakeCamera::SearchDirEx(ITEM_HANDLE_ARRAY *pItemArray,
  246. ITEM_HANDLE ParentHandle,
  247. LPOLESTR Path)
  248. {
  249. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  250. WIALOG_NO_RESOURCE_ID,
  251. WIALOG_LEVEL1,
  252. "FakeCamera::SearchDirEx");
  253. HRESULT hr = S_OK;
  254. HANDLE hFind = INVALID_HANDLE_VALUE;
  255. WIN32_FIND_DATA FindData;
  256. WCHAR TempStr[MAX_PATH];
  257. FSUSD_FILE_DATA *pFFD_array=NULL;
  258. DWORD dwNumFilesInArray=0;
  259. DWORD dwCurArraySize=0;
  260. //
  261. // Search for everything, except ".", "..", and hidden files, put them in pFFD_array
  262. //
  263. StringCchPrintfW(TempStr, ARRAYSIZE(TempStr), L"%s\\%s", Path, L"*");
  264. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("SearchDirEx, searching directory %S", TempStr));
  265. memset(&FindData, 0, sizeof(FindData));
  266. hFind = FindFirstFile(TempStr, &FindData);
  267. if (hFind == INVALID_HANDLE_VALUE)
  268. {
  269. hr = HRESULT_FROM_WIN32(::GetLastError());
  270. if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
  271. {
  272. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDir, empty directory %S", TempStr));
  273. hr = S_OK;
  274. }
  275. else
  276. {
  277. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDir, FindFirstFile failed"));
  278. WIAS_LHRESULT(m_pIWiaLog, hr);
  279. }
  280. goto Cleanup;
  281. }
  282. pFFD_array = (FSUSD_FILE_DATA *)CoTaskMemAlloc(sizeof(FSUSD_FILE_DATA)*FFD_ALLOCATION_INCREMENT);
  283. if( !pFFD_array )
  284. {
  285. hr = E_OUTOFMEMORY;
  286. goto Cleanup;
  287. }
  288. dwCurArraySize = FFD_ALLOCATION_INCREMENT;
  289. while (hr == S_OK)
  290. {
  291. if( wcscmp(FindData.cFileName, L".") &&
  292. wcscmp(FindData.cFileName, L"..") &&
  293. !(FindData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) )
  294. {
  295. pFFD_array[dwNumFilesInArray].dwFileAttributes = FindData.dwFileAttributes;
  296. pFFD_array[dwNumFilesInArray].ftFileTime = FindData.ftLastWriteTime;
  297. pFFD_array[dwNumFilesInArray].dwFileSize = FindData.nFileSizeLow;
  298. pFFD_array[dwNumFilesInArray].dwProcessed = 0;
  299. StringCchCopy(pFFD_array[dwNumFilesInArray].cFileName, ARRAYSIZE(pFFD_array[dwNumFilesInArray].cFileName), FindData.cFileName);
  300. dwNumFilesInArray++;
  301. if( (dwNumFilesInArray & (FFD_ALLOCATION_INCREMENT-1)) == (FFD_ALLOCATION_INCREMENT-1) )
  302. { // Time to allocate more memory
  303. pFFD_array = (FSUSD_FILE_DATA *)CoTaskMemRealloc(pFFD_array, (sizeof(FSUSD_FILE_DATA)*(dwCurArraySize+FFD_ALLOCATION_INCREMENT)));
  304. if( !pFFD_array )
  305. {
  306. hr = E_OUTOFMEMORY;
  307. goto Cleanup;
  308. }
  309. dwCurArraySize += FFD_ALLOCATION_INCREMENT;
  310. }
  311. }
  312. memset(&FindData, 0, sizeof(FindData));
  313. if (!FindNextFile(hFind, &FindData))
  314. {
  315. hr = HRESULT_FROM_WIN32(::GetLastError());
  316. if (hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_FILES))
  317. {
  318. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDir, FindNextFile failed"));
  319. WIAS_LHRESULT(m_pIWiaLog, hr);
  320. goto Cleanup;
  321. }
  322. }
  323. }
  324. FindClose(hFind);
  325. hFind = INVALID_HANDLE_VALUE;
  326. // Now that all names under current directory are in the array, do analysis on them
  327. // 1. Find JPG images and their attachments
  328. ULONG uImageType;
  329. UINT nFormatCode;
  330. ITEM_HANDLE ImageHandle;
  331. for(DWORD i=0; i<dwNumFilesInArray; i++)
  332. {
  333. if( pFFD_array[i].dwProcessed )
  334. continue;
  335. if( !((pFFD_array[i].dwFileAttributes) & FILE_ATTRIBUTE_DIRECTORY))
  336. {
  337. uImageType = GetImageTypeFromFilename(pFFD_array[i].cFileName, &nFormatCode);
  338. if( nFormatCode > m_NumFormatInfo )
  339. { // Something really weird happened
  340. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("Aborting SearchDirEx, Format index overflow"));
  341. hr = E_FAIL;
  342. goto Cleanup;
  343. }
  344. if( m_FormatInfo[nFormatCode].FormatGuid == WiaImgFmt_JPEG )
  345. {
  346. // Add this item
  347. hr = CreateItemEx(ParentHandle, &(pFFD_array[i]), &ImageHandle, nFormatCode);
  348. if (FAILED(hr))
  349. {
  350. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDirEx, CreateImage failed"));
  351. goto Cleanup;
  352. }
  353. if (!pItemArray->Add(ImageHandle))
  354. {
  355. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDir, Add failed"));
  356. hr = E_OUTOFMEMORY;
  357. goto Cleanup;
  358. }
  359. pFFD_array[i].dwProcessed = 1;
  360. ImageHandle->bHasAttachments = FALSE;
  361. m_NumImages ++;
  362. StringCchPrintfW(TempStr, ARRAYSIZE(TempStr), L"%s\\%s", Path, pFFD_array[i].cFileName);
  363. hr = SearchForAttachments(pItemArray, ImageHandle, TempStr, pFFD_array, dwNumFilesInArray);
  364. if (FAILED(hr))
  365. {
  366. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDir, SearchForAttachments failed"));
  367. goto Cleanup;
  368. }
  369. if (hr == S_OK)
  370. {
  371. ImageHandle->bHasAttachments = TRUE;
  372. }
  373. ImageHandle->bIsFolder = FALSE;
  374. hr = S_OK;
  375. }
  376. }
  377. } // end of JPEG images and attachments
  378. // 2. For other items that are not processed.
  379. for(i=0; i<dwNumFilesInArray; i++)
  380. {
  381. if( pFFD_array[i].dwProcessed )
  382. continue;
  383. if ((pFFD_array[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) // for folder
  384. {
  385. hr = CreateFolderEx(ParentHandle, &(pFFD_array[i]), &ImageHandle);
  386. if (FAILED(hr))
  387. {
  388. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDirEx, CreateFolder failed"));
  389. goto Cleanup;
  390. }
  391. if (!pItemArray->Add(ImageHandle))
  392. {
  393. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDirEx, Add failed"));
  394. hr = E_OUTOFMEMORY;
  395. goto Cleanup;
  396. }
  397. StringCchPrintfW(TempStr, ARRAYSIZE(TempStr), L"%s\\%s", Path, pFFD_array[i].cFileName);
  398. hr = SearchDirEx(pItemArray, ImageHandle, TempStr);
  399. if (FAILED(hr))
  400. {
  401. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDirEx, recursive SearchDir failed"));
  402. goto Cleanup;
  403. }
  404. pFFD_array[i].dwProcessed = 1;
  405. ImageHandle->bHasAttachments = FALSE;
  406. ImageHandle->bIsFolder = TRUE;
  407. }
  408. else
  409. { // for files
  410. uImageType = GetImageTypeFromFilename(pFFD_array[i].cFileName, &nFormatCode);
  411. #ifdef GDIPLUS_CHECK
  412. if( (ITEMTYPE_IMAGE == uImageType) &&
  413. !IsFormatSupportedByGDIPlus(m_FormatInfo[nFormatCode].FormatGuid))
  414. {
  415. uImageType = ITEMTYPE_FILE; // Force to create non-image item
  416. m_FormatInfo[nFormatCode].ItemType = uImageType;
  417. m_FormatInfo[nFormatCode].FormatGuid = WiaImgFmt_UNDEFINED;
  418. }
  419. #endif
  420. hr = CreateItemEx(ParentHandle, &(pFFD_array[i]), &ImageHandle, nFormatCode);
  421. if (FAILED(hr))
  422. {
  423. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDirEx, CreateImage failed"));
  424. goto Cleanup;
  425. }
  426. if (!pItemArray->Add(ImageHandle))
  427. {
  428. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchDirEx, Add failed"));
  429. hr = E_OUTOFMEMORY;
  430. goto Cleanup;
  431. }
  432. pFFD_array[i].dwProcessed = 1;
  433. ImageHandle->bHasAttachments = FALSE;
  434. ImageHandle->bIsFolder = FALSE;
  435. if(ITEMTYPE_IMAGE == uImageType)
  436. {
  437. m_NumImages ++;
  438. }
  439. hr = S_OK;
  440. }
  441. }
  442. hr = S_OK;
  443. Cleanup:
  444. if( hFind != INVALID_HANDLE_VALUE )
  445. FindClose(hFind);
  446. if( pFFD_array )
  447. CoTaskMemFree(pFFD_array);
  448. return hr;
  449. }
  450. //
  451. // Searches for attachments to an image item
  452. //
  453. inline BOOL CompareAttachmentStrings(WCHAR *pParentStr, WCHAR *pStr2)
  454. {
  455. WCHAR *pSlash = wcsrchr(pStr2, L'\\');
  456. WCHAR *pStrTmp;
  457. if( pSlash )
  458. pStrTmp = pSlash+1;
  459. else
  460. pStrTmp = pStr2;
  461. if( wcslen(pParentStr) == 8 && wcscmp(pParentStr+4, L"0000") > 0 && wcscmp(pParentStr+4, L"9999") < 0 )
  462. {
  463. if( wcslen(pStrTmp) < 8 )
  464. return FALSE;
  465. return (CSTR_EQUAL == CompareString( LOCALE_SYSTEM_DEFAULT, 0, pParentStr+4, 4, pStrTmp+4, 4) );
  466. }
  467. else
  468. {
  469. WCHAR pStr22[MAX_PATH];
  470. StringCchCopyW(pStr22, ARRAYSIZE(pStr22), pStrTmp);
  471. WCHAR *pDot = wcsrchr(pStr22, L'.');
  472. if(pDot )
  473. *pDot = L'\0';
  474. return (CSTR_EQUAL == CompareString( LOCALE_SYSTEM_DEFAULT, 0, pParentStr, -1, pStr22, -1) );
  475. }
  476. }
  477. HRESULT FakeCamera::SearchForAttachments(ITEM_HANDLE_ARRAY *pItemArray,
  478. ITEM_HANDLE ParentHandle,
  479. LPOLESTR Path,
  480. FSUSD_FILE_DATA *pFFD_Current,
  481. DWORD dwNumOfFiles)
  482. {
  483. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  484. WIALOG_NO_RESOURCE_ID,
  485. WIALOG_LEVEL1,
  486. "FakeCamera::SearchForAttachments");
  487. HRESULT hr = S_FALSE;
  488. int NumAttachments = 0;
  489. //
  490. // Attachment is defined as any non-image item whose extension is different than the parent but
  491. // the filename is the same except the first 4 letters.
  492. //
  493. WCHAR TempStrParent[MAX_PATH];
  494. WCHAR *pTemp;
  495. pTemp = wcsrchr(Path, L'\\');
  496. if (pTemp)
  497. {
  498. StringCchCopyW(TempStrParent, ARRAYSIZE(TempStrParent), pTemp+1);
  499. }
  500. else
  501. {
  502. StringCchCopyW(TempStrParent, ARRAYSIZE(TempStrParent), Path);
  503. }
  504. //
  505. // Chop the extension
  506. //
  507. WCHAR *pDot = wcsrchr(TempStrParent, L'.');
  508. if (pDot)
  509. {
  510. *(pDot) = L'\0';
  511. }
  512. else
  513. {
  514. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchForAttachments, filename did not contain a dot"));
  515. return E_INVALIDARG;
  516. }
  517. ITEM_HANDLE NonImageHandle;
  518. UINT nFormatCode;
  519. ULONG uImageType;
  520. for(DWORD i=0; i<dwNumOfFiles; i++)
  521. {
  522. if (!(pFFD_Current[i].dwProcessed) && !(pFFD_Current[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  523. {
  524. nFormatCode=0;
  525. uImageType = GetImageTypeFromFilename(pFFD_Current[i].cFileName, &nFormatCode);
  526. if( (uImageType != ITEMTYPE_IMAGE) &&
  527. CompareAttachmentStrings(TempStrParent, pFFD_Current[i].cFileName) )
  528. {
  529. hr = CreateItemEx(ParentHandle, &(pFFD_Current[i]), &NonImageHandle, nFormatCode);
  530. if (FAILED(hr))
  531. {
  532. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchForAttachments, CreateItemEx failed"));
  533. return hr;
  534. }
  535. if (!pItemArray->Add(NonImageHandle))
  536. {
  537. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("SearchForAttachments, Add failed"));
  538. return E_OUTOFMEMORY;
  539. }
  540. pFFD_Current[i].dwProcessed = 1;
  541. NonImageHandle->bIsFolder = FALSE;
  542. NumAttachments++;
  543. }
  544. }
  545. } // end of FOR loop
  546. if( NumAttachments > 0 )
  547. hr = S_OK;
  548. else
  549. hr = S_FALSE;
  550. return hr;
  551. }
  552. HRESULT FakeCamera::CreateFolderEx(ITEM_HANDLE ParentHandle,
  553. FSUSD_FILE_DATA *pFindData,
  554. ITEM_HANDLE *pFolderHandle)
  555. {
  556. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  557. WIALOG_NO_RESOURCE_ID,
  558. WIALOG_LEVEL1,
  559. "FakeCamera::CreateFolder");
  560. HRESULT hr = S_OK;
  561. if (!pFolderHandle)
  562. {
  563. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateFolder, invalid arg"));
  564. return E_INVALIDARG;
  565. }
  566. *pFolderHandle = new ITEM_INFO;
  567. if (!*pFolderHandle)
  568. {
  569. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateFolder, memory allocation failed"));
  570. return E_OUTOFMEMORY;
  571. }
  572. //
  573. // Initialize the ItemInfo structure
  574. //
  575. ITEM_INFO *pItemInfo = *pFolderHandle;
  576. memset(pItemInfo, 0, sizeof(ITEM_INFO));
  577. //
  578. // Fill in the other item information
  579. //
  580. pItemInfo->Parent = ParentHandle;
  581. pItemInfo->pName = SysAllocString(pFindData->cFileName);
  582. memset(&pItemInfo->Time, 0, sizeof(SYSTEMTIME));
  583. FILETIME ftLocalFileTime;
  584. FileTimeToLocalFileTime(&pFindData->ftFileTime, &ftLocalFileTime);
  585. if (!FileTimeToSystemTime(&ftLocalFileTime, &pItemInfo->Time))
  586. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateFolder, couldn't convert file time to system time"));
  587. pItemInfo->Format = 0;
  588. pItemInfo->bReadOnly = pFindData->dwFileAttributes & FILE_ATTRIBUTE_READONLY;
  589. pItemInfo->bCanSetReadOnly = TRUE;
  590. pItemInfo->bIsFolder = TRUE;
  591. m_NumItems++;
  592. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,
  593. ("CreateFolder, created folder %S at 0x%08x under 0x%08x",
  594. pFindData->cFileName, pItemInfo, ParentHandle));
  595. return hr;
  596. }
  597. HRESULT FakeCamera::CreateItemEx(ITEM_HANDLE ParentHandle,
  598. FSUSD_FILE_DATA *pFileData,
  599. ITEM_HANDLE *pItemHandle,
  600. UINT nFormatCode)
  601. {
  602. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  603. WIALOG_NO_RESOURCE_ID,
  604. WIALOG_LEVEL1,
  605. "FakeCamera::CreateNonImage");
  606. HRESULT hr = S_OK;
  607. if (!pItemHandle)
  608. {
  609. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateNonImage, invalid arg"));
  610. return E_INVALIDARG;
  611. }
  612. *pItemHandle = new ITEM_INFO;
  613. if (!*pItemHandle )
  614. {
  615. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateNonImage, memory allocation failed"));
  616. return E_OUTOFMEMORY;
  617. }
  618. //
  619. // The name cannot contain a dot and the name needs to be unique
  620. // wrt the parent image, so replace the dot with an underline character.
  621. //
  622. WCHAR TempStr[MAX_PATH];
  623. StringCchCopyW(TempStr, ARRAYSIZE(TempStr), pFileData->cFileName);
  624. //
  625. // Initialize the ItemInfo structure
  626. //
  627. ITEM_INFO *pItemInfo = *pItemHandle;
  628. memset(pItemInfo, 0, sizeof(ITEM_INFO));
  629. pItemInfo->Format = nFormatCode;
  630. if (nFormatCode) { // if known extension, it will be handled by the format code
  631. WCHAR *pDot = wcsrchr(TempStr, L'.');
  632. if (pDot)
  633. *pDot = L'\0';
  634. }
  635. //
  636. // Fill in the other item information
  637. //
  638. pItemInfo->Parent = ParentHandle;
  639. pItemInfo->pName = SysAllocString(TempStr);
  640. memset(&pItemInfo->Time, 0, sizeof(SYSTEMTIME));
  641. FILETIME ftLocalFileTime;
  642. FileTimeToLocalFileTime(&pFileData->ftFileTime, &ftLocalFileTime);
  643. if (!FileTimeToSystemTime(&ftLocalFileTime, &pItemInfo->Time))
  644. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateNonImage, couldn't convert file time to system time"));
  645. pItemInfo->Size = pFileData->dwFileSize;
  646. pItemInfo->bReadOnly = pFileData->dwFileAttributes & FILE_ATTRIBUTE_READONLY;
  647. pItemInfo->bCanSetReadOnly = TRUE;
  648. pItemInfo->bIsFolder = FALSE;
  649. m_NumItems++;
  650. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,
  651. ("CreateNonImage, created non-image %S at 0x%08x under 0x%08x",
  652. pFileData->cFileName, pItemInfo, ParentHandle));
  653. return hr;
  654. }
  655. //
  656. // Construct the full path name of the item by traversing its parents
  657. //
  658. VOID FakeCamera::ConstructFullName(WCHAR *pFullName, ITEM_INFO *pItemInfo, BOOL bAddExt)
  659. {
  660. if (pItemInfo->Parent)
  661. ConstructFullName(pFullName, pItemInfo->Parent, FALSE);
  662. else
  663. StringCchCopyW(pFullName, MAX_PATH, m_RootPath);
  664. //
  665. // If this item has attachments and we're creating the name for its children,
  666. // don't add its name (it's a repeat of the child's name)
  667. //
  668. WCHAR *pTmp;
  669. if( pItemInfo->Parent && pItemInfo->Parent->bHasAttachments )
  670. {
  671. pTmp = wcsrchr(pFullName, L'\\');
  672. if( pTmp )
  673. {
  674. *pTmp = L'\0';
  675. }
  676. }
  677. StringCchCatW(pFullName, MAX_PATH, L"\\");
  678. StringCchCatW(pFullName, MAX_PATH, pItemInfo->pName);
  679. if (bAddExt)
  680. {
  681. if( pItemInfo->Format > 0 && pItemInfo->Format < (INT)m_NumFormatInfo )
  682. {
  683. StringCchCatW(pFullName, MAX_PATH, L".");
  684. StringCchCatW(pFullName, MAX_PATH, m_FormatInfo[pItemInfo->Format].ExtensionString);
  685. }
  686. }
  687. }
  688. //
  689. // Frees the item info structure
  690. //
  691. VOID FakeCamera::FreeItemInfo(ITEM_INFO *pItemInfo)
  692. {
  693. if (pItemInfo)
  694. {
  695. if (pItemInfo->pName)
  696. {
  697. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("FreeItemInfo, removing %S", pItemInfo->pName));
  698. SysFreeString(pItemInfo->pName);
  699. pItemInfo->pName = NULL;
  700. }
  701. if (!m_ItemHandles.Remove(pItemInfo))
  702. WIAS_LWARNING(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("FreeItemInfo, couldn't remove handle from array"));
  703. if (m_FormatInfo[pItemInfo->Format].ItemType == ITEMTYPE_IMAGE)
  704. {
  705. m_NumImages--;
  706. }
  707. m_NumItems--;
  708. delete pItemInfo;
  709. }
  710. }
  711. //
  712. // Retrieves the thumbnail for an item
  713. //
  714. /*
  715. HRESULT FakeCamera::GetNativeThumbnail(ITEM_HANDLE ItemHandle, int *pThumbSize, BYTE **ppThumb)
  716. {
  717. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  718. WIALOG_NO_RESOURCE_ID,
  719. WIALOG_LEVEL1,
  720. "FakeCamera::GetThumbnail");
  721. HRESULT hr = S_OK;
  722. if (!ppThumb)
  723. {
  724. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, invalid arg"));
  725. return E_INVALIDARG;
  726. }
  727. *ppThumb = NULL;
  728. *pThumbSize = 0;
  729. WCHAR FullName[MAX_PATH];
  730. ConstructFullName(FullName, ItemHandle);
  731. BYTE *pBuffer;
  732. hr = ReadJpegHdr(FullName, &pBuffer);
  733. if (FAILED(hr) || !pBuffer)
  734. {
  735. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, ReadJpegHdr failed"));
  736. return hr;
  737. }
  738. IFD ImageIfd, ThumbIfd;
  739. BOOL bSwap;
  740. hr = ReadExifJpeg(pBuffer, &ImageIfd, &ThumbIfd, &bSwap);
  741. if (FAILED(hr))
  742. {
  743. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, GetExifJpegDimen failed"));
  744. delete []pBuffer;
  745. return hr;
  746. }
  747. LONG ThumbOffset = 0;
  748. for (int count = 0; count < ThumbIfd.Count; count++)
  749. {
  750. if (ThumbIfd.pEntries[count].Tag == TIFF_JPEG_DATA) {
  751. ThumbOffset = ThumbIfd.pEntries[count].Offset;
  752. }
  753. else if (ThumbIfd.pEntries[count].Tag == TIFF_JPEG_LEN) {
  754. *pThumbSize = ThumbIfd.pEntries[count].Offset;
  755. }
  756. }
  757. if (!ThumbOffset || !*pThumbSize)
  758. {
  759. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, thumbnail not found"));
  760. return E_FAIL;
  761. }
  762. *ppThumb = new BYTE[*pThumbSize];
  763. if (!*ppThumb)
  764. {
  765. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, memory allocation failed"));
  766. return E_OUTOFMEMORY;
  767. }
  768. memcpy(*ppThumb, pBuffer + APP1_OFFSET + ThumbOffset, *pThumbSize);
  769. delete []pBuffer;
  770. FreeIfd(&ImageIfd);
  771. FreeIfd(&ThumbIfd);
  772. return hr;
  773. }
  774. */
  775. HRESULT FakeCamera::CreateThumbnail(ITEM_HANDLE ItemHandle,
  776. int *pThumbSize,
  777. BYTE **ppThumb,
  778. BMP_IMAGE_INFO *pBmpImageInfo)
  779. {
  780. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  781. WIALOG_NO_RESOURCE_ID,
  782. WIALOG_LEVEL1,
  783. "FSCamera::GetThumbnail");
  784. HRESULT hr = S_OK;
  785. GpStatus Status = Gdiplus::Ok;
  786. SizeF gdipSize;
  787. BYTE *pTempBuf=NULL;
  788. CImageStream *pOutStream = NULL;
  789. Image *pImage=NULL, *pThumbnail=NULL;
  790. CLSID ClsidBmpEncoder;
  791. INT iBmpHeadSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
  792. ITEM_INFO *pItemInfo=NULL;
  793. if (!ppThumb)
  794. {
  795. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateThumbnail, invalid arg"));
  796. return E_INVALIDARG;
  797. }
  798. *ppThumb = NULL;
  799. *pThumbSize = 0;
  800. if( S_OK != (hr=GetClsidOfEncoder(ImageFormatBMP, &ClsidBmpEncoder)))
  801. {
  802. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateThumbnail, Cannot get Encode"));
  803. hr = E_FAIL;
  804. goto Cleanup;
  805. }
  806. WCHAR FullName[MAX_PATH];
  807. ConstructFullName(FullName, ItemHandle);
  808. pItemInfo = (ITEM_INFO *)ItemHandle;
  809. pImage = new Image(FullName);
  810. if( !pImage || Gdiplus::ImageTypeBitmap != pImage->GetType() )
  811. {
  812. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateThumbnail, Cannot get Full GDI+ Image for %S", FullName));
  813. hr = E_FAIL;
  814. goto Cleanup;
  815. }
  816. // Calculate Thumbnail size
  817. Status = pImage->GetPhysicalDimension(&gdipSize);
  818. if (Status != Gdiplus::Ok)
  819. {
  820. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateThumbnail, Failed in GetPhysicalDimension"));
  821. hr = E_FAIL;
  822. goto Cleanup;
  823. }
  824. if( gdipSize.Width < 1.0 || gdipSize.Height < 1.0 )
  825. {
  826. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateThumbnail, PhysicalDimension abnormal"));
  827. hr = E_FAIL;
  828. goto Cleanup;
  829. }
  830. pItemInfo->Width = (LONG)gdipSize.Width;
  831. pItemInfo->Height = (LONG)gdipSize.Height;
  832. PixelFormat PixFmt = pImage->GetPixelFormat();
  833. pItemInfo->Depth = (PixFmt & 0xFFFF) >> 8; // Cannot assume image is always 24bits/pixel
  834. if( (pItemInfo->Depth) < 24 )
  835. pItemInfo->Depth = 24;
  836. pItemInfo->BitsPerChannel = 8;
  837. pItemInfo->Channels = (pItemInfo->Depth)/(pItemInfo->BitsPerChannel);
  838. if( gdipSize.Width > gdipSize.Height )
  839. {
  840. pBmpImageInfo->Width = 120;
  841. pBmpImageInfo->Height = (INT)(gdipSize.Height*120.0/gdipSize.Width);
  842. pBmpImageInfo->Height = (pBmpImageInfo->Height + 0x3) & (~0x3);
  843. }
  844. else
  845. {
  846. pBmpImageInfo->Height = 120;
  847. pBmpImageInfo->Width = (INT)(gdipSize.Width*120.0/gdipSize.Height);
  848. pBmpImageInfo->Width = (pBmpImageInfo->Width + 0x3 ) & (~0x3);
  849. }
  850. pThumbnail = pImage->GetThumbnailImage(pBmpImageInfo->Width,pBmpImageInfo->Height);
  851. if( !pThumbnail || Gdiplus::ImageTypeBitmap != pThumbnail->GetType() )
  852. {
  853. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, Cannot get Thumbnail GDI+ Image"));
  854. hr = E_FAIL;
  855. goto Cleanup;
  856. }
  857. if( pImage )
  858. {
  859. delete pImage;
  860. pImage=NULL;
  861. }
  862. #if 0
  863. pThumbnail->Save(L"C:\\thumbdmp.bmp", &ClsidBmpEncoder, NULL);
  864. #endif
  865. //
  866. // Ask GDI+ for the image dimensions, and fill in the
  867. // passed structure
  868. //
  869. Status = pThumbnail->GetPhysicalDimension(&gdipSize);
  870. if (Status != Gdiplus::Ok)
  871. {
  872. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, Failed in GetPhysicalDimension"));
  873. hr = E_FAIL;
  874. goto Cleanup;
  875. }
  876. pBmpImageInfo->Width = (INT) gdipSize.Width;
  877. pBmpImageInfo->Height = (INT) gdipSize.Height;
  878. pBmpImageInfo->ByteWidth = (pBmpImageInfo->Width) << 2;
  879. pBmpImageInfo->Size = pBmpImageInfo->ByteWidth * pBmpImageInfo->Height;
  880. WIAS_LTRACE(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,WIALOG_LEVEL2,("GetThumbnail, W=%d H=%d", pBmpImageInfo->Width, pBmpImageInfo->Height));
  881. if (pBmpImageInfo->Size == 0)
  882. {
  883. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, Thumbnail size is zero"));
  884. hr = E_FAIL;
  885. goto Cleanup;
  886. }
  887. //
  888. // See if the caller passed in a destination buffer, and make sure
  889. // it is big enough.
  890. //
  891. if (*ppThumb) {
  892. if (*pThumbSize < pBmpImageInfo->Size) {
  893. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetThumbnail, Input Buffer too small"));
  894. hr = E_INVALIDARG;
  895. goto Cleanup;
  896. }
  897. }
  898. //
  899. // Otherwise allocate memory for a buffer
  900. //
  901. else
  902. {
  903. pTempBuf = new BYTE[pBmpImageInfo->Size];
  904. if (!pTempBuf)
  905. {
  906. hr = E_OUTOFMEMORY;
  907. goto Cleanup;
  908. }
  909. *ppThumb = pTempBuf;
  910. }
  911. //
  912. // Create output IStream
  913. //
  914. pOutStream = new CImageStream;
  915. if (!pOutStream) {
  916. hr = E_OUTOFMEMORY;
  917. goto Cleanup;
  918. }
  919. hr = pOutStream->SetBuffer(*ppThumb, pBmpImageInfo->Size, SKIP_BOTHHDR);
  920. if (FAILED(hr)) {
  921. goto Cleanup;
  922. }
  923. //
  924. // Write the Image to the output IStream in BMP format
  925. //
  926. pThumbnail->Save(pOutStream, &ClsidBmpEncoder, NULL);
  927. // pack
  928. DWORD i, k;
  929. for(k=0, i=0; k<(DWORD)(pBmpImageInfo->Size); k+=4, i+=3)
  930. {
  931. (*ppThumb)[i] = (*ppThumb)[k];
  932. (*ppThumb)[i+1] = (*ppThumb)[k+1];
  933. (*ppThumb)[i+2] = (*ppThumb)[k+2];
  934. }
  935. *pThumbSize = ((pBmpImageInfo->Size)>>2)*3;
  936. pBmpImageInfo->Size = *pThumbSize;
  937. Cleanup:
  938. if (FAILED(hr)) {
  939. if (pTempBuf) {
  940. delete []pTempBuf;
  941. pTempBuf = NULL;
  942. *ppThumb = NULL;
  943. *pThumbSize = 0;
  944. }
  945. }
  946. if (pOutStream)
  947. {
  948. pOutStream->Release();
  949. }
  950. if( pImage )
  951. {
  952. delete pImage;
  953. }
  954. if( pThumbnail )
  955. {
  956. delete pThumbnail;
  957. }
  958. return hr;
  959. }
  960. PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp)
  961. {
  962. BITMAP bmp;
  963. PBITMAPINFO pbmi;
  964. WORD cClrBits;
  965. // Retrieve the bitmap's color format, width, and height.
  966. if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
  967. {
  968. return NULL;
  969. }
  970. // Convert the color format to a count of bits.
  971. cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
  972. if (cClrBits == 1)
  973. cClrBits = 1;
  974. else if (cClrBits <= 4)
  975. cClrBits = 4;
  976. else if (cClrBits <= 8)
  977. cClrBits = 8;
  978. else if (cClrBits <= 16)
  979. cClrBits = 16;
  980. else if (cClrBits <= 24)
  981. cClrBits = 24;
  982. else cClrBits = 32;
  983. // Allocate memory for the BITMAPINFO structure. (This structure
  984. // contains a BITMAPINFOHEADER structure and an array of RGBQUAD
  985. // data structures.)
  986. if (cClrBits != 24)
  987. pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
  988. sizeof(BITMAPINFOHEADER) +
  989. sizeof(RGBQUAD) * (1<< cClrBits));
  990. // There is no RGBQUAD array for the 24-bit-per-pixel format.
  991. else
  992. pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
  993. sizeof(BITMAPINFOHEADER));
  994. if( !pbmi )
  995. return NULL;
  996. // Initialize the fields in the BITMAPINFO structure.
  997. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  998. pbmi->bmiHeader.biWidth = bmp.bmWidth;
  999. pbmi->bmiHeader.biHeight = bmp.bmHeight;
  1000. pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
  1001. pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
  1002. if (cClrBits < 24)
  1003. pbmi->bmiHeader.biClrUsed = (1<<cClrBits);
  1004. // If the bitmap is not compressed, set the BI_RGB flag.
  1005. pbmi->bmiHeader.biCompression = BI_RGB;
  1006. // Compute the number of bytes in the array of color
  1007. // indices and store the result in biSizeImage.
  1008. // For Windows NT/2000, the width must be DWORD aligned unless
  1009. // the bitmap is RLE compressed. This example shows this.
  1010. // For Windows 95/98, the width must be WORD aligned unless the
  1011. // bitmap is RLE compressed.
  1012. pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
  1013. * pbmi->bmiHeader.biHeight;
  1014. // Set biClrImportant to 0, indicating that all of the
  1015. // device colors are important.
  1016. pbmi->bmiHeader.biClrImportant = 0;
  1017. return pbmi;
  1018. }
  1019. HRESULT FakeCamera::CreateVideoThumbnail(ITEM_HANDLE ItemHandle,
  1020. int *pThumbSize,
  1021. BYTE **ppThumb,
  1022. BMP_IMAGE_INFO *pBmpImageInfo)
  1023. {
  1024. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  1025. WIALOG_NO_RESOURCE_ID,
  1026. WIALOG_LEVEL1,
  1027. "FSCamera::CreateVideoThumbnail");
  1028. HRESULT hr = S_OK;
  1029. HBITMAP hBmp=NULL;
  1030. PBITMAPINFO pBMI=NULL;
  1031. BYTE *pTempBuf=NULL;
  1032. #ifdef USE_SHELLAPI
  1033. IShellFolder *pDesktop=NULL;
  1034. IShellFolder *pFolder=NULL;
  1035. ITEMIDLIST *pidlFolder=NULL;
  1036. ITEMIDLIST *pidlFile=NULL;
  1037. IExtractImage *pExtract=NULL;
  1038. SIZE rgSize;
  1039. WCHAR *wcsTmp, wcTemp;
  1040. DWORD dwPriority, dwFlags;
  1041. if (!ppThumb || !pThumbSize || !pBmpImageInfo)
  1042. {
  1043. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, invalid arg"));
  1044. return E_INVALIDARG;
  1045. }
  1046. *ppThumb = NULL;
  1047. *pThumbSize = 0;
  1048. WCHAR FullName[MAX_PATH];
  1049. ConstructFullName(FullName, ItemHandle);
  1050. // Calculate Thumbnail size, BUGBUG
  1051. rgSize.cx = 120;
  1052. rgSize.cy = 90;
  1053. // Get thumbnail using Shell APIs
  1054. hr = SHGetDesktopFolder(&pDesktop);
  1055. if( S_OK != hr || !pDesktop )
  1056. {
  1057. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot open Desktop"));
  1058. goto Cleanup;
  1059. }
  1060. wcsTmp = wcsrchr(FullName, L'\\');
  1061. if( wcsTmp )
  1062. {
  1063. // wcTemp = *(wcsTmp+1);
  1064. *(wcsTmp) = NULL;
  1065. }
  1066. else
  1067. {
  1068. hr = E_INVALIDARG;
  1069. goto Cleanup;
  1070. }
  1071. hr = pDesktop->ParseDisplayName(NULL, NULL, FullName, NULL, &pidlFolder, NULL);
  1072. if( S_OK != hr || !pidlFolder )
  1073. {
  1074. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot open IDL Folder=%S", FullName));
  1075. goto Cleanup;
  1076. }
  1077. hr = pDesktop->BindToObject(pidlFolder, NULL, IID_IShellFolder, (LPVOID *)&pFolder);
  1078. if( S_OK != hr || !pFolder )
  1079. {
  1080. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot bind to Folder=%S", FullName));
  1081. goto Cleanup;
  1082. }
  1083. // *(wcsTmp+1) = wcTemp; // restore the char
  1084. hr = pFolder->ParseDisplayName(NULL, NULL, wcsTmp+1, NULL, &pidlFile, NULL);
  1085. if( S_OK != hr || !pidlFile )
  1086. {
  1087. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot open IDL File=%S", wcsTmp+1));
  1088. goto Cleanup;
  1089. }
  1090. hr = pFolder->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST *)&pidlFile, IID_IExtractImage, NULL, (LPVOID *)&pExtract);
  1091. if( S_OK != hr || !pExtract )
  1092. {
  1093. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot get extract pointer=%S, hr=0x%x", wcsTmp+1, hr));
  1094. goto Cleanup;
  1095. }
  1096. dwFlags = 0;
  1097. dwPriority=0;
  1098. hr = pExtract->GetLocation(FullName, MAX_PATH, &dwPriority, &rgSize, 0, &dwFlags);
  1099. if( S_OK != hr )
  1100. {
  1101. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Failed in GetLocation"));
  1102. goto Cleanup;
  1103. }
  1104. hr = pExtract->Extract(&hBmp);
  1105. #else
  1106. hBmp = (HBITMAP)LoadImage(g_hInst, MAKEINTRESOURCE(IDB_BITMAP_VIDEO), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
  1107. if( !hBmp )
  1108. {
  1109. hr = HRESULT_FROM_WIN32(::GetLastError());
  1110. }
  1111. #endif // end of if use ShellAPI
  1112. if( S_OK != hr || !hBmp )
  1113. {
  1114. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot extract Image hr=0x%x", hr));
  1115. goto Cleanup;
  1116. }
  1117. pBMI = CreateBitmapInfoStruct(hBmp);
  1118. if( !pBMI )
  1119. {
  1120. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Cannot create BitmapInfoStruct"));
  1121. goto Cleanup;
  1122. }
  1123. pBmpImageInfo->Width = pBMI->bmiHeader.biWidth;
  1124. pBmpImageInfo->Height = pBMI->bmiHeader.biHeight;
  1125. pBmpImageInfo->ByteWidth = ((pBMI->bmiHeader.biWidth * 24 + 31 ) & ~31 ) >> 3;
  1126. pBmpImageInfo->Size = pBMI->bmiHeader.biWidth * pBmpImageInfo->Height * 3;
  1127. //
  1128. // See if the caller passed in a destination buffer, and make sure
  1129. // it is big enough.
  1130. //
  1131. if (*ppThumb) {
  1132. if (*pThumbSize < pBmpImageInfo->Size) {
  1133. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Input Buffer too small"));
  1134. hr = E_INVALIDARG;
  1135. goto Cleanup;
  1136. }
  1137. }
  1138. //
  1139. // Otherwise allocate memory for a buffer
  1140. //
  1141. else
  1142. {
  1143. pTempBuf = new BYTE[(pBmpImageInfo->ByteWidth)*(pBmpImageInfo->Height)];
  1144. if (!pTempBuf)
  1145. {
  1146. hr = E_OUTOFMEMORY;
  1147. goto Cleanup;
  1148. }
  1149. *ppThumb = pTempBuf;
  1150. *pThumbSize = pBmpImageInfo->Size;
  1151. }
  1152. //
  1153. // Create output buffer
  1154. //
  1155. if (!GetDIBits(GetDC(NULL), hBmp, 0, (WORD)pBMI->bmiHeader.biHeight, *ppThumb, pBMI, DIB_RGB_COLORS))
  1156. {
  1157. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("CreateVideoThumbnail, Failed in GetDIBits"));
  1158. hr = E_FAIL;
  1159. goto Cleanup;
  1160. }
  1161. #if 0
  1162. // pack
  1163. DWORD i, k;
  1164. for(k=0, i=0; k<(DWORD)(pBmpImageInfo->Size); k+=4, i+=3)
  1165. {
  1166. pTempBuf[i] = pTempBuf[k];
  1167. pTempBuf[i+1] = pTempBuf[k+1];
  1168. pTempBuf[i+2] = pTempBuf[k+2];
  1169. }
  1170. #endif
  1171. Cleanup:
  1172. if (FAILED(hr)) {
  1173. if (pTempBuf) {
  1174. delete []pTempBuf;
  1175. pTempBuf = NULL;
  1176. *ppThumb = NULL;
  1177. *pThumbSize = 0;
  1178. }
  1179. }
  1180. if (pBMI)
  1181. LocalFree(pBMI);
  1182. #ifdef USE_SHELLAPI
  1183. if( pDesktop )
  1184. pDesktop->Release();
  1185. if( pFolder )
  1186. pFolder->Release();
  1187. if( pidlFolder )
  1188. CoTaskMemFree(pidlFolder);
  1189. if( pidlFile )
  1190. CoTaskMemFree(pidlFile);
  1191. if( pExtract )
  1192. pExtract->Release();
  1193. #endif
  1194. if( hBmp )
  1195. {
  1196. DeleteObject(hBmp);
  1197. }
  1198. return hr;
  1199. }
  1200. VOID FakeCamera::FreeThumbnail(BYTE *pThumb)
  1201. {
  1202. if (pThumb)
  1203. {
  1204. delete []pThumb;
  1205. pThumb = NULL;
  1206. }
  1207. }
  1208. //
  1209. // Retrieves the data for an item
  1210. //
  1211. HRESULT FakeCamera::GetItemData(ITEM_HANDLE ItemHandle, LONG lState,
  1212. BYTE *pBuf, DWORD lLength)
  1213. {
  1214. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  1215. WIALOG_NO_RESOURCE_ID,
  1216. WIALOG_LEVEL1,
  1217. "FakeCamera::GetItemData");
  1218. HRESULT hr = S_OK;
  1219. if (lState & STATE_FIRST)
  1220. {
  1221. if (m_hFile != NULL)
  1222. {
  1223. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetItemData, file handle is already open"));
  1224. return E_FAIL;
  1225. }
  1226. WCHAR FullName[MAX_PATH];
  1227. ConstructFullName(FullName, ItemHandle);
  1228. m_hFile = CreateFile(FullName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  1229. if (m_hFile == INVALID_HANDLE_VALUE)
  1230. {
  1231. hr = HRESULT_FROM_WIN32(::GetLastError());
  1232. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetItemData, CreateFile failed %S", FullName));
  1233. WIAS_LHRESULT(m_pIWiaLog, hr);
  1234. return hr;
  1235. }
  1236. }
  1237. if (!(lState & STATE_CANCEL))
  1238. {
  1239. DWORD Received = 0;
  1240. if (!ReadFile(m_hFile, pBuf, lLength, &Received, NULL))
  1241. {
  1242. hr = HRESULT_FROM_WIN32(::GetLastError());
  1243. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetItemData, ReadFile failed"));
  1244. WIAS_LHRESULT(m_pIWiaLog, hr);
  1245. return hr;
  1246. }
  1247. if (lLength != Received)
  1248. {
  1249. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("GetItemData, incorrect amount read %d", Received));
  1250. return E_FAIL;
  1251. }
  1252. Sleep(100);
  1253. }
  1254. if (lState & (STATE_LAST | STATE_CANCEL))
  1255. {
  1256. CloseHandle(m_hFile);
  1257. m_hFile = NULL;
  1258. }
  1259. return hr;
  1260. }
  1261. //
  1262. // Deletes an item
  1263. //
  1264. HRESULT FakeCamera::DeleteItem(ITEM_HANDLE ItemHandle)
  1265. {
  1266. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  1267. WIALOG_NO_RESOURCE_ID,
  1268. WIALOG_LEVEL1,
  1269. "FakeCamera::DeleteItem");
  1270. HRESULT hr = S_OK;
  1271. DWORD dwErr = 0;
  1272. WCHAR FullName[MAX_PATH];
  1273. ConstructFullName(FullName, ItemHandle);
  1274. if( FILE_ATTRIBUTE_DIRECTORY & GetFileAttributes(FullName) )
  1275. {
  1276. dwErr = RemoveDirectory(FullName);
  1277. } else {
  1278. dwErr = DeleteFile(FullName);
  1279. }
  1280. if (!dwErr )
  1281. {
  1282. hr = HRESULT_FROM_WIN32(::GetLastError());
  1283. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("DeleteItem, DeleteFile failed %S", FullName));
  1284. WIAS_LHRESULT(m_pIWiaLog, hr);
  1285. }
  1286. return hr;
  1287. }
  1288. //
  1289. // Captures a new image
  1290. //
  1291. HRESULT FakeCamera::TakePicture(ITEM_HANDLE *pItemHandle)
  1292. {
  1293. CWiaLogProc WIAS_LOGPROC(m_pIWiaLog,
  1294. WIALOG_NO_RESOURCE_ID,
  1295. WIALOG_LEVEL1,
  1296. "FakeCamera::TakePicture");
  1297. HRESULT hr = S_OK;
  1298. if (!pItemHandle)
  1299. {
  1300. WIAS_LERROR(m_pIWiaLog,WIALOG_NO_RESOURCE_ID,("TakePicture, invalid arg"));
  1301. return E_INVALIDARG;
  1302. }
  1303. return hr;
  1304. }
  1305. //
  1306. // See if the camera is active
  1307. //
  1308. HRESULT
  1309. FakeCamera::Status()
  1310. {
  1311. HRESULT hr = S_OK;
  1312. //
  1313. // This sample device is always active, but your driver should contact the
  1314. // device and return S_FALSE if it's not ready.
  1315. //
  1316. // if (NotReady)
  1317. // return S_FALSE;
  1318. return hr;
  1319. }
  1320. //
  1321. // Reset the camera
  1322. //
  1323. HRESULT FakeCamera::Reset()
  1324. {
  1325. HRESULT hr = S_OK;
  1326. return hr;
  1327. }