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.

637 lines
16 KiB

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright 1998 - 2003 Microsoft Corporation. All Rights Reserved.
  7. //
  8. // FILE: Intrface.cpp
  9. //
  10. //
  11. // PURPOSE: Implementation of interface for WinXP PScript5 Standard
  12. // UI Replacement plug-in.
  13. //
  14. //
  15. // Functions:
  16. //
  17. //
  18. //
  19. //
  20. // PLATFORMS: Windows 2000, Windows XP, Windows Server 2003
  21. //
  22. //
  23. #include "precomp.h"
  24. #include <INITGUID.H>
  25. #include <PRCOMOEM.H>
  26. #include "oemui.h"
  27. #include "debug.h"
  28. #include "intrface.h"
  29. // StrSafe.h needs to be included last
  30. // to disallow bad string functions.
  31. #include <STRSAFE.H>
  32. ////////////////////////////////////////////////////////
  33. // Internal Constants
  34. ////////////////////////////////////////////////////////
  35. //
  36. // List all of the supported Driver UI Helper interface IIDs from the
  37. // latest to the oldest, that's the order we will query for the
  38. // the Driver UI Helper interface to use.
  39. //
  40. const IID *Helper_IIDs[] =
  41. {
  42. &IID_IPrintCoreUI2,
  43. &IID_IPrintOemDriverUI,
  44. };
  45. const NUM_HELPER_IIDs = (sizeof(Helper_IIDs)/sizeof(Helper_IIDs[0]));
  46. ////////////////////////////////////////////////////////
  47. // Internal Globals
  48. ////////////////////////////////////////////////////////
  49. static long g_cComponents = 0 ; // Count of active components
  50. static long g_cServerLocks = 0 ; // Count of locks
  51. ////////////////////////////////////////////////////////////////////////////////
  52. //
  53. // IOemUI2 body
  54. //
  55. IOemUI2::IOemUI2()
  56. {
  57. VERBOSE(DLLTEXT("IOemUI2:IOemUI2() default constructor called.\r\n\r\n"));
  58. // Init ref count to 1 on creation, since AddRef() is implied.
  59. m_cRef = 1;
  60. // The default for UI Hiding is FALSE, since HideStandardUI method
  61. // will only be called by Driver UIs that support it.
  62. // Older Driver UIs don't know about this method and won't call us.
  63. m_bHidingStandardUI = FALSE;
  64. // Increment component count.
  65. InterlockedIncrement(&g_cComponents);
  66. }
  67. IOemUI2::~IOemUI2()
  68. {
  69. VERBOSE(DLLTEXT("IOemUI2:~IOemUI2() destructor called.\r\n\r\n"));
  70. // If this instance of the object is being deleted, then the reference
  71. // count should be zero.
  72. assert(0 == m_cRef);
  73. // Decrement component count.
  74. InterlockedDecrement(&g_cComponents);
  75. }
  76. HRESULT __stdcall IOemUI2::QueryInterface(const IID& iid, void** ppv)
  77. {
  78. VERBOSE(DLLTEXT("IOemUI2:QueryInterface entry.\r\n\r\n"));
  79. #if DBG
  80. TCHAR szIID[80] = {0};
  81. StringFromGUID2(iid, szIID, COUNTOF(szIID)); // can not fail!
  82. #endif
  83. // Determine what object to return, if any.
  84. if(iid == IID_IUnknown)
  85. {
  86. *ppv = static_cast<IUnknown*>(this);
  87. }
  88. else if(iid == IID_IPrintOemUI2)
  89. {
  90. *ppv = static_cast<IPrintOemUI2*>(this);
  91. }
  92. else if(iid == IID_IPrintOemUI)
  93. {
  94. *ppv = static_cast<IPrintOemUI*>(this);
  95. }
  96. else
  97. {
  98. // Interface not supported.
  99. #if DBG
  100. VERBOSE(DLLTEXT("IOemUI2::QueryInterface %s not supported.\r\n"), szIID);
  101. #endif
  102. *ppv = NULL ;
  103. return E_NOINTERFACE ;
  104. }
  105. #if DBG
  106. VERBOSE(DLLTEXT("IOemUI2::QueryInterface returning pointer to %s.\r\n"), szIID);
  107. #endif
  108. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  109. return S_OK ;
  110. }
  111. ULONG __stdcall IOemUI2::AddRef()
  112. {
  113. VERBOSE(DLLTEXT("IOemUI2:AddRef entry.\r\n"));
  114. return InterlockedIncrement(&m_cRef) ;
  115. }
  116. ULONG __stdcall IOemUI2::Release()
  117. {
  118. VERBOSE(DLLTEXT("IOemUI2:Release entry.\r\n"));
  119. ASSERT( 0 != m_cRef);
  120. ULONG cRef = InterlockedDecrement(&m_cRef);
  121. if (0 == cRef)
  122. {
  123. delete this;
  124. }
  125. return cRef;
  126. }
  127. HRESULT __stdcall IOemUI2::PublishDriverInterface(
  128. IUnknown *pIUnknown)
  129. {
  130. HRESULT hResult = S_OK;
  131. VERBOSE(DLLTEXT("IOemUI2:PublishDriverInterface entry.\r\n"));
  132. // Core Driver UI shouldn't call us more than once if we were successful.
  133. // Thus, if m_Helper is already valid, we shouldn't be getting called.
  134. ASSERT(!m_Helper.IsValid());
  135. // Need to store pointer to Driver Helper functions, if we already haven't.
  136. if (!m_Helper.IsValid())
  137. {
  138. PVOID pHelper = NULL;
  139. // Try to get the newest version fo the Helper function
  140. // that Driver UI supports.
  141. hResult = E_FAIL;
  142. for(DWORD dwIndex = 0; !SUCCEEDED(hResult) && (dwIndex < NUM_HELPER_IIDs); ++dwIndex)
  143. {
  144. // Query Driver UI for Helper interface.
  145. hResult = pIUnknown->QueryInterface(*Helper_IIDs[dwIndex], &pHelper);
  146. if(SUCCEEDED(hResult))
  147. {
  148. // INVARIANT: we got a Helper interface.
  149. // Store Helper interface.
  150. m_Helper.Assign(*Helper_IIDs[dwIndex], pHelper);
  151. }
  152. }
  153. }
  154. return hResult;
  155. }
  156. HRESULT __stdcall IOemUI2::GetInfo(
  157. DWORD dwMode,
  158. PVOID pBuffer,
  159. DWORD cbSize,
  160. PDWORD pcbNeeded)
  161. {
  162. VERBOSE(DLLTEXT("IOemUI2::GetInfo(%d) entry.\r\r\n"), dwMode);
  163. // Validate parameters.
  164. if( (NULL == pcbNeeded)
  165. ||
  166. ( (OEMGI_GETSIGNATURE != dwMode)
  167. &&
  168. (OEMGI_GETVERSION != dwMode)
  169. &&
  170. (OEMGI_GETPUBLISHERINFO != dwMode)
  171. )
  172. )
  173. {
  174. WARNING(DLLTEXT("IOemUI2::GetInfo() exit pcbNeeded is NULL! ERROR_INVALID_PARAMETER\r\r\n"));
  175. SetLastError(ERROR_INVALID_PARAMETER);
  176. return E_FAIL;
  177. }
  178. // Set expected buffer size and number of bytes written.
  179. *pcbNeeded = sizeof(DWORD);
  180. // Check buffer size is sufficient.
  181. if((cbSize < *pcbNeeded) || (NULL == pBuffer))
  182. {
  183. WARNING(DLLTEXT("IOemUI2::GetInfo() exit insufficient buffer!\r\r\n"));
  184. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  185. return E_FAIL;
  186. }
  187. switch(dwMode)
  188. {
  189. // OEM DLL Signature
  190. case OEMGI_GETSIGNATURE:
  191. *(PDWORD)pBuffer = OEM_SIGNATURE;
  192. break;
  193. // OEM DLL version
  194. case OEMGI_GETVERSION:
  195. *(PDWORD)pBuffer = OEM_VERSION;
  196. break;
  197. // dwMode not supported.
  198. default:
  199. // Set written bytes to zero since nothing was written.
  200. WARNING(DLLTEXT("IOemUI2::GetInfo() exit mode not supported.\r\r\n"));
  201. *pcbNeeded = 0;
  202. SetLastError(ERROR_NOT_SUPPORTED);
  203. return E_FAIL;
  204. }
  205. VERBOSE(DLLTEXT("IOemUI2::GetInfo() exit S_OK, (*pBuffer is %#x).\r\r\n"), *(PDWORD)pBuffer);
  206. return S_OK;
  207. }
  208. HRESULT __stdcall IOemUI2::DevMode(
  209. DWORD dwMode,
  210. POEMDMPARAM pOemDMParam)
  211. {
  212. VERBOSE(DLLTEXT("IOemUI2:DevMode(%d, %#x) entry.\r\n"), dwMode, pOemDMParam);
  213. return hrOEMDevMode(dwMode, pOemDMParam);
  214. }
  215. HRESULT __stdcall IOemUI2::CommonUIProp(
  216. DWORD dwMode,
  217. POEMCUIPPARAM pOemCUIPParam)
  218. {
  219. VERBOSE(DLLTEXT("IOemUI2:CommonUIProp entry.\r\n"));
  220. return hrOEMPropertyPage(dwMode, pOemCUIPParam);
  221. }
  222. HRESULT __stdcall IOemUI2::DocumentPropertySheets(
  223. PPROPSHEETUI_INFO pPSUIInfo,
  224. LPARAM lParam)
  225. {
  226. VERBOSE(DLLTEXT("IOemUI2:DocumentPropertySheets entry.\r\n"));
  227. return hrOEMDocumentPropertySheets(pPSUIInfo,
  228. lParam,
  229. m_Helper,
  230. &m_Features,
  231. m_bHidingStandardUI);
  232. }
  233. HRESULT __stdcall IOemUI2::DevicePropertySheets(
  234. PPROPSHEETUI_INFO pPSUIInfo,
  235. LPARAM lParam)
  236. {
  237. VERBOSE(DLLTEXT("IOemUI2:DevicePropertySheets entry.\r\n"));
  238. return hrOEMDevicePropertySheets(pPSUIInfo,
  239. lParam,
  240. m_Helper,
  241. &m_Features,
  242. m_bHidingStandardUI);
  243. }
  244. HRESULT __stdcall IOemUI2::DeviceCapabilities(
  245. POEMUIOBJ poemuiobj,
  246. HANDLE hPrinter,
  247. PWSTR pDeviceName,
  248. WORD wCapability,
  249. PVOID pOutput,
  250. PDEVMODE pPublicDM,
  251. PVOID pOEMDM,
  252. DWORD dwOld,
  253. DWORD *dwResult)
  254. {
  255. VERBOSE(DLLTEXT("IOemUI2:DeviceCapabilities entry.\r\n"));
  256. return E_NOTIMPL;
  257. }
  258. HRESULT __stdcall IOemUI2::DevQueryPrintEx(
  259. POEMUIOBJ poemuiobj,
  260. PDEVQUERYPRINT_INFO pDQPInfo,
  261. PDEVMODE pPublicDM,
  262. PVOID pOEMDM)
  263. {
  264. VERBOSE(DLLTEXT("IOemUI2:DevQueryPrintEx entry.\r\n"));
  265. return E_NOTIMPL;
  266. }
  267. HRESULT __stdcall IOemUI2::UpgradePrinter(
  268. DWORD dwLevel,
  269. PBYTE pDriverUpgradeInfo)
  270. {
  271. VERBOSE(DLLTEXT("IOemUI2:UpgradePrinter entry.\r\n"));
  272. return E_NOTIMPL;
  273. }
  274. HRESULT __stdcall IOemUI2::PrinterEvent(
  275. PWSTR pPrinterName,
  276. INT iDriverEvent,
  277. DWORD dwFlags,
  278. LPARAM lParam)
  279. {
  280. VERBOSE(DLLTEXT("IOemUI2:PrinterEvent entry.\r\n"));
  281. return E_NOTIMPL;
  282. }
  283. HRESULT __stdcall IOemUI2::DriverEvent(
  284. DWORD dwDriverEvent,
  285. DWORD dwLevel,
  286. LPBYTE pDriverInfo,
  287. LPARAM lParam)
  288. {
  289. VERBOSE(DLLTEXT("IOemUI2:DriverEvent entry.\r\n"));
  290. return E_NOTIMPL;
  291. };
  292. HRESULT __stdcall IOemUI2::QueryColorProfile(
  293. HANDLE hPrinter,
  294. POEMUIOBJ poemuiobj,
  295. PDEVMODE pPublicDM,
  296. PVOID pOEMDM,
  297. ULONG ulQueryMode,
  298. VOID *pvProfileData,
  299. ULONG *pcbProfileData,
  300. FLONG *pflProfileData)
  301. {
  302. VERBOSE(DLLTEXT("IOemUI2:QueryColorProfile entry.\r\n"));
  303. return E_NOTIMPL;
  304. };
  305. HRESULT __stdcall IOemUI2::FontInstallerDlgProc(
  306. HWND hWnd,
  307. UINT usMsg,
  308. WPARAM wParam,
  309. LPARAM lParam)
  310. {
  311. VERBOSE(DLLTEXT("IOemUI2:FontInstallerDlgProc entry.\r\n"));
  312. return E_NOTIMPL;
  313. };
  314. HRESULT __stdcall IOemUI2::UpdateExternalFonts(
  315. HANDLE hPrinter,
  316. HANDLE hHeap,
  317. PWSTR pwstrCartridges)
  318. {
  319. VERBOSE(DLLTEXT("IOemUI2:UpdateExternalFonts entry.\r\n"));
  320. return E_NOTIMPL;
  321. }
  322. // *********** IPrintOEMUI2 FUNCTIONS ****************
  323. //
  324. // QueryJobAttribtues
  325. //
  326. HRESULT __stdcall IOemUI2::QueryJobAttributes(
  327. HANDLE hPrinter,
  328. PDEVMODE pDevmode,
  329. DWORD dwLevel,
  330. LPBYTE lpAttributeInfo)
  331. {
  332. TERSE(DLLTEXT("IOemUI2:QueryJobAttributes entry.\r\n"));
  333. return E_NOTIMPL;
  334. }
  335. //
  336. // Hide Standard UI
  337. //
  338. HRESULT __stdcall IOemUI2::HideStandardUI(
  339. DWORD dwMode)
  340. {
  341. HRESULT hrReturn = E_NOTIMPL;
  342. TERSE(DLLTEXT("IOemUI2:HideStandardUI entry.\r\n"));
  343. switch(dwMode)
  344. {
  345. // By returning S_OK for both OEMCUIP_DOCPROP and OEMCUIP_PRNPROP,
  346. // we will hide the Standard UI for both Document Properties,
  347. // and Device Properties.
  348. // To not hide one or both, return E_NOTIMPL instead of S_OK,
  349. case OEMCUIP_DOCPROP:
  350. case OEMCUIP_PRNPROP:
  351. // Flag that we are hiding the Standard UI.
  352. // This is so we can tell easily between Driver UI
  353. // that supports HideStandardUI (such as WinXP PS UI),
  354. // or ones that don't (such as Win2K PS or Unidrv UI).
  355. m_bHidingStandardUI = TRUE;
  356. hrReturn = S_OK;
  357. break;
  358. }
  359. return hrReturn;
  360. }
  361. //
  362. // DocumentEvent
  363. //
  364. HRESULT __stdcall IOemUI2::DocumentEvent(
  365. HANDLE hPrinter,
  366. HDC hdc,
  367. INT iEsc,
  368. ULONG cbIn,
  369. PVOID pbIn,
  370. ULONG cbOut,
  371. PVOID pbOut,
  372. PINT piResult)
  373. {
  374. return E_NOTIMPL;
  375. }
  376. ////////////////////////////////////////////////////////////////////////////////
  377. //
  378. // oem class factory
  379. //
  380. class IOemCF : public IClassFactory
  381. {
  382. public:
  383. // *** IUnknown methods ***
  384. STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
  385. STDMETHOD_(ULONG,AddRef) (THIS);
  386. STDMETHOD_(ULONG,Release) (THIS);
  387. // *** IClassFactory methods ***
  388. STDMETHOD(CreateInstance) (THIS_
  389. LPUNKNOWN pUnkOuter,
  390. REFIID riid,
  391. LPVOID FAR* ppvObject);
  392. STDMETHOD(LockServer) (THIS_ BOOL bLock);
  393. // Constructor
  394. IOemCF(): m_cRef(1) { };
  395. ~IOemCF() { };
  396. protected:
  397. LONG m_cRef;
  398. };
  399. ///////////////////////////////////////////////////////////
  400. //
  401. // Class factory body
  402. //
  403. HRESULT __stdcall IOemCF::QueryInterface(const IID& iid, void** ppv)
  404. {
  405. if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
  406. {
  407. *ppv = static_cast<IOemCF*>(this) ;
  408. }
  409. else
  410. {
  411. #if DBG
  412. TCHAR szOutput[80] = {0};
  413. StringFromGUID2(iid, szOutput, COUNTOF(szOutput)); // can not fail!
  414. WARNING(DLLTEXT("IOemCF::QueryInterface %s not supported.\r\n"), szOutput);
  415. #endif
  416. *ppv = NULL ;
  417. return E_NOINTERFACE ;
  418. }
  419. reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
  420. return S_OK ;
  421. }
  422. ULONG __stdcall IOemCF::AddRef()
  423. {
  424. return InterlockedIncrement(&m_cRef) ;
  425. }
  426. ULONG __stdcall IOemCF::Release()
  427. {
  428. ASSERT( 0 != m_cRef);
  429. ULONG cRef = InterlockedDecrement(&m_cRef);
  430. if (0 == cRef)
  431. {
  432. delete this;
  433. }
  434. return cRef;
  435. }
  436. // IClassFactory implementation
  437. HRESULT __stdcall IOemCF::CreateInstance(IUnknown* pUnknownOuter,
  438. const IID& iid,
  439. void** ppv)
  440. {
  441. //DbgPrint(DLLTEXT("Class factory:\t\tCreate component.")) ;
  442. // Cannot aggregate.
  443. if (pUnknownOuter != NULL)
  444. {
  445. return CLASS_E_NOAGGREGATION ;
  446. }
  447. // Create component.
  448. IOemUI2* pOemCB = new IOemUI2 ;
  449. if (pOemCB == NULL)
  450. {
  451. return E_OUTOFMEMORY ;
  452. }
  453. // Get the requested interface.
  454. HRESULT hr = pOemCB->QueryInterface(iid, ppv) ;
  455. // Release the IUnknown pointer.
  456. // (If QueryInterface failed, component will delete itself.)
  457. pOemCB->Release() ;
  458. return hr ;
  459. }
  460. // LockServer
  461. HRESULT __stdcall IOemCF::LockServer(BOOL bLock)
  462. {
  463. if (bLock)
  464. {
  465. InterlockedIncrement(&g_cServerLocks) ;
  466. }
  467. else
  468. {
  469. InterlockedDecrement(&g_cServerLocks) ;
  470. }
  471. return S_OK ;
  472. }
  473. ///////////////////////////////////////////////////////////
  474. //
  475. // Exported functions
  476. //
  477. // Can DLL unload now?
  478. //
  479. STDAPI DllCanUnloadNow()
  480. {
  481. //
  482. // To avoid leaving OEM DLL still in memory when Unidrv or Pscript drivers
  483. // are unloaded, Unidrv and Pscript driver ignore the return value of
  484. // DllCanUnloadNow of the OEM DLL, and always call FreeLibrary on the OEMDLL.
  485. //
  486. // If OEM DLL spins off a working thread that also uses the OEM DLL, the
  487. // thread needs to call LoadLibrary and FreeLibraryAndExitThread, otherwise
  488. // it may crash after Unidrv or Pscript calls FreeLibrary.
  489. //
  490. if ((g_cComponents == 0) && (g_cServerLocks == 0))
  491. {
  492. return S_OK ;
  493. }
  494. else
  495. {
  496. return S_FALSE;
  497. }
  498. }
  499. //
  500. // Get class factory
  501. //
  502. STDAPI DllGetClassObject(const CLSID& clsid,
  503. const IID& iid,
  504. void** ppv)
  505. {
  506. VERBOSE(DLLTEXT("DllGetClassObject:Create class factory.\r\n"));
  507. // Can we create this component?
  508. if (clsid != CLSID_OEMUI)
  509. {
  510. return CLASS_E_CLASSNOTAVAILABLE ;
  511. }
  512. // Create class factory.
  513. IOemCF* pFontCF = new IOemCF ; // Reference count set to 1
  514. // in constructor
  515. if (pFontCF == NULL)
  516. {
  517. return E_OUTOFMEMORY ;
  518. }
  519. // Get requested interface.
  520. HRESULT hr = pFontCF->QueryInterface(iid, ppv) ;
  521. pFontCF->Release() ;
  522. return hr ;
  523. }