Source code of Windows XP (NT5)
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.

2185 lines
79 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 1998
  4. *
  5. * TITLE: ACQMGRCW.CPP
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ShaunIv
  10. *
  11. * DATE: 9/27/1999
  12. *
  13. * DESCRIPTION:
  14. *
  15. *******************************************************************************/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #include <windows.h>
  19. #include <simcrack.h>
  20. #include <commctrl.h>
  21. #include <wiatextc.h>
  22. #include <pviewids.h>
  23. #include <commctrl.h>
  24. #include "resource.h"
  25. #include "acqmgrcw.h"
  26. #include "wia.h"
  27. #include "wiadevdp.h"
  28. #include "evntparm.h"
  29. #include "itranhlp.h"
  30. #include "bkthread.h"
  31. #include "wiaitem.h"
  32. #include "errors.h"
  33. #include "isuppfmt.h"
  34. #include "uiexthlp.h"
  35. #include "gphelper.h"
  36. #include "svselfil.h"
  37. #include "gwiaevnt.h"
  38. #include "modlock.h"
  39. #include "comfin.h"
  40. #include "comprog.h"
  41. #include "upquery.h"
  42. #include "comdelp.h"
  43. #include "devprop.h"
  44. #include "mboxex.h"
  45. #include "dumpprop.h"
  46. #include "psutil.h"
  47. #undef TRY_SMALLER_THUMBNAILS
  48. #if defined(TRY_SMALLER_THUMBNAILS)
  49. static const int c_nDefaultThumbnailWidth = 80;
  50. static const int c_nDefaultThumbnailHeight = 80;
  51. static const int c_nMaxThumbnailWidth = 80;
  52. static const int c_nMaxThumbnailHeight = 80;
  53. static const int c_nMinThumbnailWidth = 80;
  54. static const int c_nMinThumbnailHeight = 80;
  55. #else
  56. static const int c_nDefaultThumbnailWidth = 90;
  57. static const int c_nDefaultThumbnailHeight = 90;
  58. static const int c_nMaxThumbnailWidth = 120;
  59. static const int c_nMaxThumbnailHeight = 120;
  60. static const int c_nMinThumbnailWidth = 80;
  61. static const int c_nMinThumbnailHeight = 80;
  62. #endif
  63. //
  64. // Property sheet pages' window class declarations
  65. //
  66. #include "comfirst.h"
  67. #include "camsel.h"
  68. #include "comtrans.h"
  69. #include "scansel.h"
  70. // -------------------------------------------------
  71. // CAcquisitionManagerControllerWindow
  72. // -------------------------------------------------
  73. CAcquisitionManagerControllerWindow::CAcquisitionManagerControllerWindow( HWND hWnd )
  74. : m_hWnd(hWnd),
  75. m_pEventParameters(NULL),
  76. m_DeviceTypeMode(UnknownMode),
  77. m_hWizardIconSmall(NULL),
  78. m_hWizardIconBig(NULL),
  79. m_guidOutputFormat(IID_NULL),
  80. m_bDeletePicturesIfSuccessful(false),
  81. m_nThreadNotificationMessage(RegisterWindowMessage(STR_THREAD_NOTIFICATION_MESSAGE)),
  82. m_nWiaEventMessage(RegisterWindowMessage(STR_WIAEVENT_NOTIFICATION_MESSAGE)),
  83. m_bDisconnected(false),
  84. m_pThreadMessageQueue(NULL),
  85. m_bStampTimeOnSavedFiles(true),
  86. m_bOpenShellAfterDownload(true),
  87. m_bSuppressFirstPage(false),
  88. m_nFailedImagesCount(0),
  89. m_nDestinationPageIndex(-1),
  90. m_nFinishPageIndex(-1),
  91. m_nDeleteProgressPageIndex(-1),
  92. m_nSelectionPageIndex(-1),
  93. m_hWndWizard(NULL),
  94. m_bTakePictureIsSupported(false),
  95. m_nWiaWizardPageCount(0),
  96. m_nUploadWizardPageCount(0),
  97. m_bUploadToWeb(false),
  98. m_cRef(1),
  99. m_nScannerType(ScannerTypeUnknown),
  100. m_OnDisconnect(0),
  101. m_dwLastEnumerationTickCount(0)
  102. {
  103. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::CAcquisitionManagerControllerWindow"));
  104. // This sets up the map that maps thread messages to message handlers, which are declared to be static
  105. // member functions.
  106. static CThreadMessageMap s_MsgMap[] =
  107. {
  108. { TQ_DESTROY, OnThreadDestroy},
  109. { TQ_DOWNLOADIMAGE, OnThreadDownloadImage},
  110. { TQ_DOWNLOADTHUMBNAIL, OnThreadDownloadThumbnail},
  111. { TQ_SCANPREVIEW, OnThreadPreviewScan},
  112. { TQ_DELETEIMAGES, OnThreadDeleteImages},
  113. { 0, NULL}
  114. };
  115. // Assume the default thumbnail size, in case we aren't able to calculate it
  116. m_sizeThumbnails.cx = c_nDefaultThumbnailWidth;
  117. m_sizeThumbnails.cy = c_nDefaultThumbnailHeight;
  118. //
  119. // Read the initial settings
  120. //
  121. CSimpleReg reg( HKEY_CURRENT_USER, REGSTR_PATH_USER_SETTINGS_WIAACMGR, false, KEY_READ );
  122. m_bOpenShellAfterDownload = (reg.Query( REG_STR_OPENSHELL, m_bOpenShellAfterDownload ) != FALSE);
  123. m_bSuppressFirstPage = (reg.Query( REG_STR_SUPRESSFIRSTPAGE, m_bSuppressFirstPage ) != FALSE);
  124. //
  125. // Initialize the background thread queue, which will handle all of our background requests
  126. //
  127. m_pThreadMessageQueue = new CThreadMessageQueue;
  128. if (m_pThreadMessageQueue)
  129. {
  130. //
  131. // Note that CBackgroundThread takes ownership of m_pThreadMessageQueue, and it doesn't have to be deleted in this thread
  132. //
  133. m_hBackgroundThread = CBackgroundThread::Create( m_pThreadMessageQueue, s_MsgMap, m_CancelEvent.Event(), NULL );
  134. }
  135. ZeroMemory( m_PublishWizardPages, sizeof(m_PublishWizardPages) );
  136. }
  137. CAcquisitionManagerControllerWindow::~CAcquisitionManagerControllerWindow(void)
  138. {
  139. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::~CAcquisitionManagerControllerWindow"));
  140. if (m_pEventParameters)
  141. {
  142. if (m_pEventParameters->pWizardSharedMemory)
  143. {
  144. delete m_pEventParameters->pWizardSharedMemory;
  145. }
  146. m_pEventParameters = NULL;
  147. }
  148. }
  149. LRESULT CAcquisitionManagerControllerWindow::OnDestroy( WPARAM, LPARAM )
  150. {
  151. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::OnDestroy"));
  152. //
  153. // Tell the publishing wizard to release us
  154. //
  155. if (m_pPublishingWizard)
  156. {
  157. IUnknown_SetSite( m_pPublishingWizard, NULL );
  158. }
  159. //
  160. // Release the publishing wizard and its data
  161. //
  162. m_pPublishingWizard = NULL;
  163. //
  164. // Stop downloading thumbnails
  165. //
  166. m_EventThumbnailCancel.Signal();
  167. //
  168. // Unpause the background thread
  169. //
  170. m_EventPauseBackgroundThread.Signal();
  171. //
  172. // Tell the background thread to destroy itself
  173. //
  174. m_pThreadMessageQueue->Enqueue( new CThreadMessage(TQ_DESTROY),CThreadMessageQueue::PriorityUrgent);
  175. //
  176. // Issue a cancel io command for this item
  177. //
  178. WiaUiUtil::IssueWiaCancelIO(m_pWiaItemRoot);
  179. //
  180. // Tell other instances we are done before the background thread is finished,
  181. // so we can immediately start again
  182. //
  183. if (m_pEventParameters && m_pEventParameters->pWizardSharedMemory)
  184. {
  185. m_pEventParameters->pWizardSharedMemory->Close();
  186. }
  187. //
  188. // Wait for the thread to exit
  189. //
  190. WiaUiUtil::MsgWaitForSingleObject( m_hBackgroundThread, INFINITE );
  191. CloseHandle( m_hBackgroundThread );
  192. //
  193. // Clean up the icons
  194. //
  195. if (m_hWizardIconSmall)
  196. {
  197. DestroyIcon( m_hWizardIconSmall );
  198. m_hWizardIconSmall = NULL;
  199. }
  200. if (m_hWizardIconBig)
  201. {
  202. DestroyIcon( m_hWizardIconBig );
  203. m_hWizardIconBig = NULL;
  204. }
  205. return 0;
  206. }
  207. BOOL WINAPI CAcquisitionManagerControllerWindow::OnThreadDestroy( CThreadMessage *pMsg )
  208. {
  209. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::OnThreadDestroy"));
  210. // Return false to close the queue
  211. return FALSE;
  212. }
  213. BOOL WINAPI CAcquisitionManagerControllerWindow::OnThreadDownloadImage( CThreadMessage *pMsg )
  214. {
  215. CDownloadImagesThreadMessage *pDownloadImageThreadMessage = dynamic_cast<CDownloadImagesThreadMessage*>(pMsg);
  216. if (pDownloadImageThreadMessage)
  217. {
  218. pDownloadImageThreadMessage->Download();
  219. }
  220. else
  221. {
  222. WIA_ERROR((TEXT("pDownloadImageThreadMessage was NULL")));
  223. }
  224. return TRUE;
  225. }
  226. BOOL WINAPI CAcquisitionManagerControllerWindow::OnThreadDownloadThumbnail( CThreadMessage *pMsg )
  227. {
  228. CDownloadThumbnailsThreadMessage *pDownloadThumnailsThreadMessage = dynamic_cast<CDownloadThumbnailsThreadMessage*>(pMsg);
  229. if (pDownloadThumnailsThreadMessage)
  230. {
  231. pDownloadThumnailsThreadMessage->Download();
  232. }
  233. else
  234. {
  235. WIA_ERROR((TEXT("pDownloadThumnailThreadMessage was NULL")));
  236. }
  237. return TRUE;
  238. }
  239. BOOL WINAPI CAcquisitionManagerControllerWindow::OnThreadPreviewScan( CThreadMessage *pMsg )
  240. {
  241. CPreviewScanThreadMessage *pPreviewScanThreadMessage = dynamic_cast<CPreviewScanThreadMessage*>(pMsg);
  242. if (pPreviewScanThreadMessage)
  243. {
  244. pPreviewScanThreadMessage->Scan();
  245. }
  246. else
  247. {
  248. WIA_ERROR((TEXT("pPreviewScanThreadMessage was NULL")));
  249. }
  250. return TRUE;
  251. }
  252. BOOL WINAPI CAcquisitionManagerControllerWindow::OnThreadDeleteImages( CThreadMessage *pMsg )
  253. {
  254. CDeleteImagesThreadMessage *pDeleteImagesThreadMessage = dynamic_cast<CDeleteImagesThreadMessage*>(pMsg);
  255. if (pDeleteImagesThreadMessage)
  256. {
  257. pDeleteImagesThreadMessage->DeleteImages();
  258. }
  259. else
  260. {
  261. WIA_ERROR((TEXT("pPreviewScanThreadMessage was NULL")));
  262. }
  263. return TRUE;
  264. }
  265. HRESULT CAcquisitionManagerControllerWindow::CreateDevice(void)
  266. {
  267. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::CreateDevice"));
  268. CComPtr<IWiaDevMgr> pWiaDevMgr;
  269. HRESULT hr = CoCreateInstance( CLSID_WiaDevMgr, NULL, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr, (void**)&pWiaDevMgr );
  270. if (SUCCEEDED(hr))
  271. {
  272. bool bRetry = true;
  273. for (DWORD dwRetryCount = 0;dwRetryCount < CREATE_DEVICE_RETRY_MAX_COUNT && bRetry;dwRetryCount++)
  274. {
  275. hr = pWiaDevMgr->CreateDevice( CSimpleBStr(m_pEventParameters->strDeviceID), &m_pWiaItemRoot );
  276. WIA_PRINTHRESULT((hr,TEXT("pWiaDevMgr->CreateDevice returned")));
  277. if (SUCCEEDED(hr))
  278. {
  279. //
  280. // Break out of loop
  281. //
  282. bRetry = false;
  283. //
  284. // Register for events
  285. //
  286. CGenericWiaEventHandler::RegisterForWiaEvent( m_pEventParameters->strDeviceID, WIA_EVENT_DEVICE_DISCONNECTED, &m_pDisconnectEventObject, m_hWnd, m_nWiaEventMessage );
  287. CGenericWiaEventHandler::RegisterForWiaEvent( m_pEventParameters->strDeviceID, WIA_EVENT_ITEM_DELETED, &m_pDeleteItemEventObject, m_hWnd, m_nWiaEventMessage );
  288. CGenericWiaEventHandler::RegisterForWiaEvent( m_pEventParameters->strDeviceID, WIA_EVENT_DEVICE_CONNECTED, &m_pConnectEventObject, m_hWnd, m_nWiaEventMessage );
  289. CGenericWiaEventHandler::RegisterForWiaEvent( m_pEventParameters->strDeviceID, WIA_EVENT_ITEM_CREATED, &m_pCreateItemEventObject, m_hWnd, m_nWiaEventMessage );
  290. }
  291. else if (WIA_ERROR_BUSY == hr)
  292. {
  293. //
  294. // Wait a little while before retrying
  295. //
  296. Sleep(CREATE_DEVICE_RETRY_WAIT);
  297. }
  298. else
  299. {
  300. //
  301. // All other errors are considered fatal
  302. //
  303. bRetry = false;
  304. }
  305. }
  306. }
  307. return hr;
  308. }
  309. void CAcquisitionManagerControllerWindow::GetCookiesOfSelectedImages( CWiaItem *pCurr, CSimpleDynamicArray<DWORD> &Cookies )
  310. {
  311. while (pCurr)
  312. {
  313. GetCookiesOfSelectedImages(pCurr->Children(),Cookies);
  314. if (pCurr->IsDownloadableItemType() && pCurr->SelectedForDownload())
  315. {
  316. Cookies.Append(pCurr->GlobalInterfaceTableCookie());
  317. }
  318. pCurr = pCurr->Next();
  319. }
  320. }
  321. void CAcquisitionManagerControllerWindow::MarkAllItemsUnselected( CWiaItem *pCurrItem )
  322. {
  323. while (pCurrItem)
  324. {
  325. pCurrItem->SelectedForDownload(false);
  326. MarkAllItemsUnselected( pCurrItem->Children() );
  327. pCurrItem = pCurrItem->Next();
  328. }
  329. }
  330. void CAcquisitionManagerControllerWindow::MarkItemSelected( CWiaItem *pItem, CWiaItem *pCurrItem )
  331. {
  332. while (pCurrItem)
  333. {
  334. if (pItem == pCurrItem && !pCurrItem->Deleted())
  335. {
  336. pCurrItem->SelectedForDownload(true);
  337. }
  338. MarkItemSelected( pItem, pCurrItem->Children() );
  339. pCurrItem = pCurrItem->Next();
  340. }
  341. }
  342. void CAcquisitionManagerControllerWindow::GetSelectedItems( CWiaItem *pCurr, CSimpleDynamicArray<CWiaItem*> &Items )
  343. {
  344. while (pCurr)
  345. {
  346. GetSelectedItems(pCurr->Children(),Items);
  347. if (pCurr->IsDownloadableItemType() && pCurr->SelectedForDownload())
  348. {
  349. Items.Append(pCurr);
  350. }
  351. pCurr = pCurr->Next();
  352. }
  353. }
  354. void CAcquisitionManagerControllerWindow::GetRotationOfSelectedImages( CWiaItem *pCurr, CSimpleDynamicArray<int> &Rotation )
  355. {
  356. while (pCurr)
  357. {
  358. GetRotationOfSelectedImages(pCurr->Children(),Rotation);
  359. if (pCurr->IsDownloadableItemType() && pCurr->SelectedForDownload())
  360. {
  361. Rotation.Append(pCurr->Rotation());
  362. }
  363. pCurr = pCurr->Next();
  364. }
  365. }
  366. void CAcquisitionManagerControllerWindow::GetCookiesOfAllImages( CWiaItem *pCurr, CSimpleDynamicArray<DWORD> &Cookies )
  367. {
  368. while (pCurr)
  369. {
  370. GetCookiesOfAllImages(pCurr->Children(),Cookies);
  371. if (pCurr->IsDownloadableItemType())
  372. {
  373. Cookies.Append(pCurr->GlobalInterfaceTableCookie());
  374. }
  375. pCurr = pCurr->Next();
  376. }
  377. }
  378. int CAcquisitionManagerControllerWindow::GetSelectedImageCount( void )
  379. {
  380. CSimpleDynamicArray<DWORD> Cookies;
  381. CSimpleDynamicArray<int> Rotation;
  382. GetCookiesOfSelectedImages( m_WiaItemList.Root(), Cookies );
  383. GetRotationOfSelectedImages( m_WiaItemList.Root(), Rotation );
  384. if (Rotation.Size() != Cookies.Size())
  385. {
  386. return 0;
  387. }
  388. return Cookies.Size();
  389. }
  390. bool CAcquisitionManagerControllerWindow::DeleteDownloadedImages( HANDLE hCancelDeleteEvent )
  391. {
  392. //
  393. // Make sure we are not paused
  394. //
  395. m_EventPauseBackgroundThread.Signal();
  396. CSimpleDynamicArray<DWORD> Cookies;
  397. for (int i=0;i<m_DownloadedFileInformationList.Size();i++)
  398. {
  399. Cookies.Append(m_DownloadedFileInformationList[i].Cookie());
  400. }
  401. if (Cookies.Size())
  402. {
  403. CDeleteImagesThreadMessage *pDeleteImageThreadMessage = new CDeleteImagesThreadMessage(
  404. m_hWnd,
  405. Cookies,
  406. hCancelDeleteEvent,
  407. m_EventPauseBackgroundThread.Event(),
  408. true
  409. );
  410. if (pDeleteImageThreadMessage)
  411. {
  412. m_pThreadMessageQueue->Enqueue( pDeleteImageThreadMessage, CThreadMessageQueue::PriorityNormal );
  413. }
  414. else
  415. {
  416. WIA_TRACE((TEXT("Uh-oh! Couldn't allocate the thread message")));
  417. return false;
  418. }
  419. }
  420. else
  421. {
  422. WIA_TRACE((TEXT("Uh-oh! No selected items! Cookies.Size() = %d"), Cookies.Size()));
  423. return false;
  424. }
  425. return true;
  426. }
  427. bool CAcquisitionManagerControllerWindow::DeleteSelectedImages(void)
  428. {
  429. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::DeleteSelectedImages"));
  430. CSimpleDynamicArray<DWORD> Cookies;
  431. GetCookiesOfSelectedImages( m_WiaItemList.Root(), Cookies );
  432. //
  433. // Make sure we are not paused
  434. //
  435. m_EventPauseBackgroundThread.Signal();
  436. if (Cookies.Size())
  437. {
  438. CDeleteImagesThreadMessage *pDeleteImageThreadMessage = new CDeleteImagesThreadMessage(
  439. m_hWnd,
  440. Cookies,
  441. NULL,
  442. m_EventPauseBackgroundThread.Event(),
  443. false
  444. );
  445. if (pDeleteImageThreadMessage)
  446. {
  447. m_pThreadMessageQueue->Enqueue( pDeleteImageThreadMessage, CThreadMessageQueue::PriorityNormal );
  448. }
  449. else
  450. {
  451. WIA_TRACE((TEXT("Uh-oh! Couldn't allocate the thread message")));
  452. return false;
  453. }
  454. }
  455. else
  456. {
  457. WIA_TRACE((TEXT("Uh-oh! No selected items! Cookies.Size() = %d"), Cookies.Size()));
  458. return false;
  459. }
  460. return true;
  461. }
  462. bool CAcquisitionManagerControllerWindow::DownloadSelectedImages( HANDLE hCancelDownloadEvent )
  463. {
  464. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::DownloadSelectedImages"));
  465. CSimpleDynamicArray<DWORD> Cookies;
  466. CSimpleDynamicArray<int> Rotation;
  467. GetCookiesOfSelectedImages( m_WiaItemList.Root(), Cookies );
  468. GetRotationOfSelectedImages( m_WiaItemList.Root(), Rotation );
  469. //
  470. // Make sure we are not paused
  471. //
  472. m_EventPauseBackgroundThread.Signal();
  473. if (Cookies.Size() && Rotation.Size() == Cookies.Size())
  474. {
  475. CDownloadImagesThreadMessage *pDownloadImageThreadMessage = new CDownloadImagesThreadMessage(
  476. m_hWnd,
  477. Cookies,
  478. Rotation,
  479. m_szDestinationDirectory,
  480. m_szRootFileName,
  481. m_guidOutputFormat,
  482. hCancelDownloadEvent,
  483. m_bStampTimeOnSavedFiles,
  484. m_EventPauseBackgroundThread.Event()
  485. );
  486. if (pDownloadImageThreadMessage)
  487. {
  488. m_pThreadMessageQueue->Enqueue( pDownloadImageThreadMessage, CThreadMessageQueue::PriorityNormal );
  489. }
  490. else
  491. {
  492. WIA_TRACE((TEXT("Uh-oh! Couldn't allocate the thread message")));
  493. return false;
  494. }
  495. }
  496. else
  497. {
  498. WIA_TRACE((TEXT("Uh-oh! No selected items! Cookies.Size() = %d, Rotation.Size() = %d"), Cookies.Size(), Rotation.Size()));
  499. return false;
  500. }
  501. return true;
  502. }
  503. bool CAcquisitionManagerControllerWindow::DirectoryExists( LPCTSTR pszDirectoryName )
  504. {
  505. // Try to determine if this directory exists
  506. DWORD dwFileAttributes = GetFileAttributes(pszDirectoryName);
  507. if (dwFileAttributes == 0xFFFFFFFF || !(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  508. return false;
  509. else return true;
  510. }
  511. bool CAcquisitionManagerControllerWindow::RecursiveCreateDirectory( CSimpleString strDirectoryName )
  512. {
  513. // If this directory already exists, return true.
  514. if (DirectoryExists(strDirectoryName))
  515. return true;
  516. // Otherwise try to create it.
  517. CreateDirectory(strDirectoryName,NULL);
  518. // If it now exists, return true
  519. if (DirectoryExists(strDirectoryName))
  520. return true;
  521. else
  522. {
  523. // Remove the last subdir and try again
  524. int nFind = strDirectoryName.ReverseFind(TEXT('\\'));
  525. if (nFind >= 0)
  526. {
  527. RecursiveCreateDirectory( strDirectoryName.Left(nFind) );
  528. // Now try to create it.
  529. CreateDirectory(strDirectoryName,NULL);
  530. }
  531. }
  532. //Does it exist now?
  533. return DirectoryExists(strDirectoryName);
  534. }
  535. bool CAcquisitionManagerControllerWindow::IsCameraThumbnailDownloaded( const CWiaItem &WiaItem, LPARAM lParam )
  536. {
  537. CAcquisitionManagerControllerWindow *pControllerWindow = reinterpret_cast<CAcquisitionManagerControllerWindow*>(lParam);
  538. if (pControllerWindow &&
  539. (pControllerWindow->m_DeviceTypeMode==CameraMode || pControllerWindow->m_DeviceTypeMode==VideoMode) &&
  540. WiaItem.IsDownloadableItemType() &&
  541. !WiaItem.BitmapData())
  542. {
  543. return true;
  544. }
  545. else
  546. {
  547. return false;
  548. }
  549. }
  550. int CAcquisitionManagerControllerWindow::GetCookies( CSimpleDynamicArray<DWORD> &Cookies, CWiaItem *pCurr, ComparisonCallbackFuntion pfnCallback, LPARAM lParam )
  551. {
  552. while (pCurr)
  553. {
  554. GetCookies(Cookies, pCurr->Children(), pfnCallback, lParam );
  555. if (pfnCallback && pfnCallback(*pCurr,lParam))
  556. {
  557. Cookies.Append(pCurr->GlobalInterfaceTableCookie());
  558. }
  559. pCurr = pCurr->Next();
  560. }
  561. return Cookies.Size();
  562. }
  563. // Download all of the camera's thumbnails that haven't been downloaded yet
  564. void CAcquisitionManagerControllerWindow::DownloadAllThumbnails()
  565. {
  566. //
  567. // Get all of the images in the device
  568. //
  569. CSimpleDynamicArray<DWORD> Cookies;
  570. GetCookies( Cookies, m_WiaItemList.Root(), IsCameraThumbnailDownloaded, reinterpret_cast<LPARAM>(this) );
  571. if (Cookies.Size())
  572. {
  573. m_EventThumbnailCancel.Reset();
  574. CDownloadThumbnailsThreadMessage *pDownloadThumbnailsThreadMessage = new CDownloadThumbnailsThreadMessage( m_hWnd, Cookies, m_EventThumbnailCancel.Event() );
  575. if (pDownloadThumbnailsThreadMessage)
  576. {
  577. m_pThreadMessageQueue->Enqueue( pDownloadThumbnailsThreadMessage, CThreadMessageQueue::PriorityNormal );
  578. }
  579. }
  580. }
  581. bool CAcquisitionManagerControllerWindow::PerformPreviewScan( CWiaItem *pWiaItem, HANDLE hCancelPreviewEvent )
  582. {
  583. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::PerformPreviewScan"));
  584. if (pWiaItem)
  585. {
  586. CPreviewScanThreadMessage *pPreviewScanThreadMessage = new CPreviewScanThreadMessage( m_hWnd, pWiaItem->GlobalInterfaceTableCookie(), hCancelPreviewEvent );
  587. if (pPreviewScanThreadMessage)
  588. {
  589. m_pThreadMessageQueue->Enqueue( pPreviewScanThreadMessage, CThreadMessageQueue::PriorityNormal );
  590. return true;
  591. }
  592. }
  593. return false;
  594. }
  595. void CAcquisitionManagerControllerWindow::DisplayDisconnectMessageAndExit(void)
  596. {
  597. //
  598. // Make sure we are not doing this more than once
  599. //
  600. if (!m_bDisconnected)
  601. {
  602. //
  603. // Don't do this again
  604. //
  605. m_bDisconnected = true;
  606. //
  607. // Close the shared memory section so another instance can start up
  608. //
  609. if (m_pEventParameters && m_pEventParameters->pWizardSharedMemory)
  610. {
  611. m_pEventParameters->pWizardSharedMemory->Close();
  612. }
  613. if (m_OnDisconnect & OnDisconnectFailDownload)
  614. {
  615. //
  616. // Set an appropriate error message
  617. //
  618. m_hrDownloadResult = WIA_ERROR_OFFLINE;
  619. m_strErrorMessage.LoadString( IDS_DEVICE_DISCONNECTED, g_hInstance );
  620. }
  621. if ((m_OnDisconnect & OnDisconnectGotoLastpage) && m_hWndWizard)
  622. {
  623. //
  624. // Find any active dialogs and close them
  625. //
  626. HWND hWndLastActive = GetLastActivePopup(m_hWndWizard);
  627. if (hWndLastActive && hWndLastActive != m_hWndWizard)
  628. {
  629. SendMessage( hWndLastActive, WM_CLOSE, 0, 0 );
  630. }
  631. //
  632. // Go to the finish page
  633. //
  634. PropSheet_SetCurSelByID( m_hWndWizard, IDD_COMMON_FINISH );
  635. }
  636. }
  637. }
  638. void CAcquisitionManagerControllerWindow::SetMainWindowInSharedMemory( HWND hWnd )
  639. {
  640. //
  641. // Try to grab the mutex
  642. //
  643. if (m_pEventParameters && m_pEventParameters->pWizardSharedMemory)
  644. {
  645. HWND *pHwnd = m_pEventParameters->pWizardSharedMemory->Lock();
  646. if (pHwnd)
  647. {
  648. //
  649. // Save the hWnd
  650. //
  651. *pHwnd = hWnd;
  652. //
  653. // Release the mutex
  654. //
  655. m_pEventParameters->pWizardSharedMemory->Release();
  656. }
  657. m_hWndWizard = hWnd;
  658. }
  659. }
  660. bool CAcquisitionManagerControllerWindow::GetAllImageItems( CSimpleDynamicArray<CWiaItem*> &Items, CWiaItem *pCurr )
  661. {
  662. while (pCurr)
  663. {
  664. if (pCurr->IsDownloadableItemType())
  665. {
  666. Items.Append( pCurr );
  667. }
  668. GetAllImageItems( Items, pCurr->Children() );
  669. pCurr = pCurr->Next();
  670. }
  671. return(Items.Size() != 0);
  672. }
  673. bool CAcquisitionManagerControllerWindow::GetAllImageItems( CSimpleDynamicArray<CWiaItem*> &Items )
  674. {
  675. return GetAllImageItems( Items, m_WiaItemList.Root() );
  676. }
  677. bool CAcquisitionManagerControllerWindow::CanSomeSelectedImagesBeDeleted(void)
  678. {
  679. CSimpleDynamicArray<CWiaItem*> Items;
  680. GetSelectedItems( m_WiaItemList.Root(), Items );
  681. //
  682. // Since we get these access flags in the background, if we don't actually have any yet,
  683. // we will assume some images CAN be deleted
  684. //
  685. bool bNoneAreInitialized = true;
  686. for (int i=0;i<Items.Size();i++)
  687. {
  688. if (Items[i])
  689. {
  690. if (Items[i]->AccessRights())
  691. {
  692. // At least one of the selected images has been initialized
  693. bNoneAreInitialized = false;
  694. // If at least one can be deleted, return true immediately
  695. if (Items[i]->AccessRights() & WIA_ITEM_CAN_BE_DELETED)
  696. {
  697. return true;
  698. }
  699. }
  700. }
  701. }
  702. // If none of the images have been initialized, then we will report true
  703. if (bNoneAreInitialized)
  704. {
  705. return true;
  706. }
  707. else
  708. {
  709. return false;
  710. }
  711. }
  712. CWiaItem *CAcquisitionManagerControllerWindow::FindItemByName( LPCWSTR pwszItemName )
  713. {
  714. WIA_PUSH_FUNCTION((TEXT("CAcquisitionManagerControllerWindow::FindItemByName( %ws )"), pwszItemName ));
  715. if (!pwszItemName)
  716. return NULL;
  717. if (!m_pWiaItemRoot)
  718. return NULL;
  719. return m_WiaItemList.Find(pwszItemName);
  720. }
  721. BOOL CAcquisitionManagerControllerWindow::ConfirmWizardCancel( HWND hWndParent )
  722. {
  723. //
  724. // Always let it exit, for now.
  725. //
  726. return FALSE;
  727. }
  728. int CALLBACK CAcquisitionManagerControllerWindow::PropSheetCallback( HWND hWnd, UINT uMsg, LPARAM lParam )
  729. {
  730. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::PropSheetCallback"));
  731. if (PSCB_INITIALIZED == uMsg)
  732. {
  733. //
  734. // Try to bring the window to the foreground.
  735. //
  736. SetForegroundWindow(hWnd);
  737. }
  738. return 0;
  739. }
  740. void CAcquisitionManagerControllerWindow::DetermineScannerType(void)
  741. {
  742. LONG nProps = ScannerProperties::GetDeviceProps( m_pWiaItemRoot );
  743. m_nScannerType = ScannerTypeUnknown;
  744. //
  745. // Determine which scanner type we have, based on which properties the scanner has, as follows:
  746. //
  747. // HasFlatBed HasDocumentFeeder SupportsPreview SupportsPageSize
  748. // 1 1 1 1 ScannerTypeFlatbedAdf
  749. // 1 0 1 0 ScannerTypeFlatbed
  750. // 0 1 1 1 ScannerTypeFlatbedAdf
  751. // 0 1 0 0 ScannerTypeScrollFed
  752. //
  753. // otherwise it is ScannerTypeUnknown
  754. //
  755. const int nMaxControllingProps = 4;
  756. static struct
  757. {
  758. LONG ControllingProps[nMaxControllingProps];
  759. int nScannerType;
  760. }
  761. s_DialogResourceData[] =
  762. {
  763. { ScannerProperties::HasFlatBed, ScannerProperties::HasDocumentFeeder, ScannerProperties::SupportsPreview, ScannerProperties::SupportsPageSize, NULL },
  764. { ScannerProperties::HasFlatBed, ScannerProperties::HasDocumentFeeder, ScannerProperties::SupportsPreview, ScannerProperties::SupportsPageSize, ScannerTypeFlatbedAdf },
  765. { ScannerProperties::HasFlatBed, 0, ScannerProperties::SupportsPreview, 0, ScannerTypeFlatbed },
  766. { 0, ScannerProperties::HasDocumentFeeder, ScannerProperties::SupportsPreview, ScannerProperties::SupportsPageSize, ScannerTypeFlatbedAdf },
  767. { 0, ScannerProperties::HasDocumentFeeder, 0, 0, ScannerTypeScrollFed },
  768. { 0, ScannerProperties::HasDocumentFeeder, 0, ScannerProperties::SupportsPageSize, ScannerTypeFlatbedAdf },
  769. { ScannerProperties::HasFlatBed, ScannerProperties::HasDocumentFeeder, 0, ScannerProperties::SupportsPageSize, ScannerTypeFlatbedAdf },
  770. };
  771. //
  772. // Find the set of flags that match this device. If they match, use this scanner type.
  773. // Loop through each type description.
  774. //
  775. for (int nCurrentResourceFlags=1;nCurrentResourceFlags<ARRAYSIZE(s_DialogResourceData) && (ScannerTypeUnknown == m_nScannerType);nCurrentResourceFlags++)
  776. {
  777. //
  778. // Loop through each controlling property
  779. //
  780. for (int nControllingProp=0;nControllingProp<nMaxControllingProps;nControllingProp++)
  781. {
  782. //
  783. // If this property DOESN'T match, break out prematurely
  784. //
  785. if ((nProps & s_DialogResourceData[0].ControllingProps[nControllingProp]) != s_DialogResourceData[nCurrentResourceFlags].ControllingProps[nControllingProp])
  786. {
  787. break;
  788. }
  789. }
  790. //
  791. // If the current controlling property is equal to the maximum controlling property,
  792. // we had matches all the way through, so use this type
  793. //
  794. if (nControllingProp == nMaxControllingProps)
  795. {
  796. m_nScannerType = s_DialogResourceData[nCurrentResourceFlags].nScannerType;
  797. }
  798. }
  799. }
  800. CSimpleString CAcquisitionManagerControllerWindow::GetCurrentDate(void)
  801. {
  802. SYSTEMTIME SystemTime;
  803. TCHAR szText[MAX_PATH] = TEXT("");
  804. GetLocalTime( &SystemTime );
  805. GetDateFormat( LOCALE_USER_DEFAULT, 0, &SystemTime, CSimpleString(IDS_DATEFORMAT,g_hInstance), szText, ARRAYSIZE(szText) );
  806. return szText;
  807. }
  808. bool CAcquisitionManagerControllerWindow::SuppressFirstPage(void)
  809. {
  810. return m_bSuppressFirstPage;
  811. }
  812. bool CAcquisitionManagerControllerWindow::IsSerialCamera(void)
  813. {
  814. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::IsSerialCamera"));
  815. //
  816. // Only check for serial devices if we are a camera
  817. //
  818. if (m_DeviceTypeMode==CameraMode)
  819. {
  820. #if defined(WIA_DIP_HW_CONFIG)
  821. //
  822. // Get the hardware configuration information
  823. //
  824. LONG nHardwareConfig = 0;
  825. if (PropStorageHelpers::GetProperty( m_pWiaItemRoot, WIA_DIP_HW_CONFIG, nHardwareConfig ))
  826. {
  827. //
  828. // If this is a serial device, return true
  829. //
  830. if (nHardwareConfig & STI_HW_CONFIG_SERIAL)
  831. {
  832. return true;
  833. }
  834. }
  835. #else
  836. CSimpleStringWide strwPortName;
  837. if (PropStorageHelpers::GetProperty( m_pWiaItemRoot, WIA_DIP_PORT_NAME, strwPortName ))
  838. {
  839. //
  840. // Compare the leftmost 3 characters to the word COM (as in COM1, COM2, ... )
  841. //
  842. if (strwPortName.Left(3).CompareNoCase(CSimpleStringWide(L"COM"))==0)
  843. {
  844. WIA_TRACE((TEXT("A comparison of %ws and COM succeeded"), strwPortName.Left(3).String() ));
  845. return true;
  846. }
  847. //
  848. // Compare the portname to the word AUTO
  849. //
  850. else if (strwPortName.CompareNoCase(CSimpleStringWide(L"AUTO"))==0)
  851. {
  852. WIA_TRACE((TEXT("A comparison of %ws and AUTO succeeded"), strwPortName.String() ));
  853. return true;
  854. }
  855. }
  856. #endif
  857. }
  858. //
  859. // Not a serial camera
  860. //
  861. return false;
  862. }
  863. HRESULT CAcquisitionManagerControllerWindow::CreateAndExecuteWizard(void)
  864. {
  865. //
  866. // Structure used to setup our data-driven property sheet factory
  867. //
  868. enum CPageType
  869. {
  870. NormalPage = 0,
  871. FirstPage = 1,
  872. LastPage = 2
  873. };
  874. struct CPropertyPageInfo
  875. {
  876. LPCTSTR pszTemplate;
  877. DLGPROC pfnDlgProc;
  878. int nIdTitle;
  879. int nIdSubTitle;
  880. TCHAR szTitle[256];
  881. TCHAR szSubTitle[1024];
  882. CPageType PageType;
  883. bool *pbDisplay;
  884. int *pnPageIndex;
  885. };
  886. //
  887. // Maximum number of statically created wizard pages
  888. //
  889. const int c_nMaxWizardPages = 7;
  890. HRESULT hr = S_OK;
  891. //
  892. // Register common controls
  893. //
  894. INITCOMMONCONTROLSEX icce;
  895. icce.dwSize = sizeof(icce);
  896. icce.dwICC = ICC_WIN95_CLASSES | ICC_LISTVIEW_CLASSES | ICC_USEREX_CLASSES | ICC_PROGRESS_CLASS | ICC_LINK_CLASS;
  897. InitCommonControlsEx( &icce );
  898. //
  899. // Register custom window classes
  900. //
  901. CWiaTextControl::RegisterClass( g_hInstance );
  902. RegisterWiaPreviewClasses( g_hInstance );
  903. //
  904. // These are the pages we'll use for the scanner wizard, if it doesn't have an ADF
  905. //
  906. CPropertyPageInfo ScannerPropSheetPageInfo[] =
  907. {
  908. { MAKEINTRESOURCE(IDD_SCANNER_FIRST), CCommonFirstPage::DialogProc, 0, 0, TEXT(""), TEXT(""), FirstPage, NULL, NULL },
  909. { MAKEINTRESOURCE(IDD_SCANNER_SELECT), CScannerSelectionPage::DialogProc, IDS_SCANNER_SELECT_TITLE, IDS_SCANNER_SELECT_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nSelectionPageIndex },
  910. { MAKEINTRESOURCE(IDD_SCANNER_TRANSFER), CCommonTransferPage::DialogProc, IDS_SCANNER_TRANSFER_TITLE, IDS_SCANNER_TRANSFER_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nDestinationPageIndex },
  911. { MAKEINTRESOURCE(IDD_COMMON_PROGRESS), CCommonProgressPage::DialogProc, IDS_SCANNER_PROGRESS_TITLE, IDS_SCANNER_PROGRESS_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nProgressPageIndex },
  912. { MAKEINTRESOURCE(IDD_UPLOAD_QUERY), CCommonUploadQueryPage::DialogProc, IDS_COMMON_UPLOAD_TITLE, IDS_COMMON_UPLOAD_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nUploadQueryPageIndex },
  913. { MAKEINTRESOURCE(IDD_COMMON_DELETE), CCommonDeleteProgressPage::DialogProc, IDS_COMMON_DELETE_TITLE, IDS_COMMON_DELETE_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nDeleteProgressPageIndex },
  914. { MAKEINTRESOURCE(IDD_COMMON_FINISH), CCommonFinishPage::DialogProc, 0, 0, TEXT(""), TEXT(""), LastPage, NULL, &m_nFinishPageIndex }
  915. };
  916. //
  917. // These are the pages we'll use for the scanner wizard, if it is a scroll-fed scanner
  918. //
  919. CPropertyPageInfo ScannerScrollFedPropSheetPageInfo[] =
  920. {
  921. { MAKEINTRESOURCE(IDD_SCANNER_FIRST), CCommonFirstPage::DialogProc, 0, 0, TEXT(""), TEXT(""), FirstPage, NULL, NULL },
  922. { MAKEINTRESOURCE(IDD_SCANNER_SELECT), CScannerSelectionPage::DialogProc, IDS_SCROLLFED_SELECT_TITLE, IDS_SCROLLFED_SELECT_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nSelectionPageIndex },
  923. { MAKEINTRESOURCE(IDD_SCANNER_TRANSFER), CCommonTransferPage::DialogProc, IDS_SCANNER_TRANSFER_TITLE, IDS_SCANNER_TRANSFER_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nDestinationPageIndex },
  924. { MAKEINTRESOURCE(IDD_COMMON_PROGRESS), CCommonProgressPage::DialogProc, IDS_SCANNER_PROGRESS_TITLE, IDS_SCANNER_PROGRESS_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nProgressPageIndex },
  925. { MAKEINTRESOURCE(IDD_UPLOAD_QUERY), CCommonUploadQueryPage::DialogProc, IDS_COMMON_UPLOAD_TITLE, IDS_COMMON_UPLOAD_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nUploadQueryPageIndex },
  926. { MAKEINTRESOURCE(IDD_COMMON_DELETE), CCommonDeleteProgressPage::DialogProc, IDS_COMMON_DELETE_TITLE, IDS_COMMON_DELETE_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nDeleteProgressPageIndex },
  927. { MAKEINTRESOURCE(IDD_COMMON_FINISH), CCommonFinishPage::DialogProc, 0, 0, TEXT(""), TEXT(""), LastPage, NULL, &m_nFinishPageIndex }
  928. };
  929. //
  930. // These are the pages we'll use for the scanner wizard, if it does have an ADF
  931. //
  932. CPropertyPageInfo ScannerADFPropSheetPageInfo[] =
  933. {
  934. { MAKEINTRESOURCE(IDD_SCANNER_FIRST), CCommonFirstPage::DialogProc, 0, 0, TEXT(""), TEXT(""), FirstPage, NULL, NULL },
  935. { MAKEINTRESOURCE(IDD_SCANNER_ADF_SELECT), CScannerSelectionPage::DialogProc, IDS_SCANNER_SELECT_TITLE, IDS_SCANNER_SELECT_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nSelectionPageIndex },
  936. { MAKEINTRESOURCE(IDD_SCANNER_TRANSFER), CCommonTransferPage::DialogProc, IDS_SCANNER_TRANSFER_TITLE, IDS_SCANNER_TRANSFER_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nDestinationPageIndex },
  937. { MAKEINTRESOURCE(IDD_COMMON_PROGRESS), CCommonProgressPage::DialogProc, IDS_SCANNER_PROGRESS_TITLE, IDS_SCANNER_PROGRESS_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nProgressPageIndex },
  938. { MAKEINTRESOURCE(IDD_UPLOAD_QUERY), CCommonUploadQueryPage::DialogProc, IDS_COMMON_UPLOAD_TITLE, IDS_COMMON_UPLOAD_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nUploadQueryPageIndex },
  939. { MAKEINTRESOURCE(IDD_COMMON_DELETE), CCommonDeleteProgressPage::DialogProc, IDS_COMMON_DELETE_TITLE, IDS_COMMON_DELETE_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nDeleteProgressPageIndex },
  940. { MAKEINTRESOURCE(IDD_COMMON_FINISH), CCommonFinishPage::DialogProc, 0, 0, TEXT(""), TEXT(""), LastPage, NULL, &m_nFinishPageIndex }
  941. };
  942. //
  943. // These are the pages we'll use for the camera wizard
  944. //
  945. CPropertyPageInfo CameraPropSheetPageInfo[] =
  946. {
  947. { MAKEINTRESOURCE(IDD_CAMERA_FIRST), CCommonFirstPage::DialogProc, 0, 0, TEXT(""), TEXT(""), FirstPage, NULL, NULL },
  948. { MAKEINTRESOURCE(IDD_CAMERA_SELECT), CCameraSelectionPage::DialogProc, IDS_CAMERA_SELECT_TITLE, IDS_CAMERA_SELECT_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nSelectionPageIndex },
  949. { MAKEINTRESOURCE(IDD_CAMERA_TRANSFER), CCommonTransferPage::DialogProc, IDS_CAMERA_TRANSFER_TITLE, IDS_CAMERA_TRANSFER_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nDestinationPageIndex },
  950. { MAKEINTRESOURCE(IDD_COMMON_PROGRESS), CCommonProgressPage::DialogProc, IDS_CAMERA_PROGRESS_TITLE, IDS_CAMERA_PROGRESS_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nProgressPageIndex },
  951. { MAKEINTRESOURCE(IDD_UPLOAD_QUERY), CCommonUploadQueryPage::DialogProc, IDS_COMMON_UPLOAD_TITLE, IDS_COMMON_UPLOAD_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nUploadQueryPageIndex },
  952. { MAKEINTRESOURCE(IDD_COMMON_DELETE), CCommonDeleteProgressPage::DialogProc, IDS_COMMON_DELETE_TITLE, IDS_COMMON_DELETE_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nDeleteProgressPageIndex },
  953. { MAKEINTRESOURCE(IDD_COMMON_FINISH), CCommonFinishPage::DialogProc, 0, 0, TEXT(""), TEXT(""), LastPage, NULL, &m_nFinishPageIndex }
  954. };
  955. //
  956. // These are the pages we'll use for the video wizard
  957. //
  958. CPropertyPageInfo VideoPropSheetPageInfo[] =
  959. {
  960. { MAKEINTRESOURCE(IDD_VIDEO_FIRST), CCommonFirstPage::DialogProc, 0, 0, TEXT(""), TEXT(""), FirstPage, NULL, NULL },
  961. { MAKEINTRESOURCE(IDD_VIDEO_SELECT), CCameraSelectionPage::DialogProc, IDS_VIDEO_SELECT_TITLE, IDS_VIDEO_SELECT_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nSelectionPageIndex },
  962. { MAKEINTRESOURCE(IDD_CAMERA_TRANSFER), CCommonTransferPage::DialogProc, IDS_CAMERA_TRANSFER_TITLE, IDS_CAMERA_TRANSFER_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nDestinationPageIndex },
  963. { MAKEINTRESOURCE(IDD_COMMON_PROGRESS), CCommonProgressPage::DialogProc, IDS_CAMERA_PROGRESS_TITLE, IDS_CAMERA_PROGRESS_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nProgressPageIndex },
  964. { MAKEINTRESOURCE(IDD_UPLOAD_QUERY), CCommonUploadQueryPage::DialogProc, IDS_COMMON_UPLOAD_TITLE, IDS_COMMON_UPLOAD_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nUploadQueryPageIndex },
  965. { MAKEINTRESOURCE(IDD_COMMON_DELETE), CCommonDeleteProgressPage::DialogProc, IDS_COMMON_DELETE_TITLE, IDS_COMMON_DELETE_SUBTITLE, TEXT(""), TEXT(""), NormalPage, NULL, &m_nDeleteProgressPageIndex },
  966. { MAKEINTRESOURCE(IDD_COMMON_FINISH), CCommonFinishPage::DialogProc, 0, 0, TEXT(""), TEXT(""), LastPage, NULL, &m_nFinishPageIndex }
  967. };
  968. //
  969. // Initialize all of these variables, which differ depending on which type of device we are loading
  970. //
  971. LPTSTR pszbmWatermark = NULL;
  972. LPTSTR pszbmHeader = NULL;
  973. CPropertyPageInfo *pPropSheetPageInfo = NULL;
  974. int nPropPageCount = 0;
  975. int nWizardIconId = 0;
  976. CSimpleString strDownloadManagerTitle = TEXT("");
  977. //
  978. // Decide which pages to use.
  979. //
  980. switch (m_DeviceTypeMode)
  981. {
  982. case CameraMode:
  983. pszbmWatermark = MAKEINTRESOURCE(IDB_CAMERA_WATERMARK);
  984. pszbmHeader = MAKEINTRESOURCE(IDB_CAMERA_HEADER);
  985. pPropSheetPageInfo = CameraPropSheetPageInfo;
  986. nPropPageCount = ARRAYSIZE(CameraPropSheetPageInfo);
  987. strDownloadManagerTitle.LoadString( IDS_DOWNLOAD_MANAGER_TITLE, g_hInstance );
  988. nWizardIconId = IDI_CAMERA_WIZARD;
  989. break;
  990. case VideoMode:
  991. pszbmWatermark = MAKEINTRESOURCE(IDB_VIDEO_WATERMARK);
  992. pszbmHeader = MAKEINTRESOURCE(IDB_VIDEO_HEADER);
  993. pPropSheetPageInfo = VideoPropSheetPageInfo;
  994. nPropPageCount = ARRAYSIZE(VideoPropSheetPageInfo);
  995. strDownloadManagerTitle.LoadString( IDS_DOWNLOAD_MANAGER_TITLE, g_hInstance );
  996. nWizardIconId = IDI_VIDEO_WIZARD;
  997. break;
  998. case ScannerMode:
  999. DetermineScannerType();
  1000. pszbmWatermark = MAKEINTRESOURCE(IDB_SCANNER_WATERMARK);
  1001. pszbmHeader = MAKEINTRESOURCE(IDB_SCANNER_HEADER);
  1002. strDownloadManagerTitle.LoadString( IDS_DOWNLOAD_MANAGER_TITLE, g_hInstance );
  1003. nWizardIconId = IDI_SCANNER_WIZARD;
  1004. if (m_nScannerType == ScannerTypeFlatbedAdf)
  1005. {
  1006. pPropSheetPageInfo = ScannerADFPropSheetPageInfo;
  1007. nPropPageCount = ARRAYSIZE(ScannerADFPropSheetPageInfo);
  1008. }
  1009. else if (m_nScannerType == ScannerTypeFlatbed)
  1010. {
  1011. pPropSheetPageInfo = ScannerPropSheetPageInfo;
  1012. nPropPageCount = ARRAYSIZE(ScannerPropSheetPageInfo);
  1013. }
  1014. else if (m_nScannerType == ScannerTypeScrollFed)
  1015. {
  1016. pPropSheetPageInfo = ScannerScrollFedPropSheetPageInfo;
  1017. nPropPageCount = ARRAYSIZE(ScannerScrollFedPropSheetPageInfo);
  1018. }
  1019. else
  1020. {
  1021. //
  1022. // Unknown scanner type
  1023. //
  1024. }
  1025. break;
  1026. default:
  1027. return E_INVALIDARG;
  1028. }
  1029. HICON hIconSmall=NULL, hIconBig=NULL;
  1030. if (!SUCCEEDED(WiaUiExtensionHelper::GetDeviceIcons( CSimpleBStr(m_strwDeviceUiClassId), m_nDeviceType, &hIconSmall, &hIconBig )))
  1031. {
  1032. //
  1033. // Load the icons. They will be set using WM_SETICON in the first pages.
  1034. //
  1035. hIconSmall = reinterpret_cast<HICON>(LoadImage( g_hInstance, MAKEINTRESOURCE(nWizardIconId), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR ));
  1036. hIconBig = reinterpret_cast<HICON>(LoadImage( g_hInstance, MAKEINTRESOURCE(nWizardIconId), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR ));
  1037. }
  1038. //
  1039. // Make copies of these icons to work around NTBUG 351806
  1040. //
  1041. if (hIconSmall)
  1042. {
  1043. m_hWizardIconSmall = CopyIcon(hIconSmall);
  1044. DestroyIcon(hIconSmall);
  1045. }
  1046. if (hIconBig)
  1047. {
  1048. m_hWizardIconBig = CopyIcon(hIconBig);
  1049. DestroyIcon(hIconBig);
  1050. }
  1051. //
  1052. // Make sure we have a valid set of data
  1053. //
  1054. if (pszbmWatermark && pszbmHeader && pPropSheetPageInfo && nPropPageCount)
  1055. {
  1056. const int c_MaxPageCount = 20;
  1057. HPROPSHEETPAGE PropSheetPages[c_MaxPageCount] = {0};
  1058. //
  1059. // We might not be adding all of the pages.
  1060. //
  1061. int nTotalPageCount = 0;
  1062. for (int nCurrPage=0;nCurrPage<nPropPageCount && nCurrPage<c_MaxPageCount;nCurrPage++)
  1063. {
  1064. //
  1065. // Only add the page if the controlling pbDisplay variable is NULL or points to a non-FALSE value
  1066. //
  1067. if (!pPropSheetPageInfo[nCurrPage].pbDisplay || *(pPropSheetPageInfo[nCurrPage].pbDisplay))
  1068. {
  1069. PROPSHEETPAGE CurrentPropSheetPage = {0};
  1070. //
  1071. // Set up all of the required fields from out static info.
  1072. //
  1073. CurrentPropSheetPage.dwSize = sizeof(PROPSHEETPAGE);
  1074. CurrentPropSheetPage.hInstance = g_hInstance;
  1075. CurrentPropSheetPage.lParam = reinterpret_cast<LPARAM>(this);
  1076. CurrentPropSheetPage.pfnDlgProc = pPropSheetPageInfo[nCurrPage].pfnDlgProc;
  1077. CurrentPropSheetPage.pszTemplate = pPropSheetPageInfo[nCurrPage].pszTemplate;
  1078. CurrentPropSheetPage.pszTitle = strDownloadManagerTitle.String();
  1079. CurrentPropSheetPage.dwFlags = PSP_DEFAULT;
  1080. //
  1081. // Add in the fusion flags to get COMCTLV6
  1082. //
  1083. WiaUiUtil::PreparePropertyPageForFusion( &CurrentPropSheetPage );
  1084. //
  1085. // If we want to save the index of this page, save it
  1086. //
  1087. if (pPropSheetPageInfo[nTotalPageCount].pnPageIndex)
  1088. {
  1089. *(pPropSheetPageInfo[nTotalPageCount].pnPageIndex) = nTotalPageCount;
  1090. }
  1091. if (FirstPage == pPropSheetPageInfo[nCurrPage].PageType)
  1092. {
  1093. //
  1094. // No title or subtitle needed for "first pages"
  1095. //
  1096. CurrentPropSheetPage.dwFlags |= PSP_PREMATURE | PSP_HIDEHEADER | PSP_USETITLE;
  1097. }
  1098. else if (LastPage == pPropSheetPageInfo[nCurrPage].PageType)
  1099. {
  1100. //
  1101. // No title or subtitle needed for "last pages"
  1102. //
  1103. CurrentPropSheetPage.dwFlags |= PSP_HIDEHEADER | PSP_USETITLE;
  1104. }
  1105. else
  1106. {
  1107. //
  1108. // Add header and subtitle
  1109. //
  1110. CurrentPropSheetPage.dwFlags |= PSP_PREMATURE | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE | PSP_USETITLE;
  1111. //
  1112. // Load the header and subtitle
  1113. //
  1114. LoadString( g_hInstance, pPropSheetPageInfo[nCurrPage].nIdTitle, pPropSheetPageInfo[nCurrPage].szTitle, ARRAYSIZE(pPropSheetPageInfo[nCurrPage].szTitle) );
  1115. LoadString( g_hInstance, pPropSheetPageInfo[nCurrPage].nIdSubTitle, pPropSheetPageInfo[nCurrPage].szSubTitle, ARRAYSIZE(pPropSheetPageInfo[nCurrPage].szSubTitle) );
  1116. //
  1117. // Assign the title and subtitle strings
  1118. //
  1119. CurrentPropSheetPage.pszHeaderTitle = pPropSheetPageInfo[nCurrPage].szTitle;
  1120. CurrentPropSheetPage.pszHeaderSubTitle = pPropSheetPageInfo[nCurrPage].szSubTitle;
  1121. }
  1122. //
  1123. // Create and add one more page
  1124. //
  1125. HPROPSHEETPAGE hPropSheetPage = CreatePropertySheetPage(&CurrentPropSheetPage);
  1126. if (!hPropSheetPage)
  1127. {
  1128. WIA_PRINTHRESULT((HRESULT_FROM_WIN32(GetLastError()),TEXT("CreatePropertySheetPage failed on page %d"), nCurrPage ));
  1129. return E_FAIL;
  1130. }
  1131. PropSheetPages[nTotalPageCount++] = hPropSheetPage;
  1132. }
  1133. }
  1134. //
  1135. // Save the count of our pages
  1136. //
  1137. m_nWiaWizardPageCount = nTotalPageCount;
  1138. //
  1139. // Create the property sheet header
  1140. //
  1141. PROPSHEETHEADER PropSheetHeader = {0};
  1142. PropSheetHeader.hwndParent = NULL;
  1143. PropSheetHeader.dwSize = sizeof(PROPSHEETHEADER);
  1144. PropSheetHeader.dwFlags = PSH_NOAPPLYNOW | PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER | PSH_USECALLBACK;
  1145. PropSheetHeader.pszbmWatermark = pszbmWatermark;
  1146. PropSheetHeader.pszbmHeader = pszbmHeader;
  1147. PropSheetHeader.hInstance = g_hInstance;
  1148. PropSheetHeader.nPages = m_nWiaWizardPageCount;
  1149. PropSheetHeader.phpage = PropSheetPages;
  1150. PropSheetHeader.pfnCallback = PropSheetCallback;
  1151. PropSheetHeader.nStartPage = SuppressFirstPage() ? 1 : 0;
  1152. //
  1153. // Display the property sheet
  1154. //
  1155. INT_PTR nResult = PropertySheet( &PropSheetHeader );
  1156. //
  1157. // Check for an error
  1158. //
  1159. if (nResult == -1)
  1160. {
  1161. hr = HRESULT_FROM_WIN32(GetLastError());
  1162. }
  1163. }
  1164. else
  1165. {
  1166. //
  1167. // Generic failure will have to do
  1168. //
  1169. hr = E_FAIL;
  1170. //
  1171. // Dismiss the wait dialog before we display the message box
  1172. //
  1173. if (m_pWiaProgressDialog)
  1174. {
  1175. m_pWiaProgressDialog->Destroy();
  1176. m_pWiaProgressDialog = NULL;
  1177. }
  1178. //
  1179. // Display an error message telling the user this is not a supported device
  1180. //
  1181. CMessageBoxEx::MessageBox( m_hWnd, CSimpleString(IDS_UNSUPPORTED_DEVICE,g_hInstance), CSimpleString(IDS_ERROR_TITLE,g_hInstance), CMessageBoxEx::MBEX_ICONWARNING );
  1182. WIA_ERROR((TEXT("Unknown device type")));
  1183. }
  1184. //
  1185. // Make sure the status dialog has been dismissed by now
  1186. //
  1187. if (m_pWiaProgressDialog)
  1188. {
  1189. m_pWiaProgressDialog->Destroy();
  1190. m_pWiaProgressDialog = NULL;
  1191. }
  1192. return hr;
  1193. }
  1194. bool CAcquisitionManagerControllerWindow::EnumItemsCallback( CWiaItemList::CEnumEvent EnumEvent, UINT nData, LPARAM lParam, bool bForceUpdate )
  1195. {
  1196. //
  1197. // We would return false to cancel enumeration
  1198. //
  1199. bool bResult = true;
  1200. //
  1201. // Get the instance of the controller window
  1202. //
  1203. CAcquisitionManagerControllerWindow *pThis = reinterpret_cast<CAcquisitionManagerControllerWindow*>(lParam);
  1204. if (pThis)
  1205. {
  1206. //
  1207. // Which event are we being called for?
  1208. //
  1209. switch (EnumEvent)
  1210. {
  1211. case CWiaItemList::ReadingItemInfo:
  1212. //
  1213. // This is the event that is sent while the tree is being built
  1214. //
  1215. if (pThis->m_pWiaProgressDialog && pThis->m_bUpdateEnumerationCount && nData)
  1216. {
  1217. //
  1218. // We don't want to update the status text any more often than this (minimizes flicker)
  1219. //
  1220. const DWORD dwMinDelta = 200;
  1221. //
  1222. // Get the current tick count and see if it has been more than dwMinDelta milliseconds since our last update
  1223. //
  1224. DWORD dwCurrentTickCount = GetTickCount();
  1225. if (bForceUpdate || dwCurrentTickCount - pThis->m_dwLastEnumerationTickCount >= dwMinDelta)
  1226. {
  1227. //
  1228. // Assume we haven't been cancelled
  1229. //
  1230. BOOL bCancelled = FALSE;
  1231. //
  1232. // Set the progress message
  1233. //
  1234. pThis->m_pWiaProgressDialog->SetMessage( CSimpleStringWide().Format( IDS_ENUMERATIONCOUNT, g_hInstance, nData ) );
  1235. //
  1236. // Find out if we've been cancelled
  1237. //
  1238. pThis->m_pWiaProgressDialog->Cancelled(&bCancelled);
  1239. //
  1240. // If we have been cancelled, we'll return false to stop the enumeration
  1241. //
  1242. if (bCancelled)
  1243. {
  1244. bResult = false;
  1245. }
  1246. //
  1247. // Save the current tick count for next time
  1248. //
  1249. pThis->m_dwLastEnumerationTickCount = dwCurrentTickCount;
  1250. }
  1251. }
  1252. break;
  1253. }
  1254. }
  1255. return bResult;
  1256. }
  1257. LRESULT CAcquisitionManagerControllerWindow::OnPostInitialize( WPARAM, LPARAM )
  1258. {
  1259. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::OnInitialize"));
  1260. //
  1261. // Try to get the correct animation for this device type. If we can't get the type,
  1262. // just use the camera animation. If there is a real error, it will get handled later
  1263. //
  1264. int nAnimationType = WIA_PROGRESSDLG_ANIM_CAMERA_COMMUNICATE;
  1265. LONG nAnimationDeviceType = 0;
  1266. //
  1267. // We don't want to update our enumeration count in the progress dialog for scanners, but we do for cameras
  1268. //
  1269. m_bUpdateEnumerationCount = true;
  1270. if (SUCCEEDED(WiaUiUtil::GetDeviceTypeFromId( CSimpleBStr(m_pEventParameters->strDeviceID), &nAnimationDeviceType )))
  1271. {
  1272. if (StiDeviceTypeScanner == GET_STIDEVICE_TYPE(nAnimationDeviceType))
  1273. {
  1274. nAnimationType = WIA_PROGRESSDLG_ANIM_SCANNER_COMMUNICATE;
  1275. m_bUpdateEnumerationCount = false;
  1276. }
  1277. else if (StiDeviceTypeStreamingVideo == GET_STIDEVICE_TYPE(nAnimationDeviceType))
  1278. {
  1279. nAnimationType = WIA_PROGRESSDLG_ANIM_VIDEO_COMMUNICATE;
  1280. }
  1281. }
  1282. //
  1283. // Put up a wait dialog
  1284. //
  1285. HRESULT hr = CoCreateInstance( CLSID_WiaDefaultUi, NULL, CLSCTX_INPROC_SERVER, IID_IWiaProgressDialog, (void**)&m_pWiaProgressDialog );
  1286. if (SUCCEEDED(hr))
  1287. {
  1288. m_pWiaProgressDialog->Create( m_hWnd, nAnimationType|WIA_PROGRESSDLG_NO_PROGRESS );
  1289. m_pWiaProgressDialog->SetTitle( CSimpleStringConvert::WideString(CSimpleString(IDS_DOWNLOADMANAGER_NAME,g_hInstance)));
  1290. m_pWiaProgressDialog->SetMessage( CSimpleStringConvert::WideString(CSimpleString(IDS_PROGDLG_MESSAGE,g_hInstance)));
  1291. //
  1292. // Show the progress dialog
  1293. //
  1294. m_pWiaProgressDialog->Show();
  1295. //
  1296. // Create the global interface table
  1297. //
  1298. hr = CoCreateInstance( CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (VOID**)&m_pGlobalInterfaceTable );
  1299. if (SUCCEEDED(hr))
  1300. {
  1301. //
  1302. // Create the device
  1303. //
  1304. hr = WIA_FORCE_ERROR(FE_WIAACMGR,100,CreateDevice());
  1305. if (SUCCEEDED(hr))
  1306. {
  1307. //
  1308. // Save a debug snapshot, if the entry is in the registry
  1309. //
  1310. WIA_SAVEITEMTREELOG(HKEY_CURRENT_USER,REGSTR_PATH_USER_SETTINGS_WIAACMGR,TEXT("CreateDeviceTreeSnapshot"),true,m_pWiaItemRoot);
  1311. //
  1312. // First, figure out what kind of device it is and get the UI class ID
  1313. //
  1314. if (PropStorageHelpers::GetProperty( m_pWiaItemRoot, WIA_DIP_DEV_TYPE, m_nDeviceType ) &&
  1315. PropStorageHelpers::GetProperty( m_pWiaItemRoot, WIA_DIP_UI_CLSID, m_strwDeviceUiClassId ))
  1316. {
  1317. switch (GET_STIDEVICE_TYPE(m_nDeviceType))
  1318. {
  1319. case StiDeviceTypeScanner:
  1320. m_DeviceTypeMode = ScannerMode;
  1321. break;
  1322. case StiDeviceTypeDigitalCamera:
  1323. m_DeviceTypeMode = CameraMode;
  1324. break;
  1325. case StiDeviceTypeStreamingVideo:
  1326. m_DeviceTypeMode = VideoMode;
  1327. break;
  1328. default:
  1329. m_DeviceTypeMode = UnknownMode;
  1330. hr = E_FAIL;
  1331. break;
  1332. }
  1333. }
  1334. else
  1335. {
  1336. hr = E_FAIL;
  1337. WIA_ERROR((TEXT("Unable to read the device type")));
  1338. }
  1339. if (SUCCEEDED(hr))
  1340. {
  1341. //
  1342. // Get the device name
  1343. //
  1344. PropStorageHelpers::GetProperty( m_pWiaItemRoot, WIA_DIP_DEV_NAME, m_strwDeviceName );
  1345. //
  1346. // Find out if Take Picture is supported
  1347. //
  1348. m_bTakePictureIsSupported = WiaUiUtil::IsDeviceCommandSupported( m_pWiaItemRoot, WIA_CMD_TAKE_PICTURE );
  1349. //
  1350. // Enumerate all the items in the device tree
  1351. //
  1352. hr = m_WiaItemList.EnumerateAllWiaItems(m_pWiaItemRoot,EnumItemsCallback,reinterpret_cast<LPARAM>(this));
  1353. if (S_OK == hr)
  1354. {
  1355. if (ScannerMode == m_DeviceTypeMode)
  1356. {
  1357. //
  1358. // Mark only one scanner item as selected, and save it as the current scanner item
  1359. //
  1360. MarkAllItemsUnselected( m_WiaItemList.Root() );
  1361. CSimpleDynamicArray<CWiaItem*> Items;
  1362. GetAllImageItems( Items, m_WiaItemList.Root() );
  1363. if (Items.Size() && Items[0])
  1364. {
  1365. m_pCurrentScannerItem = Items[0];
  1366. MarkItemSelected(Items[0],m_WiaItemList.Root());
  1367. //
  1368. // Make sure we have all of the properties we need to construct the device
  1369. //
  1370. hr = WiaUiUtil::VerifyScannerProperties(Items[0]->WiaItem());
  1371. }
  1372. else
  1373. {
  1374. hr = E_FAIL;
  1375. WIA_ERROR((TEXT("There don't seem to be any transfer items on this scanner")));
  1376. }
  1377. }
  1378. else if (VideoMode == m_DeviceTypeMode || CameraMode == m_DeviceTypeMode)
  1379. {
  1380. //
  1381. // Get the thumbnail width
  1382. //
  1383. LONG nWidth, nHeight;
  1384. if (PropStorageHelpers::GetProperty( m_pWiaItemRoot, WIA_DPC_THUMB_WIDTH, nWidth ) &&
  1385. PropStorageHelpers::GetProperty( m_pWiaItemRoot, WIA_DPC_THUMB_HEIGHT, nHeight ))
  1386. {
  1387. int nMax = max(nWidth,nHeight); // Allow for rotation
  1388. m_sizeThumbnails.cx = max(c_nMinThumbnailWidth,min(nMax,c_nMaxThumbnailWidth));
  1389. m_sizeThumbnails.cy = max(c_nMinThumbnailHeight,min(nMax,c_nMaxThumbnailHeight));
  1390. }
  1391. }
  1392. }
  1393. }
  1394. }
  1395. }
  1396. }
  1397. if (!SUCCEEDED(hr))
  1398. {
  1399. //
  1400. // Dismiss the wait dialog
  1401. //
  1402. if (m_pWiaProgressDialog)
  1403. {
  1404. m_pWiaProgressDialog->Destroy();
  1405. m_pWiaProgressDialog = NULL;
  1406. }
  1407. //
  1408. // Choose an appropriate error message if we have a recognizable error.
  1409. //
  1410. CSimpleString strMessage;
  1411. int nIconId = 0;
  1412. switch (hr)
  1413. {
  1414. case WIA_ERROR_BUSY:
  1415. strMessage.LoadString( IDS_DEVICE_BUSY, g_hInstance );
  1416. nIconId = MB_ICONINFORMATION;
  1417. break;
  1418. case WIA_S_NO_DEVICE_AVAILABLE:
  1419. strMessage.LoadString( IDS_DEVICE_NOT_FOUND, g_hInstance );
  1420. nIconId = MB_ICONINFORMATION;
  1421. break;
  1422. default:
  1423. strMessage.LoadString( IDS_UNABLETOCREATE, g_hInstance );
  1424. nIconId = MB_ICONINFORMATION;
  1425. break;
  1426. }
  1427. //
  1428. // Tell the user we had a problem creating the device
  1429. //
  1430. MessageBox( m_hWnd, strMessage, CSimpleString( IDS_DOWNLOAD_MANAGER_TITLE, g_hInstance ), nIconId );
  1431. }
  1432. else if (S_OK == hr)
  1433. {
  1434. hr = CreateAndExecuteWizard();
  1435. }
  1436. //
  1437. // If we were cancelled, shut down the progress UI
  1438. //
  1439. else if (m_pWiaProgressDialog)
  1440. {
  1441. m_pWiaProgressDialog->Destroy();
  1442. m_pWiaProgressDialog = NULL;
  1443. }
  1444. //
  1445. // Make sure we kill this window, and thus, this thread.
  1446. //
  1447. PostMessage( m_hWnd, WM_CLOSE, 0, 0 );
  1448. return 0;
  1449. }
  1450. LRESULT CAcquisitionManagerControllerWindow::OnCreate( WPARAM, LPARAM lParam )
  1451. {
  1452. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::OnCreate"));
  1453. //
  1454. // Ensure the background thread was started
  1455. //
  1456. if (!m_hBackgroundThread || !m_pThreadMessageQueue)
  1457. {
  1458. WIA_ERROR((TEXT("There was an error starting the background thread")));
  1459. return -1;
  1460. }
  1461. //
  1462. // Make sure we got a valid lParam
  1463. //
  1464. LPCREATESTRUCT pCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
  1465. if (!pCreateStruct)
  1466. {
  1467. WIA_ERROR((TEXT("pCreateStruct was NULL")));
  1468. return -1;
  1469. }
  1470. //
  1471. // Get the event parameters
  1472. //
  1473. m_pEventParameters = reinterpret_cast<CEventParameters*>(pCreateStruct->lpCreateParams);
  1474. if (!m_pEventParameters)
  1475. {
  1476. WIA_ERROR((TEXT("m_pEventParameters was NULL")));
  1477. return -1;
  1478. }
  1479. SetForegroundWindow(m_hWnd);
  1480. //
  1481. // Center ourselves on the parent window
  1482. //
  1483. WiaUiUtil::CenterWindow( m_hWnd, m_pEventParameters->hwndParent );
  1484. PostMessage( m_hWnd, PWM_POSTINITIALIZE, 0, 0 );
  1485. return 0;
  1486. }
  1487. void CAcquisitionManagerControllerWindow::OnNotifyDownloadImage( UINT nMsg, CThreadNotificationMessage *pThreadNotificationMessage )
  1488. {
  1489. CDownloadImagesThreadNotifyMessage *pDownloadImageThreadNotifyMessage = dynamic_cast<CDownloadImagesThreadNotifyMessage*>(pThreadNotificationMessage);
  1490. if (pDownloadImageThreadNotifyMessage)
  1491. {
  1492. switch (pDownloadImageThreadNotifyMessage->Status())
  1493. {
  1494. case CDownloadImagesThreadNotifyMessage::End:
  1495. {
  1496. switch (pDownloadImageThreadNotifyMessage->Operation())
  1497. {
  1498. case CDownloadImagesThreadNotifyMessage::DownloadImage:
  1499. {
  1500. if (S_OK != pDownloadImageThreadNotifyMessage->hr())
  1501. {
  1502. m_nFailedImagesCount++;
  1503. }
  1504. }
  1505. break;
  1506. case CDownloadImagesThreadNotifyMessage::DownloadAll:
  1507. {
  1508. if (S_OK == pDownloadImageThreadNotifyMessage->hr())
  1509. {
  1510. m_DownloadedFileInformationList = pDownloadImageThreadNotifyMessage->DownloadedFileInformation();
  1511. }
  1512. else
  1513. {
  1514. m_DownloadedFileInformationList.Destroy();
  1515. }
  1516. }
  1517. break;
  1518. }
  1519. }
  1520. break;
  1521. case CDownloadImagesThreadNotifyMessage::Begin:
  1522. {
  1523. switch (pDownloadImageThreadNotifyMessage->Operation())
  1524. {
  1525. case CDownloadImagesThreadNotifyMessage::DownloadAll:
  1526. {
  1527. m_nFailedImagesCount = 0;
  1528. }
  1529. break;
  1530. }
  1531. }
  1532. break;
  1533. }
  1534. }
  1535. }
  1536. void CAcquisitionManagerControllerWindow::OnNotifyDownloadThumbnail( UINT nMsg, CThreadNotificationMessage *pThreadNotificationMessage )
  1537. {
  1538. WIA_PUSH_FUNCTION((TEXT("CAcquisitionManagerControllerWindow::OnNotifyDownloadThumbnail( %d, %p )"), nMsg, pThreadNotificationMessage ));
  1539. CDownloadThumbnailsThreadNotifyMessage *pDownloadThumbnailsThreadNotifyMessage= dynamic_cast<CDownloadThumbnailsThreadNotifyMessage*>(pThreadNotificationMessage);
  1540. if (pDownloadThumbnailsThreadNotifyMessage)
  1541. {
  1542. switch (pDownloadThumbnailsThreadNotifyMessage->Status())
  1543. {
  1544. case CDownloadThumbnailsThreadNotifyMessage::Begin:
  1545. {
  1546. }
  1547. break;
  1548. case CDownloadThumbnailsThreadNotifyMessage::Update:
  1549. {
  1550. }
  1551. break;
  1552. case CDownloadThumbnailsThreadNotifyMessage::End:
  1553. {
  1554. switch (pDownloadThumbnailsThreadNotifyMessage->Operation())
  1555. {
  1556. case CDownloadThumbnailsThreadNotifyMessage::DownloadThumbnail:
  1557. {
  1558. WIA_TRACE((TEXT("Handling CDownloadThumbnailsThreadNotifyMessage::DownloadThumbnail")));
  1559. //
  1560. // Find the item in the list
  1561. //
  1562. CWiaItem *pWiaItem = m_WiaItemList.Find( pDownloadThumbnailsThreadNotifyMessage->Cookie() );
  1563. if (pWiaItem)
  1564. {
  1565. //
  1566. // Set the flag that indicates we've tried this image already
  1567. //
  1568. pWiaItem->AttemptedThumbnailDownload(true);
  1569. //
  1570. // Make sure we have valid thumbnail data
  1571. //
  1572. if (pDownloadThumbnailsThreadNotifyMessage->BitmapData())
  1573. {
  1574. //
  1575. // Don't replace existing thumbnail data
  1576. //
  1577. if (!pWiaItem->BitmapData())
  1578. {
  1579. //
  1580. // Set the item's thumbnail data. Take ownership of the thumbnail data
  1581. //
  1582. WIA_TRACE((TEXT("Found the thumbnail for the item with the GIT cookie %08X"), pDownloadThumbnailsThreadNotifyMessage->Cookie() ));
  1583. pWiaItem->BitmapData(pDownloadThumbnailsThreadNotifyMessage->DetachBitmapData());
  1584. pWiaItem->Width(pDownloadThumbnailsThreadNotifyMessage->Width());
  1585. pWiaItem->Height(pDownloadThumbnailsThreadNotifyMessage->Height());
  1586. pWiaItem->BitmapDataLength(pDownloadThumbnailsThreadNotifyMessage->BitmapDataLength());
  1587. pWiaItem->ImageWidth(pDownloadThumbnailsThreadNotifyMessage->PictureWidth());
  1588. pWiaItem->ImageHeight(pDownloadThumbnailsThreadNotifyMessage->PictureHeight());
  1589. pWiaItem->AnnotationType(pDownloadThumbnailsThreadNotifyMessage->AnnotationType());
  1590. pWiaItem->DefExt(pDownloadThumbnailsThreadNotifyMessage->DefExt());
  1591. }
  1592. else
  1593. {
  1594. WIA_TRACE((TEXT("Already got the image data for item %08X!"), pDownloadThumbnailsThreadNotifyMessage->Cookie()));
  1595. }
  1596. }
  1597. else
  1598. {
  1599. WIA_ERROR((TEXT("pDownloadThumbnailsThreadNotifyMessage->BitmapData was NULL!")));
  1600. }
  1601. //
  1602. // Assign the default format
  1603. //
  1604. pWiaItem->DefaultFormat(pDownloadThumbnailsThreadNotifyMessage->DefaultFormat());
  1605. //
  1606. // Assign the access flags
  1607. //
  1608. pWiaItem->AccessRights(pDownloadThumbnailsThreadNotifyMessage->AccessRights());
  1609. //
  1610. // Make sure we discard rotation angles if rotation is not possible
  1611. //
  1612. pWiaItem->DiscardRotationIfNecessary();
  1613. }
  1614. else
  1615. {
  1616. WIA_ERROR((TEXT("Can't find %08X in the item list"), pDownloadThumbnailsThreadNotifyMessage->Cookie() ));
  1617. }
  1618. }
  1619. break;
  1620. }
  1621. }
  1622. break;
  1623. }
  1624. }
  1625. }
  1626. LRESULT CAcquisitionManagerControllerWindow::OnThreadNotification( WPARAM wParam, LPARAM lParam )
  1627. {
  1628. WIA_PUSH_FUNCTION((TEXT("CAcquisitionManagerControllerWindow::OnThreadNotification( %d, %08X )"), wParam, lParam ));
  1629. CThreadNotificationMessage *pThreadNotificationMessage = reinterpret_cast<CThreadNotificationMessage*>(lParam);
  1630. if (pThreadNotificationMessage)
  1631. {
  1632. switch (pThreadNotificationMessage->Message())
  1633. {
  1634. case TQ_DOWNLOADTHUMBNAIL:
  1635. OnNotifyDownloadThumbnail( static_cast<UINT>(wParam), pThreadNotificationMessage );
  1636. break;
  1637. case TQ_DOWNLOADIMAGE:
  1638. OnNotifyDownloadImage( static_cast<UINT>(wParam), pThreadNotificationMessage );
  1639. break;
  1640. }
  1641. //
  1642. // Notify all the registered windows
  1643. //
  1644. m_WindowList.SendMessage( m_nThreadNotificationMessage, wParam, lParam );
  1645. //
  1646. // Free the message structure
  1647. //
  1648. delete pThreadNotificationMessage;
  1649. }
  1650. return HANDLED_THREAD_MESSAGE;
  1651. }
  1652. void CAcquisitionManagerControllerWindow::AddNewItemToList( CGenericWiaEventHandler::CEventMessage *pEventMessage )
  1653. {
  1654. WIA_PUSHFUNCTION((TEXT("CAcquisitionManagerControllerWindow::AddNewItemToList")));
  1655. //
  1656. // Check to see if the item is already in our list
  1657. //
  1658. CWiaItem *pWiaItem = m_WiaItemList.Find(pEventMessage->FullItemName());
  1659. if (pWiaItem)
  1660. {
  1661. //
  1662. // If it is already in our list, just return.
  1663. //
  1664. return;
  1665. }
  1666. //
  1667. // Get an IWiaItem interface pointer for this item
  1668. //
  1669. CComPtr<IWiaItem> pItem;
  1670. HRESULT hr = m_pWiaItemRoot->FindItemByName( 0, CSimpleBStr(pEventMessage->FullItemName()).BString(), &pItem );
  1671. if (SUCCEEDED(hr) && pItem)
  1672. {
  1673. //
  1674. // Add it to the root of the item tree
  1675. //
  1676. m_WiaItemList.Add( NULL, new CWiaItem(pItem) );
  1677. }
  1678. }
  1679. void CAcquisitionManagerControllerWindow::RequestThumbnailForNewItem( CGenericWiaEventHandler::CEventMessage *pEventMessage )
  1680. {
  1681. WIA_PUSHFUNCTION((TEXT("CAcquisitionManagerControllerWindow::RequestThumbnailForNewItem")));
  1682. //
  1683. // Find the item in our list
  1684. //
  1685. CWiaItem *pWiaItem = m_WiaItemList.Find(pEventMessage->FullItemName());
  1686. if (pWiaItem)
  1687. {
  1688. //
  1689. // Add this item's cookie to an empty list
  1690. //
  1691. CSimpleDynamicArray<DWORD> Cookies;
  1692. Cookies.Append( pWiaItem->GlobalInterfaceTableCookie() );
  1693. if (Cookies.Size())
  1694. {
  1695. //
  1696. // Reset the cancel event
  1697. //
  1698. m_EventThumbnailCancel.Reset();
  1699. //
  1700. // Prepare and send the request
  1701. //
  1702. CDownloadThumbnailsThreadMessage *pDownloadThumbnailsThreadMessage = new CDownloadThumbnailsThreadMessage( m_hWnd, Cookies, m_EventThumbnailCancel.Event() );
  1703. if (pDownloadThumbnailsThreadMessage)
  1704. {
  1705. m_pThreadMessageQueue->Enqueue( pDownloadThumbnailsThreadMessage, CThreadMessageQueue::PriorityNormal );
  1706. }
  1707. }
  1708. }
  1709. }
  1710. LRESULT CAcquisitionManagerControllerWindow::OnEventNotification( WPARAM wParam, LPARAM lParam )
  1711. {
  1712. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::OnEventNotification"));
  1713. CGenericWiaEventHandler::CEventMessage *pEventMessage = reinterpret_cast<CGenericWiaEventHandler::CEventMessage *>(lParam);
  1714. if (pEventMessage)
  1715. {
  1716. //
  1717. // If we got an item created message, add the item to the list
  1718. //
  1719. if (pEventMessage->EventId() == WIA_EVENT_ITEM_CREATED)
  1720. {
  1721. AddNewItemToList( pEventMessage );
  1722. }
  1723. //
  1724. // On Disconnect, perform disconnection operations
  1725. //
  1726. else if (pEventMessage->EventId() == WIA_EVENT_DEVICE_DISCONNECTED)
  1727. {
  1728. DisplayDisconnectMessageAndExit();
  1729. }
  1730. //
  1731. // Propagate the message to all currently registered windows
  1732. //
  1733. m_WindowList.SendMessage( m_nWiaEventMessage, wParam, lParam );
  1734. //
  1735. // Make sure we ask for the new thumbnail *AFTER* we tell the views the item exists
  1736. //
  1737. if (pEventMessage->EventId() == WIA_EVENT_ITEM_CREATED)
  1738. {
  1739. RequestThumbnailForNewItem( pEventMessage );
  1740. }
  1741. //
  1742. // If this is a deleted item event, mark this item deleted
  1743. //
  1744. if (pEventMessage->EventId() == WIA_EVENT_ITEM_DELETED)
  1745. {
  1746. CWiaItem *pWiaItem = m_WiaItemList.Find(pEventMessage->FullItemName());
  1747. if (pWiaItem)
  1748. {
  1749. pWiaItem->MarkDeleted();
  1750. }
  1751. }
  1752. //
  1753. // On a connect event for this device, close the wizard
  1754. //
  1755. if (pEventMessage->EventId() == WIA_EVENT_DEVICE_CONNECTED)
  1756. {
  1757. if (m_bDisconnected && m_hWndWizard)
  1758. {
  1759. PropSheet_PressButton(m_hWndWizard,PSBTN_CANCEL);
  1760. }
  1761. }
  1762. //
  1763. // Free the event message
  1764. //
  1765. delete pEventMessage;
  1766. }
  1767. return HANDLED_EVENT_MESSAGE;
  1768. }
  1769. LRESULT CAcquisitionManagerControllerWindow::OnPowerBroadcast( WPARAM wParam, LPARAM lParam )
  1770. {
  1771. if (PBT_APMQUERYSUSPEND == wParam)
  1772. {
  1773. }
  1774. return TRUE;
  1775. }
  1776. LRESULT CALLBACK CAcquisitionManagerControllerWindow::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1777. {
  1778. SC_BEGIN_REFCOUNTED_MESSAGE_HANDLERS(CAcquisitionManagerControllerWindow)
  1779. {
  1780. SC_HANDLE_MESSAGE( WM_CREATE, OnCreate );
  1781. SC_HANDLE_MESSAGE( WM_DESTROY, OnDestroy );
  1782. SC_HANDLE_MESSAGE( PWM_POSTINITIALIZE, OnPostInitialize );
  1783. SC_HANDLE_MESSAGE( WM_POWERBROADCAST, OnPowerBroadcast );
  1784. }
  1785. SC_HANDLE_REGISTERED_MESSAGE(m_nThreadNotificationMessage,OnThreadNotification);
  1786. SC_HANDLE_REGISTERED_MESSAGE(m_nWiaEventMessage,OnEventNotification);
  1787. SC_END_MESSAGE_HANDLERS();
  1788. }
  1789. bool CAcquisitionManagerControllerWindow::Register( HINSTANCE hInstance )
  1790. {
  1791. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::Register"));
  1792. WNDCLASSEX WndClassEx;
  1793. memset( &WndClassEx, 0, sizeof(WndClassEx) );
  1794. WndClassEx.cbSize = sizeof(WNDCLASSEX);
  1795. WndClassEx.lpfnWndProc = WndProc;
  1796. WndClassEx.hInstance = hInstance;
  1797. WndClassEx.hCursor = LoadCursor(NULL,IDC_ARROW);
  1798. WndClassEx.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  1799. WndClassEx.lpszClassName = ACQUISITION_MANAGER_CONTROLLER_WINDOW_CLASSNAME;
  1800. BOOL bResult = (::RegisterClassEx(&WndClassEx) != 0);
  1801. DWORD dw = GetLastError();
  1802. return(bResult != 0);
  1803. }
  1804. HWND CAcquisitionManagerControllerWindow::Create( HINSTANCE hInstance, CEventParameters *pEventParameters )
  1805. {
  1806. return CreateWindowEx( 0, ACQUISITION_MANAGER_CONTROLLER_WINDOW_CLASSNAME,
  1807. TEXT("WIA Acquisition Manager Controller Window"),
  1808. WS_OVERLAPPEDWINDOW,
  1809. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  1810. NULL, NULL, hInstance, pEventParameters );
  1811. }
  1812. //
  1813. // Reference counting for our object
  1814. //
  1815. STDMETHODIMP_(ULONG) CAcquisitionManagerControllerWindow::AddRef(void)
  1816. {
  1817. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::AddRef"));
  1818. ULONG nRes = InterlockedIncrement(&m_cRef);
  1819. WIA_TRACE((TEXT("m_cRef: %d"),m_cRef));
  1820. return nRes;
  1821. }
  1822. STDMETHODIMP_(ULONG) CAcquisitionManagerControllerWindow::Release(void)
  1823. {
  1824. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::Release"));
  1825. if (InterlockedDecrement(&m_cRef)==0)
  1826. {
  1827. WIA_TRACE((TEXT("m_cRef: 0")));
  1828. //
  1829. // Cause this thread to exit
  1830. //
  1831. PostQuitMessage(0);
  1832. //
  1833. // Delete this instance of the wizard
  1834. //
  1835. delete this;
  1836. return 0;
  1837. }
  1838. WIA_TRACE((TEXT("m_cRef: %d"),m_cRef));
  1839. return(m_cRef);
  1840. }
  1841. HRESULT CAcquisitionManagerControllerWindow::QueryInterface( REFIID riid, void **ppvObject )
  1842. {
  1843. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::QueryInterface"));
  1844. HRESULT hr = S_OK;
  1845. *ppvObject = NULL;
  1846. if (IsEqualIID( riid, IID_IUnknown ))
  1847. {
  1848. *ppvObject = static_cast<IWizardSite*>(this);
  1849. reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();
  1850. }
  1851. else if (IsEqualIID( riid, IID_IWizardSite ))
  1852. {
  1853. *ppvObject = static_cast<IWizardSite*>(this);
  1854. reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();
  1855. }
  1856. else if (IsEqualIID( riid, IID_IServiceProvider ))
  1857. {
  1858. *ppvObject = static_cast<IServiceProvider*>(this);
  1859. reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();
  1860. }
  1861. else
  1862. {
  1863. WIA_PRINTGUID((riid,TEXT("Unknown interface")));
  1864. *ppvObject = NULL;
  1865. hr = E_NOINTERFACE;
  1866. }
  1867. return hr;
  1868. }
  1869. //
  1870. // IWizardSite
  1871. //
  1872. HRESULT CAcquisitionManagerControllerWindow::GetPreviousPage(HPROPSHEETPAGE *phPage)
  1873. {
  1874. if (!phPage)
  1875. {
  1876. return E_INVALIDARG;
  1877. }
  1878. *phPage = PropSheet_IndexToPage( m_hWndWizard, m_nUploadQueryPageIndex );
  1879. if (*phPage)
  1880. {
  1881. return S_OK;
  1882. }
  1883. return E_FAIL;
  1884. }
  1885. HRESULT CAcquisitionManagerControllerWindow::GetNextPage(HPROPSHEETPAGE *phPage)
  1886. {
  1887. if (!phPage)
  1888. {
  1889. return E_INVALIDARG;
  1890. }
  1891. *phPage = PropSheet_IndexToPage( m_hWndWizard, m_nFinishPageIndex );
  1892. if (*phPage)
  1893. {
  1894. return S_OK;
  1895. }
  1896. return E_FAIL;
  1897. }
  1898. HRESULT CAcquisitionManagerControllerWindow::GetCancelledPage(HPROPSHEETPAGE *phPage)
  1899. {
  1900. return GetNextPage(phPage);
  1901. }
  1902. //
  1903. // IServiceProvider
  1904. //
  1905. HRESULT CAcquisitionManagerControllerWindow::QueryService( REFGUID guidService, REFIID riid, void **ppv )
  1906. {
  1907. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::QueryService"));
  1908. WIA_PRINTGUID((guidService,TEXT("guidService")));
  1909. WIA_PRINTGUID((riid,TEXT("riid")));
  1910. if (!ppv)
  1911. {
  1912. return E_INVALIDARG;
  1913. }
  1914. //
  1915. // Initialize result
  1916. //
  1917. *ppv = NULL;
  1918. if (guidService == SID_PublishingWizard)
  1919. {
  1920. }
  1921. else
  1922. {
  1923. }
  1924. return E_FAIL;
  1925. }
  1926. static CSimpleString GetDisplayName( IShellItem *pShellItem )
  1927. {
  1928. CSimpleString strResult;
  1929. if (pShellItem)
  1930. {
  1931. LPOLESTR pszStr = NULL;
  1932. if (SUCCEEDED(pShellItem->GetDisplayName( SIGDN_FILESYSPATH, &pszStr )) && pszStr)
  1933. {
  1934. strResult = CSimpleStringConvert::NaturalString(CSimpleStringWide(pszStr));
  1935. CComPtr<IMalloc> pMalloc;
  1936. if (SUCCEEDED(SHGetMalloc(&pMalloc)))
  1937. {
  1938. pMalloc->Free( pszStr );
  1939. }
  1940. }
  1941. }
  1942. return strResult;
  1943. }
  1944. //
  1945. // These two functions are needed to use the generic event handler class
  1946. //
  1947. void DllAddRef(void)
  1948. {
  1949. #if !defined(DBG_GENERATE_PRETEND_EVENT)
  1950. _Module.Lock();
  1951. #endif
  1952. }
  1953. void DllRelease(void)
  1954. {
  1955. #if !defined(DBG_GENERATE_PRETEND_EVENT)
  1956. _Module.Unlock();
  1957. #endif
  1958. }