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.

545 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: Interface for User Mode COM Customization DLL.
  12. //
  13. //
  14. // Functions:
  15. //
  16. //
  17. //
  18. //
  19. // PLATFORMS: Windows 2000, Windows XP, Windows Server 2003
  20. //
  21. //
  22. #include "precomp.h"
  23. #include <INITGUID.H>
  24. #include <PRCOMOEM.H>
  25. #include "oemps.h"
  26. #include "debug.h"
  27. #include "command.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; // Count of active components
  36. static long g_cServerLocks; // Count of locks
  37. ////////////////////////////////////////////////////////////////////////////////
  38. //
  39. // IOemPS body
  40. //
  41. IOemPS::IOemPS()
  42. {
  43. VERBOSE(DLLTEXT("IOemPS::IOemPS() entered.\r\n"));
  44. // Increment COM component count.
  45. InterlockedIncrement(&g_cComponents);
  46. InterlockedIncrement(&m_cRef);
  47. m_pOEMHelp = NULL;
  48. VERBOSE(DLLTEXT("IOemPS::IOemPS() leaving.\r\n"));
  49. }
  50. IOemPS::~IOemPS()
  51. {
  52. // Make sure that helper interface is released.
  53. if(NULL != m_pOEMHelp)
  54. {
  55. m_pOEMHelp->Release();
  56. m_pOEMHelp = NULL;
  57. }
  58. // If this instance of the object is being deleted, then the reference
  59. // count should be zero.
  60. assert(0 == m_cRef);
  61. // Decrement COM compontent count.
  62. InterlockedDecrement(&g_cComponents);
  63. }
  64. HRESULT __stdcall IOemPS::QueryInterface(const IID& iid, void** ppv)
  65. {
  66. if (iid == IID_IUnknown)
  67. {
  68. *ppv = static_cast<IUnknown*>(this);
  69. VERBOSE(DLLTEXT("IOemPS::QueryInterface IUnknown.\r\n"));
  70. }
  71. else if (iid == IID_IPrintOemPS)
  72. {
  73. *ppv = static_cast<IPrintOemPS*>(this);
  74. VERBOSE(DLLTEXT("IOemPS::QueryInterface IPrintOemPs.\r\n"));
  75. }
  76. else
  77. {
  78. #if DBG && defined(USERMODE_DRIVER)
  79. TCHAR szOutput[80] = {0};
  80. StringFromGUID2(iid, szOutput, COUNTOF(szOutput)); // can not fail!
  81. VERBOSE(DLLTEXT("IOemPS::QueryInterface %s not supported.\r\n"), szOutput);
  82. #endif
  83. *ppv = NULL;
  84. return E_NOINTERFACE;
  85. }
  86. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  87. return S_OK;
  88. }
  89. ULONG __stdcall IOemPS::AddRef()
  90. {
  91. VERBOSE(DLLTEXT("IOemPS::AddRef() entry.\r\n"));
  92. return InterlockedIncrement(&m_cRef);
  93. }
  94. ULONG __stdcall IOemPS::Release()
  95. {
  96. VERBOSE(DLLTEXT("IOemPS::Release() entry.\r\n"));
  97. ASSERT( 0 != m_cRef);
  98. ULONG cRef = InterlockedDecrement(&m_cRef);
  99. if (0 == cRef)
  100. {
  101. delete this;
  102. }
  103. return cRef;
  104. }
  105. HRESULT __stdcall IOemPS::GetInfo (
  106. DWORD dwMode,
  107. PVOID pBuffer,
  108. DWORD cbSize,
  109. PDWORD pcbNeeded)
  110. {
  111. VERBOSE(DLLTEXT("IOemPS::GetInfo(%d) entry.\r\n"), dwMode);
  112. // Validate parameters.
  113. if( (NULL == pcbNeeded)
  114. ||
  115. ( (OEMGI_GETSIGNATURE != dwMode)
  116. &&
  117. (OEMGI_GETVERSION != dwMode)
  118. &&
  119. (OEMGI_GETPUBLISHERINFO != dwMode)
  120. )
  121. )
  122. {
  123. ERR(DLLTEXT("IOemPS::GetInfo() exit pcbNeeded is NULL!\r\n"));
  124. SetLastError(ERROR_INVALID_PARAMETER);
  125. return E_FAIL;
  126. }
  127. // Set expected buffer size.
  128. if(OEMGI_GETPUBLISHERINFO != dwMode)
  129. {
  130. *pcbNeeded = sizeof(DWORD);
  131. }
  132. else
  133. {
  134. *pcbNeeded = sizeof(PUBLISHERINFO);
  135. return E_FAIL;
  136. }
  137. // Check buffer size is sufficient.
  138. if((cbSize < *pcbNeeded) || (NULL == pBuffer))
  139. {
  140. ERR(DLLTEXT("IOemPS::GetInfo() exit insufficient buffer!\r\n"));
  141. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  142. return E_FAIL;
  143. }
  144. switch(dwMode)
  145. {
  146. // OEM DLL Signature
  147. case OEMGI_GETSIGNATURE:
  148. *(PDWORD)pBuffer = OEM_SIGNATURE;
  149. break;
  150. // OEM DLL version
  151. case OEMGI_GETVERSION:
  152. *(PDWORD)pBuffer = OEM_VERSION;
  153. break;
  154. case OEMGI_GETPUBLISHERINFO:
  155. Dump((PPUBLISHERINFO)pBuffer);
  156. // Fall through to default case.
  157. // dwMode not supported.
  158. default:
  159. // Set written bytes to zero since nothing was written.
  160. ERR(DLLTEXT("IOemPS::GetInfo() exit, mode not supported.\r\n"));
  161. *pcbNeeded = 0;
  162. SetLastError(ERROR_NOT_SUPPORTED);
  163. return E_FAIL;
  164. }
  165. VERBOSE(DLLTEXT("IOemPS::GetInfo() exit S_OK, (*pBuffer is %#x).\r\n"), *(PDWORD)pBuffer);
  166. return S_OK;
  167. }
  168. HRESULT __stdcall IOemPS::PublishDriverInterface(
  169. IUnknown *pIUnknown)
  170. {
  171. VERBOSE(DLLTEXT("IOemPS::PublishDriverInterface() entry.\r\n"));
  172. // Need to store pointer to Driver Helper functions, if we already haven't.
  173. if (this->m_pOEMHelp == NULL)
  174. {
  175. HRESULT hResult;
  176. // Get Interface to Helper Functions.
  177. hResult = pIUnknown->QueryInterface(IID_IPrintOemDriverPS, (void** ) &(this->m_pOEMHelp));
  178. if(!SUCCEEDED(hResult))
  179. {
  180. // Make sure that interface pointer reflects interface query failure.
  181. this->m_pOEMHelp = NULL;
  182. return E_FAIL;
  183. }
  184. }
  185. return S_OK;
  186. }
  187. HRESULT __stdcall IOemPS::EnableDriver(DWORD dwDriverVersion,
  188. DWORD cbSize,
  189. PDRVENABLEDATA pded)
  190. {
  191. VERBOSE(DLLTEXT("IOemPS::EnableDriver() entry.\r\n"));
  192. OEMEnableDriver(dwDriverVersion, cbSize, pded);
  193. // Even if nothing is done, need to return S_OK so
  194. // that DisableDriver() will be called, which releases
  195. // the reference to the Printer Driver's interface.
  196. // If error occurs, return E_FAIL.
  197. return S_OK;
  198. }
  199. HRESULT __stdcall IOemPS::DisableDriver(VOID)
  200. {
  201. VERBOSE(DLLTEXT("IOemPS::DisaleDriver() entry.\r\n"));
  202. OEMDisableDriver();
  203. // Release reference to Printer Driver's interface.
  204. if (this->m_pOEMHelp)
  205. {
  206. this->m_pOEMHelp->Release();
  207. this->m_pOEMHelp = NULL;
  208. }
  209. return S_OK;
  210. }
  211. HRESULT __stdcall IOemPS::DisablePDEV(
  212. PDEVOBJ pdevobj)
  213. {
  214. VERBOSE(DLLTEXT("IOemPS::DisablePDEV() entry.\r\n"));
  215. OEMDisablePDEV(pdevobj);
  216. return S_OK;
  217. };
  218. HRESULT __stdcall IOemPS::EnablePDEV(
  219. PDEVOBJ pdevobj,
  220. PWSTR pPrinterName,
  221. ULONG cPatterns,
  222. HSURF *phsurfPatterns,
  223. ULONG cjGdiInfo,
  224. GDIINFO *pGdiInfo,
  225. ULONG cjDevInfo,
  226. DEVINFO *pDevInfo,
  227. DRVENABLEDATA *pded,
  228. OUT PDEVOEM *pDevOem)
  229. {
  230. VERBOSE(DLLTEXT("IOemPS::EnablePDEV() entry.\r\n"));
  231. *pDevOem = OEMEnablePDEV(pdevobj, pPrinterName, cPatterns, phsurfPatterns,
  232. cjGdiInfo, pGdiInfo, cjDevInfo, pDevInfo, pded);
  233. return (NULL != *pDevOem ? S_OK : E_FAIL);
  234. }
  235. HRESULT __stdcall IOemPS::ResetPDEV(
  236. PDEVOBJ pdevobjOld,
  237. PDEVOBJ pdevobjNew)
  238. {
  239. BOOL bResult;
  240. VERBOSE(DLLTEXT("IOemPS::ResetPDEV() entry.\r\n"));
  241. bResult = OEMResetPDEV(pdevobjOld, pdevobjNew);
  242. return (bResult ? S_OK : E_FAIL);
  243. }
  244. HRESULT __stdcall IOemPS::DevMode(
  245. DWORD dwMode,
  246. POEMDMPARAM pOemDMParam)
  247. {
  248. VERBOSE(DLLTEXT("IOemPS:DevMode(%d, %#x) entry.\n"), dwMode, pOemDMParam);
  249. return hrOEMDevMode(dwMode, pOemDMParam);
  250. }
  251. HRESULT __stdcall IOemPS::Command(
  252. PDEVOBJ pdevobj,
  253. DWORD dwIndex,
  254. PVOID pData,
  255. DWORD cbSize,
  256. OUT DWORD *pdwResult)
  257. {
  258. HRESULT hResult = E_NOTIMPL;
  259. VERBOSE(DLLTEXT("IOemPS::Command() entry.\r\n"));
  260. hResult = PSCommand(pdevobj, dwIndex, pData, cbSize, m_pOEMHelp, pdwResult);
  261. return hResult;
  262. }
  263. ////////////////////////////////////////////////////////////////////////////////
  264. //
  265. // oem class factory
  266. //
  267. class IOemCF : public IClassFactory
  268. {
  269. public:
  270. // *** IUnknown methods ***
  271. STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
  272. STDMETHOD_(ULONG,AddRef) (THIS);
  273. STDMETHOD_(ULONG,Release) (THIS);
  274. // *** IClassFactory methods ***
  275. STDMETHOD(CreateInstance) (THIS_
  276. LPUNKNOWN pUnkOuter,
  277. REFIID riid,
  278. LPVOID FAR* ppvObject);
  279. STDMETHOD(LockServer) (THIS_ BOOL bLock);
  280. // Constructor
  281. IOemCF();
  282. ~IOemCF();
  283. protected:
  284. long m_cRef;
  285. };
  286. ///////////////////////////////////////////////////////////
  287. //
  288. // Class factory body
  289. //
  290. IOemCF::IOemCF()
  291. {
  292. VERBOSE(DLLTEXT("IOemCF::IOemCF() entered.\r\n"));
  293. InterlockedIncrement(&m_cRef);
  294. }
  295. IOemCF::~IOemCF()
  296. {
  297. VERBOSE(DLLTEXT("IOemCF::~IOemCF() entered.\r\n"));
  298. // If this instance of the object is being deleted, then the reference
  299. // count should be zero.
  300. assert(0 == m_cRef);
  301. }
  302. HRESULT __stdcall IOemCF::QueryInterface(const IID& iid, void** ppv)
  303. {
  304. VERBOSE(DLLTEXT("IOemCF::QueryInterface entered.\r\n"));
  305. if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
  306. {
  307. *ppv = static_cast<IOemCF*>(this);
  308. }
  309. else
  310. {
  311. #if DBG && defined(USERMODE_DRIVER)
  312. TCHAR szOutput[80] = {0};
  313. StringFromGUID2(iid, szOutput, COUNTOF(szOutput)); // can not fail!
  314. WARNING(DLLTEXT("IOemCF::QueryInterface %s not supported.\r\n"), szOutput);
  315. #endif
  316. *ppv = NULL;
  317. return E_NOINTERFACE;
  318. }
  319. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  320. VERBOSE(DLLTEXT("IOemCF::QueryInterface leaving.\r\n"));
  321. return S_OK;
  322. }
  323. ULONG __stdcall IOemCF::AddRef()
  324. {
  325. VERBOSE(DLLTEXT("IOemCF::AddRef() called.\r\n"));
  326. return InterlockedIncrement(&m_cRef);
  327. }
  328. ULONG __stdcall IOemCF::Release()
  329. {
  330. VERBOSE(DLLTEXT("IOemCF::Release() called.\r\n"));
  331. ASSERT( 0 != m_cRef);
  332. ULONG cRef = InterlockedDecrement(&m_cRef);
  333. if (0 == cRef)
  334. {
  335. delete this;
  336. }
  337. return cRef;
  338. }
  339. // IClassFactory implementation
  340. HRESULT __stdcall IOemCF::CreateInstance(IUnknown* pUnknownOuter,
  341. const IID& iid,
  342. void** ppv)
  343. {
  344. VERBOSE(DLLTEXT("Class factory: Create component.\r\n"));
  345. // Cannot aggregate.
  346. if (pUnknownOuter != NULL)
  347. {
  348. WARNING(DLLTEXT("Class factory: non-Null pUnknownOuter.\r\n"));
  349. return CLASS_E_NOAGGREGATION;
  350. }
  351. // Create component.
  352. IOemPS* pOemCP = new IOemPS;
  353. if (pOemCP == NULL)
  354. {
  355. ERR(ERRORTEXT("Class factory: failed to allocate IOemPS.\r\n"));
  356. return E_OUTOFMEMORY;
  357. }
  358. // Get the requested interface.
  359. HRESULT hr = pOemCP->QueryInterface(iid, ppv);
  360. // Release the IUnknown pointer.
  361. // (If QueryInterface failed, component will delete itself.)
  362. pOemCP->Release();
  363. return hr;
  364. }
  365. // LockServer
  366. HRESULT __stdcall IOemCF::LockServer(BOOL bLock)
  367. {
  368. VERBOSE(DLLTEXT("IOemCF::LockServer(%d) entered.\r\n"), bLock);
  369. if (bLock)
  370. {
  371. InterlockedIncrement(&g_cServerLocks);
  372. }
  373. else
  374. {
  375. InterlockedDecrement(&g_cServerLocks);
  376. }
  377. VERBOSE(DLLTEXT("IOemCF::LockServer() leaving.\r\n"));
  378. return S_OK;
  379. }
  380. //
  381. // Registration functions
  382. //
  383. //
  384. // Can DLL unload now?
  385. //
  386. STDAPI DllCanUnloadNow()
  387. {
  388. //
  389. // To avoid leaving OEM DLL still in memory when Unidrv or Pscript drivers
  390. // are unloaded, Unidrv and Pscript driver ignore the return value of
  391. // DllCanUnloadNow of the OEM DLL, and always call FreeLibrary on the OEMDLL.
  392. //
  393. // If OEM DLL spins off a working thread that also uses the OEM DLL, the
  394. // thread needs to call LoadLibrary and FreeLibraryAndExitThread, otherwise
  395. // it may crash after Unidrv or Pscript calls FreeLibrary.
  396. //
  397. VERBOSE(DLLTEXT("DllCanUnloadNow entered.\r\n"));
  398. if ((g_cComponents == 0) && (g_cServerLocks == 0))
  399. {
  400. return S_OK;
  401. }
  402. else
  403. {
  404. return S_FALSE;
  405. }
  406. }
  407. //
  408. // Get class factory
  409. //
  410. STDAPI DllGetClassObject(const CLSID& clsid,
  411. const IID& iid,
  412. void** ppv)
  413. {
  414. VERBOSE(DLLTEXT("DllGetClassObject: Create class factory entered.\r\n"));
  415. // Can we create this component?
  416. if (clsid != CLSID_OEMRENDER)
  417. {
  418. ERR(ERRORTEXT("DllGetClassObject: doesn't support clsid %#x!\r\n"), clsid);
  419. return CLASS_E_CLASSNOTAVAILABLE;
  420. }
  421. // Create class factory.
  422. IOemCF* pFontCF = new IOemCF; // Reference count set to 1
  423. // in constructor
  424. if (pFontCF == NULL)
  425. {
  426. ERR(ERRORTEXT("DllGetClassObject: memory allocation failed!\r\n"));
  427. return E_OUTOFMEMORY;
  428. }
  429. // Get requested interface.
  430. HRESULT hr = pFontCF->QueryInterface(iid, ppv);
  431. pFontCF->Release();
  432. VERBOSE(DLLTEXT("DllGetClassObject: Create class factory leaving.\r\n"));
  433. return hr;
  434. }