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.

790 lines
19 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 "oemuni.h"
  26. #include "debug.h"
  27. #include "intrface.h"
  28. #include "name.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. // IOemUni body
  40. //
  41. IOemUni::~IOemUni()
  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 IOemUni::QueryInterface(const IID& iid, void** ppv)
  54. {
  55. if (iid == IID_IUnknown)
  56. {
  57. *ppv = static_cast<IUnknown*>(this);
  58. VERBOSE(DLLTEXT("IOemUni::QueryInterface IUnknown.\r\n"));
  59. }
  60. else if (iid == IID_IPrintOemUni)
  61. {
  62. *ppv = static_cast<IPrintOemUni*>(this);
  63. VERBOSE(DLLTEXT("IOemUni::QueryInterface IPrintOemUni.\r\n"));
  64. }
  65. else
  66. {
  67. *ppv = NULL;
  68. #if DBG && defined(USERMODE_DRIVER)
  69. TCHAR szOutput[80] = {0};
  70. StringFromGUID2(iid, szOutput, COUNTOF(szOutput)); // can not fail!
  71. VERBOSE(DLLTEXT("IOemUni::QueryInterface %s not supported.\r\n"), szOutput);
  72. #endif
  73. return E_NOINTERFACE;
  74. }
  75. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  76. return S_OK;
  77. }
  78. ULONG __stdcall IOemUni::AddRef()
  79. {
  80. VERBOSE(DLLTEXT("IOemUni::AddRef() entry.\r\n"));
  81. return InterlockedIncrement(&m_cRef);
  82. }
  83. ULONG __stdcall IOemUni::Release()
  84. {
  85. VERBOSE(DLLTEXT("IOemUni::Release() entry.\r\n"));
  86. ASSERT( 0 != m_cRef);
  87. ULONG cRef = InterlockedDecrement(&m_cRef);
  88. if (0 == cRef)
  89. {
  90. delete this;
  91. }
  92. return cRef;
  93. }
  94. HRESULT __stdcall IOemUni::GetInfo (
  95. DWORD dwMode,
  96. PVOID pBuffer,
  97. DWORD cbSize,
  98. PDWORD pcbNeeded)
  99. {
  100. VERBOSE(DLLTEXT("IOemUni::GetInfo(%d) entry.\r\n"), dwMode);
  101. // Validate parameters.
  102. if( (NULL == pcbNeeded)
  103. ||
  104. ( (OEMGI_GETSIGNATURE != dwMode)
  105. &&
  106. (OEMGI_GETVERSION != dwMode)
  107. &&
  108. (OEMGI_GETPUBLISHERINFO != dwMode)
  109. )
  110. )
  111. {
  112. WARNING(DLLTEXT("IOemUni::GetInfo() exit pcbNeeded is NULL! ERROR_INVALID_PARAMETER.\r\n"));
  113. SetLastError(ERROR_INVALID_PARAMETER);
  114. return E_FAIL;
  115. }
  116. // Set expected buffer size.
  117. if(OEMGI_GETPUBLISHERINFO != dwMode)
  118. {
  119. *pcbNeeded = sizeof(DWORD);
  120. }
  121. else
  122. {
  123. *pcbNeeded = sizeof(PUBLISHERINFO);
  124. return E_FAIL;
  125. }
  126. // Check buffer size is sufficient.
  127. if((cbSize < *pcbNeeded) || (NULL == pBuffer))
  128. {
  129. VERBOSE(DLLTEXT("IOemUni::GetInfo() exit insufficient buffer!\r\n"));
  130. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  131. return E_FAIL;
  132. }
  133. switch(dwMode)
  134. {
  135. // OEM DLL Signature
  136. case OEMGI_GETSIGNATURE:
  137. *(PDWORD)pBuffer = OEM_SIGNATURE;
  138. break;
  139. // OEM DLL version
  140. case OEMGI_GETVERSION:
  141. *(PDWORD)pBuffer = OEM_VERSION;
  142. break;
  143. case OEMGI_GETPUBLISHERINFO:
  144. Dump((PPUBLISHERINFO)pBuffer);
  145. // Fall through to default case.
  146. // dwMode not supported.
  147. default:
  148. // Set written bytes to zero since nothing was written.
  149. WARNING(DLLTEXT("IOemUni::GetInfo() exit mode not supported.\r\n"));
  150. *pcbNeeded = 0;
  151. SetLastError(ERROR_NOT_SUPPORTED);
  152. return E_FAIL;
  153. }
  154. VERBOSE(DLLTEXT("IOemUni::GetInfo() exit S_OK, (*pBuffer is %#x).\r\n"), *(PDWORD)pBuffer);
  155. return S_OK;
  156. }
  157. HRESULT __stdcall IOemUni::PublishDriverInterface(
  158. IUnknown *pIUnknown)
  159. {
  160. VERBOSE(DLLTEXT("IOemUni::PublishDriverInterface() entry.\r\n"));
  161. // Need to store pointer to Driver Helper functions, if we already haven't.
  162. if (this->m_pOEMHelp == NULL)
  163. {
  164. HRESULT hResult;
  165. // Get Interface to Helper Functions.
  166. hResult = pIUnknown->QueryInterface(IID_IPrintOemDriverUni, (void** ) &(this->m_pOEMHelp));
  167. if(!SUCCEEDED(hResult))
  168. {
  169. // Make sure that interface pointer reflects interface query failure.
  170. this->m_pOEMHelp = NULL;
  171. return E_FAIL;
  172. }
  173. }
  174. return S_OK;
  175. }
  176. HRESULT __stdcall IOemUni::EnableDriver(
  177. DWORD dwDriverVersion,
  178. DWORD cbSize,
  179. PDRVENABLEDATA pded)
  180. {
  181. VERBOSE(DLLTEXT("IOemUni::EnableDriver() entry.\r\n"));
  182. OEMEnableDriver(dwDriverVersion, cbSize, pded);
  183. // Even if nothing is done, need to return S_OK so
  184. // that DisableDriver() will be called, which releases
  185. // the reference to the Printer Driver's interface.
  186. // If error occurs, return E_FAIL.
  187. return S_OK;
  188. }
  189. HRESULT __stdcall IOemUni::DisableDriver(VOID)
  190. {
  191. VERBOSE(DLLTEXT("IOemUni::DisaleDriver() entry.\r\n"));
  192. OEMDisableDriver();
  193. // Release reference to Printer Driver's interface.
  194. if (this->m_pOEMHelp)
  195. {
  196. this->m_pOEMHelp->Release();
  197. this->m_pOEMHelp = NULL;
  198. }
  199. return S_OK;
  200. }
  201. HRESULT __stdcall IOemUni::DisablePDEV(
  202. PDEVOBJ pdevobj)
  203. {
  204. VERBOSE(DLLTEXT("IOemUni::DisablePDEV() entry.\r\n"));
  205. OEMDisablePDEV(pdevobj);
  206. return S_OK;
  207. };
  208. HRESULT __stdcall IOemUni::EnablePDEV(
  209. PDEVOBJ pdevobj,
  210. PWSTR pPrinterName,
  211. ULONG cPatterns,
  212. HSURF *phsurfPatterns,
  213. ULONG cjGdiInfo,
  214. GDIINFO *pGdiInfo,
  215. ULONG cjDevInfo,
  216. DEVINFO *pDevInfo,
  217. DRVENABLEDATA *pded,
  218. OUT PDEVOEM *pDevOem)
  219. {
  220. VERBOSE(DLLTEXT("IOemUni::EnablePDEV() entry.\r\n"));
  221. *pDevOem = OEMEnablePDEV(pdevobj, pPrinterName, cPatterns, phsurfPatterns,
  222. cjGdiInfo, pGdiInfo, cjDevInfo, pDevInfo, pded);
  223. return (NULL != *pDevOem ? S_OK : E_FAIL);
  224. }
  225. HRESULT __stdcall IOemUni::ResetPDEV(
  226. PDEVOBJ pdevobjOld,
  227. PDEVOBJ pdevobjNew)
  228. {
  229. BOOL bResult;
  230. VERBOSE(DLLTEXT("IOemUni::ResetPDEV() entry.\r\n"));
  231. bResult = OEMResetPDEV(pdevobjOld, pdevobjNew);
  232. return (bResult ? S_OK : E_FAIL);
  233. }
  234. HRESULT __stdcall IOemUni::DevMode(
  235. DWORD dwMode,
  236. POEMDMPARAM pOemDMParam)
  237. {
  238. VERBOSE(DLLTEXT("IOemUni:DevMode(%d, %#x) entry.\n"), dwMode, pOemDMParam);
  239. return hrOEMDevMode(dwMode, pOemDMParam);
  240. }
  241. HRESULT __stdcall IOemUni::GetImplementedMethod(PSTR pMethodName)
  242. {
  243. HRESULT Result = S_FALSE;
  244. VERBOSE(DLLTEXT("IOemUni::GetImplementedMethod() entry.\r\n"));
  245. VERBOSE(DLLTEXT(" Function:%hs:"),pMethodName);
  246. // Unidrv only calls GetImplementedMethod for optional
  247. // methods. The required methods are assumed to be
  248. // supported.
  249. // Return S_OK for supported function (i.e. implemented),
  250. // and S_FALSE for functions that aren't supported (i.e. not implemented).
  251. switch (*pMethodName)
  252. {
  253. case 'C':
  254. if (!strcmp(NAME_CommandCallback, pMethodName))
  255. {
  256. Result = S_OK;
  257. }
  258. else if (!strcmp(NAME_Compression, pMethodName))
  259. {
  260. Result = S_FALSE;
  261. }
  262. break;
  263. case 'D':
  264. if (!strcmp(NAME_DownloadFontHeader, pMethodName))
  265. {
  266. Result = S_FALSE;
  267. }
  268. else if (!strcmp(NAME_DownloadCharGlyph, pMethodName))
  269. {
  270. Result = S_FALSE;
  271. }
  272. break;
  273. case 'F':
  274. if (!strcmp(NAME_FilterGraphics, pMethodName))
  275. {
  276. Result = S_OK;
  277. }
  278. break;
  279. case 'H':
  280. if (!strcmp(NAME_HalftonePattern, pMethodName))
  281. {
  282. Result = S_FALSE;
  283. }
  284. break;
  285. case 'I':
  286. if (!strcmp(NAME_ImageProcessing, pMethodName))
  287. {
  288. Result = S_OK;
  289. }
  290. break;
  291. case 'M':
  292. if (!strcmp(NAME_MemoryUsage, pMethodName))
  293. {
  294. Result = S_FALSE;
  295. }
  296. break;
  297. case 'O':
  298. if (!strcmp(NAME_OutputCharStr, pMethodName))
  299. {
  300. Result = S_FALSE;
  301. }
  302. break;
  303. case 'S':
  304. if (!strcmp(NAME_SendFontCmd, pMethodName))
  305. {
  306. Result = S_FALSE;
  307. }
  308. break;
  309. case 'T':
  310. if (!strcmp(NAME_TextOutAsBitmap, pMethodName))
  311. {
  312. Result = S_FALSE;
  313. }
  314. else if (!strcmp(NAME_TTDownloadMethod, pMethodName))
  315. {
  316. Result = S_FALSE;
  317. }
  318. else if (!strcmp(NAME_TTYGetInfo, pMethodName))
  319. {
  320. Result = S_FALSE;
  321. }
  322. break;
  323. case 'W':
  324. if(!strcmp(NAME_WritePrinter, pMethodName))
  325. {
  326. Result = S_FALSE;
  327. }
  328. break;
  329. }
  330. VERBOSE( Result == S_OK ? TEXT("Supported\r\n") : TEXT("NOT supported\r\n"));
  331. return Result;
  332. }
  333. HRESULT __stdcall IOemUni::CommandCallback(
  334. PDEVOBJ pdevobj,
  335. DWORD dwCallbackID,
  336. DWORD dwCount,
  337. PDWORD pdwParams,
  338. OUT INT *piResult)
  339. {
  340. VERBOSE(DLLTEXT("IOemUni::CommandCallback() entry.\r\n"));
  341. VERBOSE(DLLTEXT(" dwCallbackID = %d\r\n"), dwCallbackID);
  342. VERBOSE(DLLTEXT(" dwCount = %d\r\n"), dwCount);
  343. *piResult = 0;
  344. return S_OK;
  345. }
  346. HRESULT __stdcall IOemUni::ImageProcessing(
  347. PDEVOBJ pdevobj,
  348. PBYTE pSrcBitmap,
  349. PBITMAPINFOHEADER pBitmapInfoHeader,
  350. PBYTE pColorTable,
  351. DWORD dwCallbackID,
  352. PIPPARAMS pIPParams,
  353. OUT PBYTE *ppbResult)
  354. {
  355. VERBOSE(DLLTEXT("IOemUni::ImageProcessing() entry.\r\n"));
  356. return S_OK;
  357. }
  358. HRESULT __stdcall IOemUni::FilterGraphics(
  359. PDEVOBJ pdevobj,
  360. PBYTE pBuf,
  361. DWORD dwLen)
  362. {
  363. DWORD dwResult;
  364. VERBOSE(DLLTEXT("IOemUni::FilterGraphis() entry.\r\n"));
  365. m_pOEMHelp->DrvWriteSpoolBuf(pdevobj, pBuf, dwLen, &dwResult);
  366. if (dwResult == dwLen)
  367. return S_OK;
  368. else
  369. return E_FAIL;
  370. }
  371. HRESULT __stdcall IOemUni::Compression(
  372. PDEVOBJ pdevobj,
  373. PBYTE pInBuf,
  374. PBYTE pOutBuf,
  375. DWORD dwInLen,
  376. DWORD dwOutLen,
  377. OUT INT *piResult)
  378. {
  379. VERBOSE(DLLTEXT("IOemUni::Compression() entry.\r\n"));
  380. // When implemented, the return from GetImplementedMethod
  381. // for this method name must be S_OK.
  382. return E_NOTIMPL;
  383. }
  384. HRESULT __stdcall IOemUni::HalftonePattern(
  385. PDEVOBJ pdevobj,
  386. PBYTE pHTPattern,
  387. DWORD dwHTPatternX,
  388. DWORD dwHTPatternY,
  389. DWORD dwHTNumPatterns,
  390. DWORD dwCallbackID,
  391. PBYTE pResource,
  392. DWORD dwResourceSize)
  393. {
  394. VERBOSE(DLLTEXT("IOemUni::HalftonePattern() entry.\r\n"));
  395. // When implemented, the return from GetImplementedMethod
  396. // for this method name must be S_OK.
  397. return E_NOTIMPL;
  398. }
  399. HRESULT __stdcall IOemUni::MemoryUsage(
  400. PDEVOBJ pdevobj,
  401. POEMMEMORYUSAGE pMemoryUsage)
  402. {
  403. VERBOSE(DLLTEXT("IOemUni::MemoryUsage() entry.\r\n"));
  404. // When implemented, the return from GetImplementedMethod
  405. // for this method name must be S_OK.
  406. return E_NOTIMPL;
  407. }
  408. HRESULT __stdcall IOemUni::DownloadFontHeader(
  409. PDEVOBJ pdevobj,
  410. PUNIFONTOBJ pUFObj,
  411. OUT DWORD *pdwResult)
  412. {
  413. VERBOSE(DLLTEXT("IOemUni::DownloadFontHeader() entry.\r\n"));
  414. // When implemented, the return from GetImplementedMethod
  415. // for this method name must be S_OK.
  416. return E_NOTIMPL;
  417. }
  418. HRESULT __stdcall IOemUni::DownloadCharGlyph(
  419. PDEVOBJ pdevobj,
  420. PUNIFONTOBJ pUFObj,
  421. HGLYPH hGlyph,
  422. PDWORD pdwWidth,
  423. OUT DWORD *pdwResult)
  424. {
  425. VERBOSE(DLLTEXT("IOemUni::DownloadCharGlyph() entry.\r\n"));
  426. // When implemented, the return from GetImplementedMethod
  427. // for this method name must be S_OK.
  428. return E_NOTIMPL;
  429. }
  430. HRESULT __stdcall IOemUni::TTDownloadMethod(
  431. PDEVOBJ pdevobj,
  432. PUNIFONTOBJ pUFObj,
  433. OUT DWORD *pdwResult)
  434. {
  435. VERBOSE(DLLTEXT("IOemUni::TTDownloadMethod() entry.\r\n"));
  436. // When implemented, the return from GetImplementedMethod
  437. // for this method name must be S_OK.
  438. return E_NOTIMPL;
  439. }
  440. HRESULT __stdcall IOemUni::OutputCharStr(
  441. PDEVOBJ pdevobj,
  442. PUNIFONTOBJ pUFObj,
  443. DWORD dwType,
  444. DWORD dwCount,
  445. PVOID pGlyph)
  446. {
  447. VERBOSE(DLLTEXT("IOemUni::OutputCharStr() entry.\r\n"));
  448. // When implemented, the return from GetImplementedMethod
  449. // for this method name must be S_OK.
  450. return E_NOTIMPL;
  451. }
  452. HRESULT __stdcall IOemUni::SendFontCmd(
  453. PDEVOBJ pdevobj,
  454. PUNIFONTOBJ pUFObj,
  455. PFINVOCATION pFInv)
  456. {
  457. VERBOSE(DLLTEXT("IOemUni::SendFontCmd() entry.\r\n"));
  458. // When implemented, the return from GetImplementedMethod
  459. // for this method name must be S_OK.
  460. return E_NOTIMPL;
  461. }
  462. HRESULT __stdcall IOemUni::DriverDMS(
  463. PVOID pDevObj,
  464. PVOID pBuffer,
  465. DWORD cbSize,
  466. PDWORD pcbNeeded)
  467. {
  468. VERBOSE(DLLTEXT("IOemUni::DriverDMS() entry.\r\n"));
  469. return E_NOTIMPL;
  470. }
  471. HRESULT __stdcall IOemUni::TextOutAsBitmap(
  472. SURFOBJ *pso,
  473. STROBJ *NAME_o,
  474. FONTOBJ *pfo,
  475. CLIPOBJ *pco,
  476. RECTL *prclExtra,
  477. RECTL *prclOpaque,
  478. BRUSHOBJ *pboFore,
  479. BRUSHOBJ *pboOpaque,
  480. POINTL *pptlOrg,
  481. MIX mix)
  482. {
  483. VERBOSE(DLLTEXT("IOemUni::TextOutAsBitmap() entry.\r\n"));
  484. // When implemented, the return from GetImplementedMethod
  485. // for this method name must be S_OK.
  486. return E_NOTIMPL;
  487. }
  488. HRESULT __stdcall IOemUni::TTYGetInfo(
  489. PDEVOBJ pdevobj,
  490. DWORD dwInfoIndex,
  491. PVOID pOutputBuf,
  492. DWORD dwSize,
  493. DWORD *pcbcNeeded)
  494. {
  495. VERBOSE(DLLTEXT("IOemUni::TTYGetInfo() entry.\r\n"));
  496. // When implemented, the return from GetImplementedMethod
  497. // for this method name must be S_OK.
  498. return E_NOTIMPL;
  499. }
  500. ////////////////////////////////////////////////////////////////////////////////
  501. //
  502. // oem class factory
  503. //
  504. class IOemCF : public IClassFactory
  505. {
  506. public:
  507. // *** IUnknown methods ***
  508. STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
  509. STDMETHOD_(ULONG,AddRef) (THIS);
  510. STDMETHOD_(ULONG,Release) (THIS);
  511. // *** IClassFactory methods ***
  512. STDMETHOD(CreateInstance) (THIS_
  513. LPUNKNOWN pUnkOuter,
  514. REFIID riid,
  515. LPVOID FAR* ppvObject);
  516. STDMETHOD(LockServer) (THIS_ BOOL bLock);
  517. // Constructor
  518. IOemCF(): m_cRef(1) { };
  519. ~IOemCF() { };
  520. protected:
  521. LONG m_cRef;
  522. };
  523. ///////////////////////////////////////////////////////////
  524. //
  525. // Class factory body
  526. //
  527. HRESULT __stdcall IOemCF::QueryInterface(const IID& iid, void** ppv)
  528. {
  529. if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
  530. {
  531. *ppv = static_cast<IOemCF*>(this);
  532. }
  533. else
  534. {
  535. *ppv = NULL;
  536. #if DBG && defined(USERMODE_DRIVER)
  537. TCHAR szOutput[80] = {0};
  538. StringFromGUID2(iid, szOutput, COUNTOF(szOutput)); // can not fail!
  539. VERBOSE(DLLTEXT("IOemCF::QueryInterface %s not supported.\r\n"), szOutput);
  540. #endif
  541. return E_NOINTERFACE;
  542. }
  543. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  544. return S_OK;
  545. }
  546. ULONG __stdcall IOemCF::AddRef()
  547. {
  548. return InterlockedIncrement(&m_cRef);
  549. }
  550. ULONG __stdcall IOemCF::Release()
  551. {
  552. ASSERT( 0 != m_cRef);
  553. ULONG cRef = InterlockedDecrement(&m_cRef);
  554. if (0 == cRef)
  555. {
  556. delete this;
  557. }
  558. return cRef;
  559. }
  560. // IClassFactory implementation
  561. HRESULT __stdcall IOemCF::CreateInstance(IUnknown* pUnknownOuter,
  562. const IID& iid,
  563. void** ppv)
  564. {
  565. //VERBOSE(DLLTEXT("Class factory:\t\tCreate component."));
  566. // Cannot aggregate.
  567. if (pUnknownOuter != NULL)
  568. {
  569. return CLASS_E_NOAGGREGATION;
  570. }
  571. // Create component.
  572. IOemUni* pOemCP = new IOemUni;
  573. if (pOemCP == NULL)
  574. {
  575. return E_OUTOFMEMORY;
  576. }
  577. // Get the requested interface.
  578. HRESULT hr = pOemCP->QueryInterface(iid, ppv);
  579. // Release the IUnknown pointer.
  580. // (If QueryInterface failed, component will delete itself.)
  581. pOemCP->Release();
  582. return hr;
  583. }
  584. // LockServer
  585. HRESULT __stdcall IOemCF::LockServer(BOOL bLock)
  586. {
  587. if (bLock)
  588. {
  589. InterlockedIncrement(&g_cServerLocks);
  590. }
  591. else
  592. {
  593. InterlockedDecrement(&g_cServerLocks);
  594. }
  595. return S_OK;
  596. }
  597. //
  598. // Registration functions
  599. //
  600. //
  601. // Can DLL unload now?
  602. //
  603. STDAPI DllCanUnloadNow()
  604. {
  605. //
  606. // To avoid leaving OEM DLL still in memory when Unidrv or Pscript drivers
  607. // are unloaded, Unidrv and Pscript driver ignore the return value of
  608. // DllCanUnloadNow of the OEM DLL, and always call FreeLibrary on the OEMDLL.
  609. //
  610. // If OEM DLL spins off a working thread that also uses the OEM DLL, the
  611. // thread needs to call LoadLibrary and FreeLibraryAndExitThread, otherwise
  612. // it may crash after Unidrv or Pscript calls FreeLibrary.
  613. //
  614. VERBOSE(DLLTEXT("DllCanUnloadNow entered.\r\n"));
  615. if ((g_cComponents == 0) && (g_cServerLocks == 0))
  616. {
  617. return S_OK;
  618. }
  619. else
  620. {
  621. return S_FALSE;
  622. }
  623. }
  624. //
  625. // Get class factory
  626. //
  627. STDAPI DllGetClassObject(const CLSID& clsid,
  628. const IID& iid,
  629. void** ppv)
  630. {
  631. VERBOSE(DLLTEXT("DllGetClassObject:\tCreate class factory.\r\n"));
  632. // Can we create this component?
  633. if (clsid != CLSID_OEMRENDER)
  634. {
  635. return CLASS_E_CLASSNOTAVAILABLE;
  636. }
  637. // Create class factory.
  638. IOemCF* pFontCF = new IOemCF; // Reference count set to 1
  639. // in constructor
  640. if (pFontCF == NULL)
  641. {
  642. return E_OUTOFMEMORY;
  643. }
  644. // Get requested interface.
  645. HRESULT hr = pFontCF->QueryInterface(iid, ppv);
  646. pFontCF->Release();
  647. return hr;
  648. }