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.

536 lines
13 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 PScript4, PScript5, Unidrv4,
  12. // Unidrv5 UI plug-ins.
  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 Globals
  34. ////////////////////////////////////////////////////////
  35. static long g_cComponents = 0 ; // Count of active components
  36. static long g_cServerLocks = 0 ; // Count of locks
  37. ////////////////////////////////////////////////////////////////////////////////
  38. //
  39. // IOemUI body
  40. //
  41. IOemUI::~IOemUI()
  42. {
  43. // Make sure that helper interface is released.
  44. if(NULL != m_pOEMHelp)
  45. {
  46. m_pOEMHelp->Release();
  47. m_pOEMHelp = NULL;
  48. }
  49. // If this instance of the object is being deleted, then the reference
  50. // count should be zero.
  51. assert(0 == m_cRef);
  52. }
  53. HRESULT __stdcall IOemUI::QueryInterface(const IID& iid, void** ppv)
  54. {
  55. VERBOSE(DLLTEXT("IOemUI:QueryInterface entry.\r\n\r\n"));
  56. if (iid == IID_IUnknown)
  57. {
  58. *ppv = static_cast<IUnknown*>(this);
  59. VERBOSE(DLLTEXT("IOemUI:Return pointer to IUnknown.\r\n\r\n"));
  60. }
  61. else if (iid == IID_IPrintOemUI)
  62. {
  63. *ppv = static_cast<IPrintOemUI*>(this) ;
  64. VERBOSE(DLLTEXT("IOemUI:Return pointer to IPrintOemUI.\r\n"));
  65. }
  66. else
  67. {
  68. #if DBG
  69. TCHAR szOutput[80] = {0};
  70. StringFromGUID2(iid, szOutput, COUNTOF(szOutput)); // can not fail!
  71. VERBOSE(DLLTEXT("IOemUI::QueryInterface %s not supported.\r\n"), szOutput);
  72. #endif
  73. *ppv = NULL ;
  74. return E_NOINTERFACE ;
  75. }
  76. reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
  77. return S_OK ;
  78. }
  79. ULONG __stdcall IOemUI::AddRef()
  80. {
  81. VERBOSE(DLLTEXT("IOemUI:AddRef entry.\r\n"));
  82. return InterlockedIncrement(&m_cRef) ;
  83. }
  84. ULONG __stdcall IOemUI::Release()
  85. {
  86. VERBOSE(DLLTEXT("IOemUI:Release entry.\r\n"));
  87. ASSERT( 0 != m_cRef);
  88. ULONG cRef = InterlockedDecrement(&m_cRef);
  89. if (0 == cRef)
  90. {
  91. delete this;
  92. }
  93. return cRef;
  94. }
  95. HRESULT __stdcall IOemUI::PublishDriverInterface(
  96. IUnknown *pIUnknown)
  97. {
  98. VERBOSE(DLLTEXT("IOemUI:PublishDriverInterface entry.\r\n"));
  99. // Need to store pointer to Driver Helper functions, if we already haven't.
  100. if (m_pOEMHelp == NULL)
  101. {
  102. HRESULT hResult;
  103. // Get Interface to Helper Functions.
  104. hResult = pIUnknown->QueryInterface(IID_IPrintOemDriverUI, (void** ) &(m_pOEMHelp));
  105. if(!SUCCEEDED(hResult))
  106. {
  107. // Make sure that interface pointer reflects interface query failure.
  108. m_pOEMHelp = NULL;
  109. return E_FAIL;
  110. }
  111. }
  112. return S_OK;
  113. }
  114. HRESULT __stdcall IOemUI::GetInfo(
  115. DWORD dwMode,
  116. PVOID pBuffer,
  117. DWORD cbSize,
  118. PDWORD pcbNeeded)
  119. {
  120. VERBOSE(DLLTEXT("IOemUI::GetInfo(%d) entry.\r\r\n"), dwMode);
  121. // Validate parameters.
  122. if( (NULL == pcbNeeded)
  123. ||
  124. ( (OEMGI_GETSIGNATURE != dwMode)
  125. &&
  126. (OEMGI_GETVERSION != dwMode)
  127. &&
  128. (OEMGI_GETPUBLISHERINFO != dwMode)
  129. )
  130. )
  131. {
  132. WARNING(DLLTEXT("IOemUI::GetInfo() exit pcbNeeded is NULL! ERROR_INVALID_PARAMETER\r\r\n"));
  133. SetLastError(ERROR_INVALID_PARAMETER);
  134. return E_FAIL;
  135. }
  136. // Set expected buffer size and number of bytes written.
  137. *pcbNeeded = sizeof(DWORD);
  138. // Check buffer size is sufficient.
  139. if((cbSize < *pcbNeeded) || (NULL == pBuffer))
  140. {
  141. WARNING(DLLTEXT("IOemUI::GetInfo() exit insufficient buffer!\r\r\n"));
  142. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  143. return E_FAIL;
  144. }
  145. switch(dwMode)
  146. {
  147. // OEM DLL Signature
  148. case OEMGI_GETSIGNATURE:
  149. *(PDWORD)pBuffer = OEM_SIGNATURE;
  150. break;
  151. // OEM DLL version
  152. case OEMGI_GETVERSION:
  153. *(PDWORD)pBuffer = OEM_VERSION;
  154. break;
  155. // dwMode not supported.
  156. default:
  157. // Set written bytes to zero since nothing was written.
  158. WARNING(DLLTEXT("IOemUI::GetInfo() exit mode not supported.\r\r\n"));
  159. *pcbNeeded = 0;
  160. SetLastError(ERROR_NOT_SUPPORTED);
  161. return E_FAIL;
  162. }
  163. VERBOSE(DLLTEXT("IOemUI::GetInfo() exit S_OK, (*pBuffer is %#x).\r\r\n"), *(PDWORD)pBuffer);
  164. return S_OK;
  165. }
  166. HRESULT __stdcall IOemUI::DevMode(
  167. DWORD dwMode,
  168. POEMDMPARAM pOemDMParam)
  169. {
  170. VERBOSE(DLLTEXT("IOemUI:DevMode(%d, %#x) entry.\r\n"), dwMode, pOemDMParam);
  171. return hrOEMDevMode(dwMode, pOemDMParam);
  172. }
  173. HRESULT __stdcall IOemUI::CommonUIProp(
  174. DWORD dwMode,
  175. POEMCUIPPARAM pOemCUIPParam)
  176. {
  177. VERBOSE(DLLTEXT("IOemUI:CommonUIProp entry.\r\n"));
  178. return hrOEMPropertyPage(dwMode, pOemCUIPParam);
  179. }
  180. HRESULT __stdcall IOemUI::DocumentPropertySheets(
  181. PPROPSHEETUI_INFO pPSUIInfo,
  182. LPARAM lParam)
  183. {
  184. VERBOSE(DLLTEXT("IOemUI:DocumentPropertySheets entry.\r\n"));
  185. return hrOEMDocumentPropertySheets(pPSUIInfo, lParam, m_pOEMHelp);
  186. }
  187. HRESULT __stdcall IOemUI::DevicePropertySheets(
  188. PPROPSHEETUI_INFO pPSUIInfo,
  189. LPARAM lParam)
  190. {
  191. VERBOSE(DLLTEXT("IOemUI:DevicePropertySheets entry.\r\n"));
  192. return hrOEMDevicePropertySheets(pPSUIInfo, lParam);
  193. }
  194. HRESULT __stdcall IOemUI::DeviceCapabilities(
  195. POEMUIOBJ poemuiobj,
  196. HANDLE hPrinter,
  197. PWSTR pDeviceName,
  198. WORD wCapability,
  199. PVOID pOutput,
  200. PDEVMODE pPublicDM,
  201. PVOID pOEMDM,
  202. DWORD dwOld,
  203. DWORD *dwResult)
  204. {
  205. VERBOSE(DLLTEXT("IOemUI:DeviceCapabilities entry.\r\n"));
  206. return E_NOTIMPL;
  207. }
  208. HRESULT __stdcall IOemUI::DevQueryPrintEx(
  209. POEMUIOBJ poemuiobj,
  210. PDEVQUERYPRINT_INFO pDQPInfo,
  211. PDEVMODE pPublicDM,
  212. PVOID pOEMDM)
  213. {
  214. VERBOSE(DLLTEXT("IOemUI:DevQueryPrintEx entry.\r\n"));
  215. return E_NOTIMPL;
  216. }
  217. HRESULT __stdcall IOemUI::UpgradePrinter(
  218. DWORD dwLevel,
  219. PBYTE pDriverUpgradeInfo)
  220. {
  221. VERBOSE(DLLTEXT("IOemUI:UpgradePrinter entry.\r\n"));
  222. return E_NOTIMPL;
  223. }
  224. HRESULT __stdcall IOemUI::PrinterEvent(
  225. PWSTR pPrinterName,
  226. INT iDriverEvent,
  227. DWORD dwFlags,
  228. LPARAM lParam)
  229. {
  230. VERBOSE(DLLTEXT("IOemUI:PrinterEvent entry.\r\n"));
  231. return E_NOTIMPL;
  232. }
  233. HRESULT __stdcall IOemUI::DriverEvent(
  234. DWORD dwDriverEvent,
  235. DWORD dwLevel,
  236. LPBYTE pDriverInfo,
  237. LPARAM lParam)
  238. {
  239. VERBOSE(DLLTEXT("IOemUI:DriverEvent entry.\r\n"));
  240. return E_NOTIMPL;
  241. };
  242. #define PROFILE_NAME L"OEMPROFILE.icm\0"
  243. HRESULT __stdcall IOemUI::QueryColorProfile(
  244. HANDLE hPrinter,
  245. POEMUIOBJ poemuiobj,
  246. PDEVMODE pPublicDM,
  247. PVOID pOEMDM,
  248. ULONG ulQueryMode,
  249. VOID *pvProfileData,
  250. ULONG *pcbProfileData,
  251. FLONG *pflProfileData)
  252. {
  253. HRESULT Result = E_FAIL;
  254. VERBOSE(DLLTEXT("IOemUI:QueryColorProfile entry.\r\n"));
  255. if(QCP_DEVICEPROFILE == ulQueryMode)
  256. {
  257. if(NULL == pvProfileData)
  258. {
  259. *pcbProfileData = sizeof(PROFILE_NAME);
  260. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  261. }
  262. else
  263. {
  264. if(*pcbProfileData < sizeof(PROFILE_NAME))
  265. {
  266. *pcbProfileData = sizeof(PROFILE_NAME);
  267. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  268. }
  269. else
  270. {
  271. Result = StringCbCopy((LPWSTR)pvProfileData, *pcbProfileData, PROFILE_NAME);
  272. *pcbProfileData = sizeof(PROFILE_NAME);
  273. *pflProfileData = QCP_PROFILEDISK;
  274. if(FAILED(Result))
  275. {
  276. SetLastError(Result);
  277. }
  278. }
  279. }
  280. }
  281. return Result;
  282. };
  283. HRESULT __stdcall IOemUI::FontInstallerDlgProc(
  284. HWND hWnd,
  285. UINT usMsg,
  286. WPARAM wParam,
  287. LPARAM lParam)
  288. {
  289. VERBOSE(DLLTEXT("IOemUI:FontInstallerDlgProc entry.\r\n"));
  290. return E_NOTIMPL;
  291. };
  292. HRESULT __stdcall IOemUI::UpdateExternalFonts(
  293. HANDLE hPrinter,
  294. HANDLE hHeap,
  295. PWSTR pwstrCartridges)
  296. {
  297. VERBOSE(DLLTEXT("IOemUI:UpdateExternalFonts entry.\r\n"));
  298. return E_NOTIMPL;
  299. }
  300. ////////////////////////////////////////////////////////////////////////////////
  301. //
  302. // oem class factory
  303. //
  304. class IOemCF : public IClassFactory
  305. {
  306. public:
  307. // *** IUnknown methods ***
  308. STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
  309. STDMETHOD_(ULONG,AddRef) (THIS);
  310. STDMETHOD_(ULONG,Release) (THIS);
  311. // *** IClassFactory methods ***
  312. STDMETHOD(CreateInstance) (THIS_
  313. LPUNKNOWN pUnkOuter,
  314. REFIID riid,
  315. LPVOID FAR* ppvObject);
  316. STDMETHOD(LockServer) (THIS_ BOOL bLock);
  317. // Constructor
  318. IOemCF(): m_cRef(1) { };
  319. ~IOemCF() { };
  320. protected:
  321. LONG m_cRef;
  322. };
  323. ///////////////////////////////////////////////////////////
  324. //
  325. // Class factory body
  326. //
  327. HRESULT __stdcall IOemCF::QueryInterface(const IID& iid, void** ppv)
  328. {
  329. if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
  330. {
  331. *ppv = static_cast<IOemCF*>(this) ;
  332. }
  333. else
  334. {
  335. #if DBG && defined(USERMODE_DRIVER)
  336. TCHAR szOutput[80] = {0};
  337. StringFromGUID2(iid, szOutput, COUNTOF(szOutput)); // can not fail!
  338. WARNING(DLLTEXT("IOemCF::QueryInterface %s not supported.\r\n"), szOutput);
  339. #endif
  340. *ppv = NULL ;
  341. return E_NOINTERFACE ;
  342. }
  343. reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
  344. return S_OK ;
  345. }
  346. ULONG __stdcall IOemCF::AddRef()
  347. {
  348. return InterlockedIncrement(&m_cRef) ;
  349. }
  350. ULONG __stdcall IOemCF::Release()
  351. {
  352. ASSERT( 0 != m_cRef);
  353. ULONG cRef = InterlockedDecrement(&m_cRef);
  354. if (0 == cRef)
  355. {
  356. delete this;
  357. }
  358. return cRef;
  359. }
  360. // IClassFactory implementation
  361. HRESULT __stdcall IOemCF::CreateInstance(IUnknown* pUnknownOuter,
  362. const IID& iid,
  363. void** ppv)
  364. {
  365. //DbgPrint(DLLTEXT("Class factory:\t\tCreate component.")) ;
  366. // Cannot aggregate.
  367. if (pUnknownOuter != NULL)
  368. {
  369. return CLASS_E_NOAGGREGATION ;
  370. }
  371. // Create component.
  372. IOemUI* pOemCB = new IOemUI ;
  373. if (pOemCB == NULL)
  374. {
  375. return E_OUTOFMEMORY ;
  376. }
  377. // Get the requested interface.
  378. HRESULT hr = pOemCB->QueryInterface(iid, ppv) ;
  379. // Release the IUnknown pointer.
  380. // (If QueryInterface failed, component will delete itself.)
  381. pOemCB->Release() ;
  382. return hr ;
  383. }
  384. // LockServer
  385. HRESULT __stdcall IOemCF::LockServer(BOOL bLock)
  386. {
  387. if (bLock)
  388. {
  389. InterlockedIncrement(&g_cServerLocks) ;
  390. }
  391. else
  392. {
  393. InterlockedDecrement(&g_cServerLocks) ;
  394. }
  395. return S_OK ;
  396. }
  397. ///////////////////////////////////////////////////////////
  398. //
  399. // Exported functions
  400. //
  401. // Can DLL unload now?
  402. //
  403. STDAPI DllCanUnloadNow()
  404. {
  405. //
  406. // To avoid leaving OEM DLL still in memory when Unidrv or Pscript drivers
  407. // are unloaded, Unidrv and Pscript driver ignore the return value of
  408. // DllCanUnloadNow of the OEM DLL, and always call FreeLibrary on the OEMDLL.
  409. //
  410. // If OEM DLL spins off a working thread that also uses the OEM DLL, the
  411. // thread needs to call LoadLibrary and FreeLibraryAndExitThread, otherwise
  412. // it may crash after Unidrv or Pscript calls FreeLibrary.
  413. //
  414. if ((g_cComponents == 0) && (g_cServerLocks == 0))
  415. {
  416. return S_OK ;
  417. }
  418. else
  419. {
  420. return S_FALSE;
  421. }
  422. }
  423. //
  424. // Get class factory
  425. //
  426. STDAPI DllGetClassObject(const CLSID& clsid,
  427. const IID& iid,
  428. void** ppv)
  429. {
  430. VERBOSE(DLLTEXT("DllGetClassObject:Create class factory.\r\n"));
  431. // Can we create this component?
  432. if (clsid != CLSID_OEMUI)
  433. {
  434. return CLASS_E_CLASSNOTAVAILABLE ;
  435. }
  436. // Create class factory.
  437. IOemCF* pFontCF = new IOemCF ; // Reference count set to 1
  438. // in constructor
  439. if (pFontCF == NULL)
  440. {
  441. return E_OUTOFMEMORY ;
  442. }
  443. // Get requested interface.
  444. HRESULT hr = pFontCF->QueryInterface(iid, ppv) ;
  445. pFontCF->Release() ;
  446. return hr ;
  447. }