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.

2189 lines
81 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. case HRESULT_FROM_WIN32(ERROR_SERVICE_DISABLED):
  1423. strMessage = WiaUiUtil::GetErrorTextFromHResult(HRESULT_FROM_WIN32(ERROR_SERVICE_DISABLED));
  1424. nIconId = MB_ICONINFORMATION;
  1425. break;
  1426. default:
  1427. strMessage.LoadString( IDS_UNABLETOCREATE, g_hInstance );
  1428. nIconId = MB_ICONINFORMATION;
  1429. break;
  1430. }
  1431. //
  1432. // Tell the user we had a problem creating the device
  1433. //
  1434. MessageBox( m_hWnd, strMessage, CSimpleString( IDS_DOWNLOAD_MANAGER_TITLE, g_hInstance ), nIconId );
  1435. }
  1436. else if (S_OK == hr)
  1437. {
  1438. hr = CreateAndExecuteWizard();
  1439. }
  1440. //
  1441. // If we were cancelled, shut down the progress UI
  1442. //
  1443. else if (m_pWiaProgressDialog)
  1444. {
  1445. m_pWiaProgressDialog->Destroy();
  1446. m_pWiaProgressDialog = NULL;
  1447. }
  1448. //
  1449. // Make sure we kill this window, and thus, this thread.
  1450. //
  1451. PostMessage( m_hWnd, WM_CLOSE, 0, 0 );
  1452. return 0;
  1453. }
  1454. LRESULT CAcquisitionManagerControllerWindow::OnCreate( WPARAM, LPARAM lParam )
  1455. {
  1456. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::OnCreate"));
  1457. //
  1458. // Ensure the background thread was started
  1459. //
  1460. if (!m_hBackgroundThread || !m_pThreadMessageQueue)
  1461. {
  1462. WIA_ERROR((TEXT("There was an error starting the background thread")));
  1463. return -1;
  1464. }
  1465. //
  1466. // Make sure we got a valid lParam
  1467. //
  1468. LPCREATESTRUCT pCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
  1469. if (!pCreateStruct)
  1470. {
  1471. WIA_ERROR((TEXT("pCreateStruct was NULL")));
  1472. return -1;
  1473. }
  1474. //
  1475. // Get the event parameters
  1476. //
  1477. m_pEventParameters = reinterpret_cast<CEventParameters*>(pCreateStruct->lpCreateParams);
  1478. if (!m_pEventParameters)
  1479. {
  1480. WIA_ERROR((TEXT("m_pEventParameters was NULL")));
  1481. return -1;
  1482. }
  1483. SetForegroundWindow(m_hWnd);
  1484. //
  1485. // Center ourselves on the parent window
  1486. //
  1487. WiaUiUtil::CenterWindow( m_hWnd, m_pEventParameters->hwndParent );
  1488. PostMessage( m_hWnd, PWM_POSTINITIALIZE, 0, 0 );
  1489. return 0;
  1490. }
  1491. void CAcquisitionManagerControllerWindow::OnNotifyDownloadImage( UINT nMsg, CThreadNotificationMessage *pThreadNotificationMessage )
  1492. {
  1493. CDownloadImagesThreadNotifyMessage *pDownloadImageThreadNotifyMessage = dynamic_cast<CDownloadImagesThreadNotifyMessage*>(pThreadNotificationMessage);
  1494. if (pDownloadImageThreadNotifyMessage)
  1495. {
  1496. switch (pDownloadImageThreadNotifyMessage->Status())
  1497. {
  1498. case CDownloadImagesThreadNotifyMessage::End:
  1499. {
  1500. switch (pDownloadImageThreadNotifyMessage->Operation())
  1501. {
  1502. case CDownloadImagesThreadNotifyMessage::DownloadImage:
  1503. {
  1504. if (S_OK != pDownloadImageThreadNotifyMessage->hr())
  1505. {
  1506. m_nFailedImagesCount++;
  1507. }
  1508. }
  1509. break;
  1510. case CDownloadImagesThreadNotifyMessage::DownloadAll:
  1511. {
  1512. if (S_OK == pDownloadImageThreadNotifyMessage->hr())
  1513. {
  1514. m_DownloadedFileInformationList = pDownloadImageThreadNotifyMessage->DownloadedFileInformation();
  1515. }
  1516. else
  1517. {
  1518. m_DownloadedFileInformationList.Destroy();
  1519. }
  1520. }
  1521. break;
  1522. }
  1523. }
  1524. break;
  1525. case CDownloadImagesThreadNotifyMessage::Begin:
  1526. {
  1527. switch (pDownloadImageThreadNotifyMessage->Operation())
  1528. {
  1529. case CDownloadImagesThreadNotifyMessage::DownloadAll:
  1530. {
  1531. m_nFailedImagesCount = 0;
  1532. }
  1533. break;
  1534. }
  1535. }
  1536. break;
  1537. }
  1538. }
  1539. }
  1540. void CAcquisitionManagerControllerWindow::OnNotifyDownloadThumbnail( UINT nMsg, CThreadNotificationMessage *pThreadNotificationMessage )
  1541. {
  1542. WIA_PUSH_FUNCTION((TEXT("CAcquisitionManagerControllerWindow::OnNotifyDownloadThumbnail( %d, %p )"), nMsg, pThreadNotificationMessage ));
  1543. CDownloadThumbnailsThreadNotifyMessage *pDownloadThumbnailsThreadNotifyMessage= dynamic_cast<CDownloadThumbnailsThreadNotifyMessage*>(pThreadNotificationMessage);
  1544. if (pDownloadThumbnailsThreadNotifyMessage)
  1545. {
  1546. switch (pDownloadThumbnailsThreadNotifyMessage->Status())
  1547. {
  1548. case CDownloadThumbnailsThreadNotifyMessage::Begin:
  1549. {
  1550. }
  1551. break;
  1552. case CDownloadThumbnailsThreadNotifyMessage::Update:
  1553. {
  1554. }
  1555. break;
  1556. case CDownloadThumbnailsThreadNotifyMessage::End:
  1557. {
  1558. switch (pDownloadThumbnailsThreadNotifyMessage->Operation())
  1559. {
  1560. case CDownloadThumbnailsThreadNotifyMessage::DownloadThumbnail:
  1561. {
  1562. WIA_TRACE((TEXT("Handling CDownloadThumbnailsThreadNotifyMessage::DownloadThumbnail")));
  1563. //
  1564. // Find the item in the list
  1565. //
  1566. CWiaItem *pWiaItem = m_WiaItemList.Find( pDownloadThumbnailsThreadNotifyMessage->Cookie() );
  1567. if (pWiaItem)
  1568. {
  1569. //
  1570. // Set the flag that indicates we've tried this image already
  1571. //
  1572. pWiaItem->AttemptedThumbnailDownload(true);
  1573. //
  1574. // Make sure we have valid thumbnail data
  1575. //
  1576. if (pDownloadThumbnailsThreadNotifyMessage->BitmapData())
  1577. {
  1578. //
  1579. // Don't replace existing thumbnail data
  1580. //
  1581. if (!pWiaItem->BitmapData())
  1582. {
  1583. //
  1584. // Set the item's thumbnail data. Take ownership of the thumbnail data
  1585. //
  1586. WIA_TRACE((TEXT("Found the thumbnail for the item with the GIT cookie %08X"), pDownloadThumbnailsThreadNotifyMessage->Cookie() ));
  1587. pWiaItem->BitmapData(pDownloadThumbnailsThreadNotifyMessage->DetachBitmapData());
  1588. pWiaItem->Width(pDownloadThumbnailsThreadNotifyMessage->Width());
  1589. pWiaItem->Height(pDownloadThumbnailsThreadNotifyMessage->Height());
  1590. pWiaItem->BitmapDataLength(pDownloadThumbnailsThreadNotifyMessage->BitmapDataLength());
  1591. pWiaItem->ImageWidth(pDownloadThumbnailsThreadNotifyMessage->PictureWidth());
  1592. pWiaItem->ImageHeight(pDownloadThumbnailsThreadNotifyMessage->PictureHeight());
  1593. pWiaItem->AnnotationType(pDownloadThumbnailsThreadNotifyMessage->AnnotationType());
  1594. pWiaItem->DefExt(pDownloadThumbnailsThreadNotifyMessage->DefExt());
  1595. }
  1596. else
  1597. {
  1598. WIA_TRACE((TEXT("Already got the image data for item %08X!"), pDownloadThumbnailsThreadNotifyMessage->Cookie()));
  1599. }
  1600. }
  1601. else
  1602. {
  1603. WIA_ERROR((TEXT("pDownloadThumbnailsThreadNotifyMessage->BitmapData was NULL!")));
  1604. }
  1605. //
  1606. // Assign the default format
  1607. //
  1608. pWiaItem->DefaultFormat(pDownloadThumbnailsThreadNotifyMessage->DefaultFormat());
  1609. //
  1610. // Assign the access flags
  1611. //
  1612. pWiaItem->AccessRights(pDownloadThumbnailsThreadNotifyMessage->AccessRights());
  1613. //
  1614. // Make sure we discard rotation angles if rotation is not possible
  1615. //
  1616. pWiaItem->DiscardRotationIfNecessary();
  1617. }
  1618. else
  1619. {
  1620. WIA_ERROR((TEXT("Can't find %08X in the item list"), pDownloadThumbnailsThreadNotifyMessage->Cookie() ));
  1621. }
  1622. }
  1623. break;
  1624. }
  1625. }
  1626. break;
  1627. }
  1628. }
  1629. }
  1630. LRESULT CAcquisitionManagerControllerWindow::OnThreadNotification( WPARAM wParam, LPARAM lParam )
  1631. {
  1632. WIA_PUSH_FUNCTION((TEXT("CAcquisitionManagerControllerWindow::OnThreadNotification( %d, %08X )"), wParam, lParam ));
  1633. CThreadNotificationMessage *pThreadNotificationMessage = reinterpret_cast<CThreadNotificationMessage*>(lParam);
  1634. if (pThreadNotificationMessage)
  1635. {
  1636. switch (pThreadNotificationMessage->Message())
  1637. {
  1638. case TQ_DOWNLOADTHUMBNAIL:
  1639. OnNotifyDownloadThumbnail( static_cast<UINT>(wParam), pThreadNotificationMessage );
  1640. break;
  1641. case TQ_DOWNLOADIMAGE:
  1642. OnNotifyDownloadImage( static_cast<UINT>(wParam), pThreadNotificationMessage );
  1643. break;
  1644. }
  1645. //
  1646. // Notify all the registered windows
  1647. //
  1648. m_WindowList.SendMessage( m_nThreadNotificationMessage, wParam, lParam );
  1649. //
  1650. // Free the message structure
  1651. //
  1652. delete pThreadNotificationMessage;
  1653. }
  1654. return HANDLED_THREAD_MESSAGE;
  1655. }
  1656. void CAcquisitionManagerControllerWindow::AddNewItemToList( CGenericWiaEventHandler::CEventMessage *pEventMessage )
  1657. {
  1658. WIA_PUSHFUNCTION((TEXT("CAcquisitionManagerControllerWindow::AddNewItemToList")));
  1659. //
  1660. // Check to see if the item is already in our list
  1661. //
  1662. CWiaItem *pWiaItem = m_WiaItemList.Find(pEventMessage->FullItemName());
  1663. if (pWiaItem)
  1664. {
  1665. //
  1666. // If it is already in our list, just return.
  1667. //
  1668. return;
  1669. }
  1670. //
  1671. // Get an IWiaItem interface pointer for this item
  1672. //
  1673. CComPtr<IWiaItem> pItem;
  1674. HRESULT hr = m_pWiaItemRoot->FindItemByName( 0, CSimpleBStr(pEventMessage->FullItemName()).BString(), &pItem );
  1675. if (SUCCEEDED(hr) && pItem)
  1676. {
  1677. //
  1678. // Add it to the root of the item tree
  1679. //
  1680. m_WiaItemList.Add( NULL, new CWiaItem(pItem) );
  1681. }
  1682. }
  1683. void CAcquisitionManagerControllerWindow::RequestThumbnailForNewItem( CGenericWiaEventHandler::CEventMessage *pEventMessage )
  1684. {
  1685. WIA_PUSHFUNCTION((TEXT("CAcquisitionManagerControllerWindow::RequestThumbnailForNewItem")));
  1686. //
  1687. // Find the item in our list
  1688. //
  1689. CWiaItem *pWiaItem = m_WiaItemList.Find(pEventMessage->FullItemName());
  1690. if (pWiaItem)
  1691. {
  1692. //
  1693. // Add this item's cookie to an empty list
  1694. //
  1695. CSimpleDynamicArray<DWORD> Cookies;
  1696. Cookies.Append( pWiaItem->GlobalInterfaceTableCookie() );
  1697. if (Cookies.Size())
  1698. {
  1699. //
  1700. // Reset the cancel event
  1701. //
  1702. m_EventThumbnailCancel.Reset();
  1703. //
  1704. // Prepare and send the request
  1705. //
  1706. CDownloadThumbnailsThreadMessage *pDownloadThumbnailsThreadMessage = new CDownloadThumbnailsThreadMessage( m_hWnd, Cookies, m_EventThumbnailCancel.Event() );
  1707. if (pDownloadThumbnailsThreadMessage)
  1708. {
  1709. m_pThreadMessageQueue->Enqueue( pDownloadThumbnailsThreadMessage, CThreadMessageQueue::PriorityNormal );
  1710. }
  1711. }
  1712. }
  1713. }
  1714. LRESULT CAcquisitionManagerControllerWindow::OnEventNotification( WPARAM wParam, LPARAM lParam )
  1715. {
  1716. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::OnEventNotification"));
  1717. CGenericWiaEventHandler::CEventMessage *pEventMessage = reinterpret_cast<CGenericWiaEventHandler::CEventMessage *>(lParam);
  1718. if (pEventMessage)
  1719. {
  1720. //
  1721. // If we got an item created message, add the item to the list
  1722. //
  1723. if (pEventMessage->EventId() == WIA_EVENT_ITEM_CREATED)
  1724. {
  1725. AddNewItemToList( pEventMessage );
  1726. }
  1727. //
  1728. // On Disconnect, perform disconnection operations
  1729. //
  1730. else if (pEventMessage->EventId() == WIA_EVENT_DEVICE_DISCONNECTED)
  1731. {
  1732. DisplayDisconnectMessageAndExit();
  1733. }
  1734. //
  1735. // Propagate the message to all currently registered windows
  1736. //
  1737. m_WindowList.SendMessage( m_nWiaEventMessage, wParam, lParam );
  1738. //
  1739. // Make sure we ask for the new thumbnail *AFTER* we tell the views the item exists
  1740. //
  1741. if (pEventMessage->EventId() == WIA_EVENT_ITEM_CREATED)
  1742. {
  1743. RequestThumbnailForNewItem( pEventMessage );
  1744. }
  1745. //
  1746. // If this is a deleted item event, mark this item deleted
  1747. //
  1748. if (pEventMessage->EventId() == WIA_EVENT_ITEM_DELETED)
  1749. {
  1750. CWiaItem *pWiaItem = m_WiaItemList.Find(pEventMessage->FullItemName());
  1751. if (pWiaItem)
  1752. {
  1753. pWiaItem->MarkDeleted();
  1754. }
  1755. }
  1756. //
  1757. // On a connect event for this device, close the wizard
  1758. //
  1759. if (pEventMessage->EventId() == WIA_EVENT_DEVICE_CONNECTED)
  1760. {
  1761. if (m_bDisconnected && m_hWndWizard)
  1762. {
  1763. PropSheet_PressButton(m_hWndWizard,PSBTN_CANCEL);
  1764. }
  1765. }
  1766. //
  1767. // Free the event message
  1768. //
  1769. delete pEventMessage;
  1770. }
  1771. return HANDLED_EVENT_MESSAGE;
  1772. }
  1773. LRESULT CAcquisitionManagerControllerWindow::OnPowerBroadcast( WPARAM wParam, LPARAM lParam )
  1774. {
  1775. if (PBT_APMQUERYSUSPEND == wParam)
  1776. {
  1777. }
  1778. return TRUE;
  1779. }
  1780. LRESULT CALLBACK CAcquisitionManagerControllerWindow::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1781. {
  1782. SC_BEGIN_REFCOUNTED_MESSAGE_HANDLERS(CAcquisitionManagerControllerWindow)
  1783. {
  1784. SC_HANDLE_MESSAGE( WM_CREATE, OnCreate );
  1785. SC_HANDLE_MESSAGE( WM_DESTROY, OnDestroy );
  1786. SC_HANDLE_MESSAGE( PWM_POSTINITIALIZE, OnPostInitialize );
  1787. SC_HANDLE_MESSAGE( WM_POWERBROADCAST, OnPowerBroadcast );
  1788. }
  1789. SC_HANDLE_REGISTERED_MESSAGE(m_nThreadNotificationMessage,OnThreadNotification);
  1790. SC_HANDLE_REGISTERED_MESSAGE(m_nWiaEventMessage,OnEventNotification);
  1791. SC_END_MESSAGE_HANDLERS();
  1792. }
  1793. bool CAcquisitionManagerControllerWindow::Register( HINSTANCE hInstance )
  1794. {
  1795. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::Register"));
  1796. WNDCLASSEX WndClassEx;
  1797. memset( &WndClassEx, 0, sizeof(WndClassEx) );
  1798. WndClassEx.cbSize = sizeof(WNDCLASSEX);
  1799. WndClassEx.lpfnWndProc = WndProc;
  1800. WndClassEx.hInstance = hInstance;
  1801. WndClassEx.hCursor = LoadCursor(NULL,IDC_ARROW);
  1802. WndClassEx.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  1803. WndClassEx.lpszClassName = ACQUISITION_MANAGER_CONTROLLER_WINDOW_CLASSNAME;
  1804. BOOL bResult = (::RegisterClassEx(&WndClassEx) != 0);
  1805. DWORD dw = GetLastError();
  1806. return(bResult != 0);
  1807. }
  1808. HWND CAcquisitionManagerControllerWindow::Create( HINSTANCE hInstance, CEventParameters *pEventParameters )
  1809. {
  1810. return CreateWindowEx( 0, ACQUISITION_MANAGER_CONTROLLER_WINDOW_CLASSNAME,
  1811. TEXT("WIA Acquisition Manager Controller Window"),
  1812. WS_OVERLAPPEDWINDOW,
  1813. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  1814. NULL, NULL, hInstance, pEventParameters );
  1815. }
  1816. //
  1817. // Reference counting for our object
  1818. //
  1819. STDMETHODIMP_(ULONG) CAcquisitionManagerControllerWindow::AddRef(void)
  1820. {
  1821. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::AddRef"));
  1822. ULONG nRes = InterlockedIncrement(&m_cRef);
  1823. WIA_TRACE((TEXT("m_cRef: %d"),m_cRef));
  1824. return nRes;
  1825. }
  1826. STDMETHODIMP_(ULONG) CAcquisitionManagerControllerWindow::Release(void)
  1827. {
  1828. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::Release"));
  1829. if (InterlockedDecrement(&m_cRef)==0)
  1830. {
  1831. WIA_TRACE((TEXT("m_cRef: 0")));
  1832. //
  1833. // Cause this thread to exit
  1834. //
  1835. PostQuitMessage(0);
  1836. //
  1837. // Delete this instance of the wizard
  1838. //
  1839. delete this;
  1840. return 0;
  1841. }
  1842. WIA_TRACE((TEXT("m_cRef: %d"),m_cRef));
  1843. return(m_cRef);
  1844. }
  1845. HRESULT CAcquisitionManagerControllerWindow::QueryInterface( REFIID riid, void **ppvObject )
  1846. {
  1847. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::QueryInterface"));
  1848. HRESULT hr = S_OK;
  1849. *ppvObject = NULL;
  1850. if (IsEqualIID( riid, IID_IUnknown ))
  1851. {
  1852. *ppvObject = static_cast<IWizardSite*>(this);
  1853. reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();
  1854. }
  1855. else if (IsEqualIID( riid, IID_IWizardSite ))
  1856. {
  1857. *ppvObject = static_cast<IWizardSite*>(this);
  1858. reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();
  1859. }
  1860. else if (IsEqualIID( riid, IID_IServiceProvider ))
  1861. {
  1862. *ppvObject = static_cast<IServiceProvider*>(this);
  1863. reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();
  1864. }
  1865. else
  1866. {
  1867. WIA_PRINTGUID((riid,TEXT("Unknown interface")));
  1868. *ppvObject = NULL;
  1869. hr = E_NOINTERFACE;
  1870. }
  1871. return hr;
  1872. }
  1873. //
  1874. // IWizardSite
  1875. //
  1876. HRESULT CAcquisitionManagerControllerWindow::GetPreviousPage(HPROPSHEETPAGE *phPage)
  1877. {
  1878. if (!phPage)
  1879. {
  1880. return E_INVALIDARG;
  1881. }
  1882. *phPage = PropSheet_IndexToPage( m_hWndWizard, m_nUploadQueryPageIndex );
  1883. if (*phPage)
  1884. {
  1885. return S_OK;
  1886. }
  1887. return E_FAIL;
  1888. }
  1889. HRESULT CAcquisitionManagerControllerWindow::GetNextPage(HPROPSHEETPAGE *phPage)
  1890. {
  1891. if (!phPage)
  1892. {
  1893. return E_INVALIDARG;
  1894. }
  1895. *phPage = PropSheet_IndexToPage( m_hWndWizard, m_nFinishPageIndex );
  1896. if (*phPage)
  1897. {
  1898. return S_OK;
  1899. }
  1900. return E_FAIL;
  1901. }
  1902. HRESULT CAcquisitionManagerControllerWindow::GetCancelledPage(HPROPSHEETPAGE *phPage)
  1903. {
  1904. return GetNextPage(phPage);
  1905. }
  1906. //
  1907. // IServiceProvider
  1908. //
  1909. HRESULT CAcquisitionManagerControllerWindow::QueryService( REFGUID guidService, REFIID riid, void **ppv )
  1910. {
  1911. WIA_PUSHFUNCTION(TEXT("CAcquisitionManagerControllerWindow::QueryService"));
  1912. WIA_PRINTGUID((guidService,TEXT("guidService")));
  1913. WIA_PRINTGUID((riid,TEXT("riid")));
  1914. if (!ppv)
  1915. {
  1916. return E_INVALIDARG;
  1917. }
  1918. //
  1919. // Initialize result
  1920. //
  1921. *ppv = NULL;
  1922. if (guidService == SID_PublishingWizard)
  1923. {
  1924. }
  1925. else
  1926. {
  1927. }
  1928. return E_FAIL;
  1929. }
  1930. static CSimpleString GetDisplayName( IShellItem *pShellItem )
  1931. {
  1932. CSimpleString strResult;
  1933. if (pShellItem)
  1934. {
  1935. LPOLESTR pszStr = NULL;
  1936. if (SUCCEEDED(pShellItem->GetDisplayName( SIGDN_FILESYSPATH, &pszStr )) && pszStr)
  1937. {
  1938. strResult = CSimpleStringConvert::NaturalString(CSimpleStringWide(pszStr));
  1939. CComPtr<IMalloc> pMalloc;
  1940. if (SUCCEEDED(SHGetMalloc(&pMalloc)))
  1941. {
  1942. pMalloc->Free( pszStr );
  1943. }
  1944. }
  1945. }
  1946. return strResult;
  1947. }
  1948. //
  1949. // These two functions are needed to use the generic event handler class
  1950. //
  1951. void DllAddRef(void)
  1952. {
  1953. #if !defined(DBG_GENERATE_PRETEND_EVENT)
  1954. _Module.Lock();
  1955. #endif
  1956. }
  1957. void DllRelease(void)
  1958. {
  1959. #if !defined(DBG_GENERATE_PRETEND_EVENT)
  1960. _Module.Unlock();
  1961. #endif
  1962. }