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.

631 lines
18 KiB

  1. /*****************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 2000
  4. *
  5. * TITLE: dll.cpp
  6. *
  7. * VERSION: 1.0, stolen from netplwiz
  8. *
  9. * AUTHOR: RickTu
  10. *
  11. * DATE: 10/12/00
  12. *
  13. * DESCRIPTION: DLL main & class factory code
  14. *
  15. *****************************************************************************/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. // shell/lib files look for this instance variable
  19. HINSTANCE g_hInst = 0;
  20. LONG g_cLocks = 0;
  21. ATOM g_cPreviewClassWnd = 0;
  22. // guids for our stuff
  23. // some guids are in shguidp.lib. We need to move them out of the shell depot into printscan at some point
  24. const GUID IID_ISetWaitEventForTesting = {0xd61e2fe1, 0x4af8, 0x4dbd, {0xb8, 0xad, 0xe7, 0xe0, 0x7a, 0xdc, 0xf9, 0x0f}};
  25. // DLL lifetime stuff
  26. STDAPI_(BOOL) DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
  27. {
  28. switch (dwReason)
  29. {
  30. case DLL_PROCESS_ATTACH:
  31. g_hInst = hinstDLL;
  32. SHFusionInitializeFromModuleID( hinstDLL, 123 );
  33. WIA_DEBUG_CREATE(hinstDLL);
  34. WIA_TRACE((TEXT("DLL_PROCESS_ATTACH called on photowiz.dll")));
  35. CPreviewWindow::s_RegisterClass(hinstDLL);
  36. break;
  37. case DLL_PROCESS_DETACH:
  38. WIA_TRACE((TEXT("DLL_PROCESS_DETACH called on photowiz.dll")));
  39. if (g_cPreviewClassWnd)
  40. {
  41. UnregisterClass( (LPCTSTR)g_cPreviewClassWnd, hinstDLL );
  42. }
  43. SHFusionUninitialize();
  44. WIA_REPORT_LEAKS();
  45. WIA_DEBUG_DESTROY();
  46. break;
  47. case DLL_THREAD_ATTACH:
  48. // WIA_TRACE((TEXT("DLL_THREAD_ATTACH called on photowiz.dll")));
  49. break;
  50. case DLL_THREAD_DETACH:
  51. // WIA_TRACE((TEXT("DLL_THREAD_DETACH called on photowiz.dll")));
  52. break;
  53. }
  54. return TRUE;
  55. }
  56. STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
  57. {
  58. return S_OK;
  59. }
  60. STDAPI DllCanUnloadNow()
  61. {
  62. HRESULT hr = (g_cLocks == 0) ? S_OK:S_FALSE;
  63. WIA_PUSH_FUNCTION_MASK((TRACE_REF_COUNTS, TEXT("DllCanUnloadNowRef, ref count is %d, hr = 0x%x"),g_cLocks,hr));
  64. WIA_RETURN_HR(hr);
  65. }
  66. STDAPI_(void) DllAddRef(void)
  67. {
  68. InterlockedIncrement(&g_cLocks);
  69. WIA_PUSH_FUNCTION_MASK((TRACE_REF_COUNTS, TEXT("DllAddRef, new ref count is %d"),g_cLocks));
  70. }
  71. STDAPI_(void) DllRelease(void)
  72. {
  73. InterlockedDecrement(&g_cLocks);
  74. WIA_PUSH_FUNCTION_MASK((TRACE_REF_COUNTS, TEXT("DllRelease, new ref count is %d"),g_cLocks));
  75. }
  76. /*****************************************************************************
  77. _CallRegInstall
  78. Helper function to allow us to invoke our .inf for installation...
  79. *****************************************************************************/
  80. HRESULT _CallRegInstall(LPCSTR szSection, BOOL bUninstall)
  81. {
  82. HRESULT hr = E_FAIL;
  83. HINSTANCE hinstAdvPack = NULL;
  84. hinstAdvPack = LoadLibrary( TEXT("advpack.dll") );
  85. if (hinstAdvPack)
  86. {
  87. REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall");
  88. if (pfnri)
  89. {
  90. STRENTRY seReg[] = {
  91. { "25", "%SystemRoot%" },
  92. { "11", "%SystemRoot%\\system32" },
  93. };
  94. STRTABLE stReg = { ARRAYSIZE(seReg), seReg };
  95. hr = pfnri(g_hInst, szSection, &stReg);
  96. if (bUninstall)
  97. {
  98. // ADVPACK will return E_UNEXPECTED if you try to uninstall
  99. // (which does a registry restore) on an INF section that was
  100. // never installed. We uninstall sections that may never have
  101. // been installed, so ignore this error
  102. hr = ((E_UNEXPECTED == hr) ? S_OK : hr);
  103. }
  104. }
  105. FreeLibrary(hinstAdvPack);
  106. }
  107. return hr;
  108. }
  109. STDAPI DllRegisterServer()
  110. {
  111. _CallRegInstall("UnregDll", TRUE);
  112. return _CallRegInstall("RegDll", FALSE);
  113. }
  114. STDAPI DllUnregisterServer()
  115. {
  116. return _CallRegInstall("UnregDll", TRUE);
  117. }
  118. HMODULE GetThreadHMODULE( LPTHREAD_START_ROUTINE pfnThreadProc )
  119. {
  120. MEMORY_BASIC_INFORMATION mbi;
  121. if (VirtualQuery(pfnThreadProc, &mbi, sizeof(mbi)))
  122. {
  123. TCHAR szModule[MAX_PATH];
  124. if (GetModuleFileName((HMODULE)mbi.AllocationBase, szModule, ARRAYSIZE(szModule)))
  125. {
  126. return LoadLibrary(szModule);
  127. }
  128. }
  129. return NULL;
  130. }
  131. STDAPI PPWCoInitialize(void)
  132. {
  133. HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
  134. if (FAILED(hr))
  135. {
  136. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
  137. }
  138. return hr;
  139. }
  140. /*****************************************************************************
  141. ClassFactory code
  142. <Notes>
  143. *****************************************************************************/
  144. //
  145. // This array holds information needed for ClassFacory.
  146. // OLEMISC_ flags are used by shembed and shocx.
  147. //
  148. // PERF: this table should be ordered in most-to-least used order
  149. //
  150. #define OIF_ALLOWAGGREGATION 0x0001
  151. CF_TABLE_BEGIN(g_ObjectInfo)
  152. CF_TABLE_ENTRY( &CLSID_PrintPhotosDropTarget, CPrintPhotosDropTarget_CreateInstance, COCREATEONLY),
  153. CF_TABLE_ENTRY( &CLSID_PrintPhotosWizard, CPrintPhotosWizard_CreateInstance, COCREATEONLY),
  154. CF_TABLE_END(g_ObjectInfo)
  155. // constructor for CObjectInfo.
  156. CObjectInfo::CObjectInfo(CLSID const* pclsidin, LPFNCREATEOBJINSTANCE pfnCreatein, IID const* piidIn,
  157. IID const* piidEventsIn, long lVersionIn, DWORD dwOleMiscFlagsIn,
  158. DWORD dwClassFactFlagsIn)
  159. {
  160. pclsid = pclsidin;
  161. pfnCreateInstance = pfnCreatein;
  162. piid = piidIn;
  163. piidEvents = piidEventsIn;
  164. lVersion = lVersionIn;
  165. dwOleMiscFlags = dwOleMiscFlagsIn;
  166. dwClassFactFlags = dwClassFactFlagsIn;
  167. }
  168. // static class factory (no allocs!)
  169. STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void **ppvObj)
  170. {
  171. WIA_PUSH_FUNCTION_MASK((TRACE_CF, TEXT("CClassFactory::QueryInterface")));
  172. if (!ppvObj)
  173. {
  174. return E_INVALIDARG;
  175. }
  176. if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
  177. {
  178. *ppvObj = (void *)GET_ICLASSFACTORY(this);
  179. DllAddRef();
  180. WIA_TRACE((TEXT("returning our class factory & S_OK")));
  181. return NOERROR;
  182. }
  183. *ppvObj = NULL;
  184. WIA_ERROR((TEXT("returning E_NOINTERFACE")));
  185. return E_NOINTERFACE;
  186. }
  187. STDMETHODIMP_(ULONG) CClassFactory::AddRef()
  188. {
  189. WIA_PUSH_FUNCTION_MASK((TRACE_CF, TEXT("CClassFactory::AddRef")));
  190. DllAddRef();
  191. return 2;
  192. }
  193. STDMETHODIMP_(ULONG) CClassFactory::Release()
  194. {
  195. WIA_PUSH_FUNCTION_MASK((TRACE_CF, TEXT("CClassFactory::Release")));
  196. DllRelease();
  197. return 1;
  198. }
  199. STDMETHODIMP CClassFactory::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
  200. {
  201. WIA_PUSH_FUNCTION_MASK((TRACE_CF, TEXT("CClassFactory::CreateInstance")));
  202. if (!ppv)
  203. {
  204. return E_INVALIDARG;
  205. }
  206. *ppv = NULL;
  207. if (punkOuter && !IsEqualIID(riid, IID_IUnknown))
  208. {
  209. // It is technically illegal to aggregate an object and request
  210. // any interface other than IUnknown. Enforce this.
  211. //
  212. WIA_ERROR((TEXT("we don't support aggregation, returning CLASS_E_NOAGGREGATION")));
  213. return CLASS_E_NOAGGREGATION;
  214. }
  215. else
  216. {
  217. LPOBJECTINFO pthisobj = (LPOBJECTINFO)this;
  218. if (punkOuter && !(pthisobj->dwClassFactFlags & OIF_ALLOWAGGREGATION))
  219. {
  220. WIA_ERROR((TEXT("we don't support aggregation, returning CLASS_E_NOAGGREGATION")));
  221. return CLASS_E_NOAGGREGATION;
  222. }
  223. IUnknown *punk;
  224. HRESULT hres = pthisobj->pfnCreateInstance(punkOuter, &punk, pthisobj);
  225. if (SUCCEEDED(hres))
  226. {
  227. hres = punk->QueryInterface(riid, ppv);
  228. punk->Release();
  229. }
  230. //_ASSERT(FAILED(hres) ? *ppv == NULL : TRUE);
  231. WIA_RETURN_HR(hres);
  232. }
  233. }
  234. STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
  235. {
  236. WIA_PUSH_FUNCTION_MASK((TRACE_CF, TEXT("CClassFactory::LockServer")));
  237. if (fLock)
  238. DllAddRef();
  239. else
  240. DllRelease();
  241. return S_OK;
  242. }
  243. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
  244. {
  245. WIA_PUSH_FUNCTION_MASK((TRACE_CF, TEXT("DllGetClassObject")));
  246. HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
  247. if (!ppv)
  248. {
  249. return E_INVALIDARG;
  250. }
  251. *ppv = NULL;
  252. if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
  253. {
  254. for (LPCOBJECTINFO pcls = g_ObjectInfo; pcls->pclsid; pcls++)
  255. {
  256. if (IsEqualGUID(rclsid, *(pcls->pclsid)))
  257. {
  258. *ppv = (void*)pcls;
  259. DllAddRef(); // class factory holds DLL ref count
  260. hr = S_OK;
  261. }
  262. }
  263. }
  264. #ifdef ATL_ENABLED
  265. if (hr == CLASS_E_CLASSNOTAVAILABLE)
  266. hr = AtlGetClassObject(rclsid, riid, ppv);
  267. #endif
  268. WIA_RETURN_HR(hr);
  269. }
  270. STDMETHODIMP UsePPWForPrintTo( LPCMINVOKECOMMANDINFO pCMI, IDataObject * pdo )
  271. {
  272. WIA_PUSH_FUNCTION_MASK((TRACE_PRINTTO, TEXT("UsePPWForPrintTo")));
  273. HRESULT hr = E_INVALIDARG;
  274. CSimpleString strPrinterName;
  275. if (pCMI &&
  276. ((pCMI->cbSize == sizeof(CMINVOKECOMMANDINFO)) || (pCMI->cbSize == sizeof(CMINVOKECOMMANDINFOEX))) &&
  277. pdo)
  278. {
  279. //
  280. // Keep a reference on the data object while we do our thing...
  281. //
  282. pdo->AddRef();
  283. //
  284. // Get printer to use...
  285. //
  286. if ( (pCMI->cbSize == sizeof(CMINVOKECOMMANDINFO)) ||
  287. (pCMI->cbSize == sizeof(CMINVOKECOMMANDINFOEX) && (!(pCMI->fMask & CMIC_MASK_UNICODE)))
  288. )
  289. {
  290. //
  291. // printer name is first token on the line, but it might be quoted...
  292. //
  293. CHAR szPrinterName[ MAX_PATH ];
  294. LPCSTR p = pCMI->lpParameters;
  295. INT i = 0;
  296. if (p)
  297. {
  298. //
  299. // skip beginning "'s, if any
  300. //
  301. while (*p && (*p == '\"'))
  302. {
  303. p++;
  304. }
  305. //
  306. // Copy first param, which would be printer name...
  307. //
  308. while ( *p && (*p != '\"') && (i <(ARRAYSIZE(szPrinterName)-1)) )
  309. {
  310. szPrinterName[i++] = *p;
  311. p++;
  312. }
  313. //
  314. // Ensure NULL termination
  315. //
  316. szPrinterName[i] = 0;
  317. }
  318. //
  319. // Convert into CSimpleString...
  320. strPrinterName.Assign(CSimpleStringConvert::NaturalString(CSimpleStringAnsi(szPrinterName)));
  321. }
  322. else if ((pCMI->cbSize == sizeof(CMINVOKECOMMANDINFOEX)) && (pCMI->fMask & CMIC_MASK_UNICODE))
  323. {
  324. LPCMINVOKECOMMANDINFOEX pCMIEX = (LPCMINVOKECOMMANDINFOEX) pCMI;
  325. WCHAR szwPrinterName[ MAX_PATH ];
  326. LPCWSTR p = pCMIEX->lpParametersW;
  327. INT i = 0;
  328. if (p)
  329. {
  330. //
  331. // skip beginning "'s, if any
  332. //
  333. while (*p && (*p == L'\"'))
  334. {
  335. p++;
  336. }
  337. //
  338. // Copy first param, which would be printer name...
  339. //
  340. while ( *p && (*p != L'\"') && (i <(ARRAYSIZE(szwPrinterName)-1)) )
  341. {
  342. szwPrinterName[i++] = *p;
  343. p++;
  344. }
  345. //
  346. // Ensure NULL termination
  347. //
  348. szwPrinterName[i] = 0;
  349. }
  350. //
  351. // Convert into CSimpleString...
  352. strPrinterName.Assign(CSimpleStringConvert::NaturalString(CSimpleStringWide(szwPrinterName)));
  353. }
  354. WIA_TRACE((TEXT("UsePPWForPrintTo - printer name to use is [%s]"),strPrinterName.String()));
  355. //
  356. // Create wizard object in UI less mode...
  357. //
  358. CWizardInfoBlob * pWizInfo = new CWizardInfoBlob( pdo, FALSE, TRUE );
  359. if (pWizInfo)
  360. {
  361. //
  362. // create full page print template...
  363. //
  364. WIA_TRACE((TEXT("UsePPWForPrintTo - constructing full page template")));
  365. pWizInfo->ConstructPrintToTemplate();
  366. //
  367. // Get a list of items...
  368. //
  369. WIA_TRACE((TEXT("UsePPWForPrintTo - adding items to print to pWizInfo")));
  370. pWizInfo->AddAllPhotosFromDataObject();
  371. //
  372. // Mark all items as selected for printing...
  373. //
  374. LONG nItemCount = pWizInfo->CountOfPhotos(FALSE);
  375. WIA_TRACE((TEXT("UsePPWForPrintTo - there are %d photos to be marked for printing"),nItemCount));
  376. //
  377. // Loop through all the photos and add them...
  378. //
  379. CListItem * pItem = NULL;
  380. for (INT i=0; i < nItemCount; i++)
  381. {
  382. //
  383. // Get the item in question
  384. //
  385. pItem = pWizInfo->GetListItem(i,FALSE);
  386. if (pItem)
  387. {
  388. pItem->SetSelectionState(TRUE);
  389. }
  390. }
  391. //
  392. // Set up for printing...
  393. //
  394. pWizInfo->SetPrinterToUse( strPrinterName.String() );
  395. HANDLE hPrinter = NULL;
  396. if (OpenPrinter( (LPTSTR)strPrinterName.String(), &hPrinter, NULL ) && hPrinter)
  397. {
  398. LONG lSize = DocumentProperties( NULL, hPrinter, (LPTSTR)strPrinterName.String(), NULL, NULL, 0 );
  399. if (lSize)
  400. {
  401. DEVMODE * pDevMode = (DEVMODE *) new BYTE[ lSize ];
  402. if (pDevMode)
  403. {
  404. if (IDOK == DocumentProperties( NULL, hPrinter, (LPTSTR)strPrinterName.String(), NULL, pDevMode, DM_OUT_BUFFER ))
  405. {
  406. WIA_TRACE((TEXT("UsePPWForPrintTo - setting devmode to use")));
  407. pWizInfo->SetDevModeToUse( pDevMode );
  408. }
  409. delete [] pDevMode;
  410. }
  411. }
  412. }
  413. if (hPrinter)
  414. {
  415. ClosePrinter(hPrinter);
  416. }
  417. //
  418. // Create HDC for the printer...
  419. //
  420. HDC hDC = CreateDC( TEXT("WINSPOOL"), pWizInfo->GetPrinterToUse(), NULL, pWizInfo->GetDevModeToUse() );
  421. if (hDC)
  422. {
  423. DOCINFO di = {0};
  424. di.cbSize = sizeof(DOCINFO);
  425. //
  426. // turn on ICM for this hDC
  427. //
  428. WIA_TRACE((TEXT("UsePPWForPrintTo - setting ICM mode on for hDC")));
  429. SetICMMode( hDC, ICM_ON );
  430. //
  431. // Lets use the template name for the document name...
  432. //
  433. CSimpleString strTitle;
  434. CTemplateInfo * pTemplateInfo = NULL;
  435. if (SUCCEEDED(pWizInfo->GetTemplateByIndex( 0, &pTemplateInfo)) && pTemplateInfo)
  436. {
  437. pTemplateInfo->GetTitle( &strTitle );
  438. }
  439. //
  440. // Let's remove the ':' at the end if there is one
  441. //
  442. INT iLen = strTitle.Length();
  443. if (iLen && (strTitle[(INT)iLen-1] == TEXT(':')))
  444. {
  445. strTitle.Truncate(iLen);
  446. }
  447. di.lpszDocName = strTitle;
  448. WIA_TRACE((TEXT("UsePPWForPrintTo - calling StartDoc")));
  449. if (StartDoc( hDC, &di ) > 0)
  450. {
  451. //
  452. // Loop through until we've printed all the photos...
  453. //
  454. INT iPageCount = 0;
  455. if (SUCCEEDED(hr = pWizInfo->GetCountOfPrintedPages( 0, &iPageCount )))
  456. {
  457. WIA_TRACE((TEXT("UsePPWForPrintTo - iPageCount is %d"),iPageCount));
  458. for (INT iPage = 0; iPage < iPageCount; iPage++)
  459. {
  460. //
  461. // Print the page...
  462. //
  463. if (StartPage( hDC ) > 0)
  464. {
  465. WIA_TRACE((TEXT("UsePPWForPrintTo - printing page %d"),iPage));
  466. hr = pWizInfo->RenderPrintedPage( 0, iPage, hDC, NULL, (float)0.0, NULL );
  467. EndPage( hDC );
  468. }
  469. else
  470. {
  471. WIA_ERROR((TEXT("UsePPWForPrintTo - StartPage failed w/GLE = %d"),GetLastError()));
  472. }
  473. }
  474. }
  475. WIA_TRACE((TEXT("UsePPWForPrintTo - calling EndDoc")));
  476. EndDoc( hDC );
  477. }
  478. DeleteDC( hDC );
  479. }
  480. delete pWizInfo;
  481. }
  482. pdo->Release();
  483. }
  484. WIA_RETURN_HR(hr);
  485. }