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.

954 lines
23 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. oemkm.c
  5. Abstract:
  6. Kernel mode support for OEM plugins
  7. Environment:
  8. Windows NT Unidrv driver
  9. Revision History:
  10. 04/01/97 -zhanw-
  11. Adapted from Pscript source
  12. --*/
  13. #include "unidrv.h"
  14. #ifdef WINNT_40
  15. //
  16. // The global link list of ref counts for currently loaded OEM render plugin DLLs
  17. //
  18. POEM_PLUGIN_REFCOUNT gpOEMPluginRefCount;
  19. static const CHAR szDllInitialize[] = "DllInitialize";
  20. #endif // WINNT_40
  21. //
  22. // Unidrv specific OEM entrypoints
  23. //
  24. // NOTE: Please keep this in sync with indices defined in printer5\inc\oemutil.h!!!
  25. //
  26. static CONST PSTR OEMUnidrvProcNames[MAX_UNIDRV_ONLY_HOOKS] = {
  27. "OEMCommandCallback",
  28. "OEMImageProcessing",
  29. "OEMFilterGraphics",
  30. "OEMCompression",
  31. "OEMHalftonePattern",
  32. "OEMMemoryUsage",
  33. "OEMDownloadFontHeader",
  34. "OEMDownloadCharGlyph",
  35. "OEMTTDownloadMethod",
  36. "OEMOutputCharStr",
  37. "OEMSendFontCmd",
  38. "OEMTTYGetInfo",
  39. "OEMTextOutAsBitmap",
  40. "OEMWritePrinter",
  41. };
  42. static CONST PSTR COMUnidrvProcNames[MAX_UNIDRV_ONLY_HOOKS] = {
  43. "CommandCallback",
  44. "ImageProcessing",
  45. "FilterGraphics",
  46. "Compression",
  47. "HalftonePattern",
  48. "MemoryUsage",
  49. "DownloadFontHeader",
  50. "DownloadCharGlyph",
  51. "TTDownloadMethod",
  52. "OutputCharStr",
  53. "SendFontCmd",
  54. "TTYGetInfo",
  55. "TextOutAsBitmap",
  56. "WritePrinter",
  57. };
  58. //
  59. // OEM plugin helper function table
  60. //
  61. static const DRVPROCS OEMHelperFuncs = {
  62. (PFN_DrvWriteSpoolBuf) WriteSpoolBuf,
  63. (PFN_DrvXMoveTo) XMoveTo,
  64. (PFN_DrvYMoveTo) YMoveTo,
  65. (PFN_DrvGetDriverSetting) BGetDriverSettingForOEM,
  66. (PFN_DrvGetStandardVariable) BGetStandardVariable,
  67. (PFN_DrvUnidriverTextOut) FMTextOut,
  68. (PFN_DrvWriteAbortBuf) WriteAbortBuf,
  69. };
  70. INT
  71. IMapDDIIndexToOEMIndex(
  72. ULONG ulDdiIndex
  73. )
  74. /*++
  75. Routine Description:
  76. Maps DDI entrypoint index to OEM entrypoint index
  77. Arguments:
  78. ulDdiIndex - DDI entrypoint index
  79. Return Value:
  80. OEM entrypoint index corresponding to the specified DDI entrypoint index
  81. -1 if the specified DDI entrypoint cannot be hooked out by OEM plugins
  82. --*/
  83. {
  84. static const struct {
  85. ULONG ulDdiIndex;
  86. INT iOemIndex;
  87. }
  88. OemToDdiMapping[] =
  89. {
  90. INDEX_DrvRealizeBrush, EP_OEMRealizeBrush,
  91. INDEX_DrvDitherColor, EP_OEMDitherColor,
  92. INDEX_DrvCopyBits, EP_OEMCopyBits,
  93. INDEX_DrvBitBlt, EP_OEMBitBlt,
  94. INDEX_DrvStretchBlt, EP_OEMStretchBlt,
  95. #ifndef WINNT_40
  96. INDEX_DrvStretchBltROP, EP_OEMStretchBltROP,
  97. INDEX_DrvPlgBlt, EP_OEMPlgBlt,
  98. INDEX_DrvTransparentBlt, EP_OEMTransparentBlt,
  99. INDEX_DrvAlphaBlend, EP_OEMAlphaBlend,
  100. INDEX_DrvGradientFill, EP_OEMGradientFill,
  101. #endif
  102. INDEX_DrvTextOut, EP_OEMTextOut,
  103. INDEX_DrvStrokePath, EP_OEMStrokePath,
  104. INDEX_DrvFillPath, EP_OEMFillPath,
  105. INDEX_DrvStrokeAndFillPath, EP_OEMStrokeAndFillPath,
  106. INDEX_DrvPaint, EP_OEMPaint,
  107. INDEX_DrvLineTo, EP_OEMLineTo,
  108. INDEX_DrvStartPage, EP_OEMStartPage,
  109. INDEX_DrvSendPage, EP_OEMSendPage,
  110. INDEX_DrvEscape, EP_OEMEscape,
  111. INDEX_DrvStartDoc, EP_OEMStartDoc,
  112. INDEX_DrvEndDoc, EP_OEMEndDoc,
  113. INDEX_DrvNextBand, EP_OEMNextBand,
  114. INDEX_DrvStartBanding, EP_OEMStartBanding,
  115. INDEX_DrvQueryFont, EP_OEMQueryFont,
  116. INDEX_DrvQueryFontTree, EP_OEMQueryFontTree,
  117. INDEX_DrvQueryFontData, EP_OEMQueryFontData,
  118. INDEX_DrvQueryAdvanceWidths, EP_OEMQueryAdvanceWidths,
  119. INDEX_DrvFontManagement, EP_OEMFontManagement,
  120. INDEX_DrvGetGlyphMode, EP_OEMGetGlyphMode,
  121. };
  122. INT iIndex;
  123. INT iLimit = sizeof(OemToDdiMapping) / (sizeof(INT) * 2);
  124. for (iIndex=0; iIndex < iLimit; iIndex++)
  125. {
  126. if (OemToDdiMapping[iIndex].ulDdiIndex == ulDdiIndex)
  127. return OemToDdiMapping[iIndex].iOemIndex;
  128. }
  129. return -1;
  130. }
  131. BOOL
  132. BLoadAndInitOemPlugins(
  133. PDEV *pPDev
  134. )
  135. /*++
  136. Routine Description:
  137. Get information about OEM plugins associated with the current device
  138. Load them into memory and call OEMEnableDriver for each of them
  139. Arguments:
  140. pPDev - Points to our device data structure
  141. Return Value:
  142. TRUE if successful, FALSE if there is an error
  143. --*/
  144. {
  145. PFN_OEMEnableDriver pfnOEMEnableDriver;
  146. DRVENABLEDATA ded;
  147. DWORD dwCount;
  148. INT iIndex;
  149. PDRVFN pdrvfn;
  150. OEMPROC oemproc;
  151. //
  152. // Load OEM plugins into memory
  153. //
  154. pPDev->devobj.pDrvProcs = (PDRVPROCS) &OEMHelperFuncs;
  155. if (! (pPDev->pOemPlugins = PGetOemPluginInfo(pPDev->devobj.hPrinter,
  156. pPDev->pDriverInfo3->pDriverPath,
  157. pPDev->pDriverInfo3)) ||
  158. ! BLoadOEMPluginModules(pPDev->pOemPlugins))
  159. {
  160. return FALSE;
  161. }
  162. //
  163. // Init pdriverobj to point to devobj for OEM to access private setting
  164. //
  165. pPDev->pOemPlugins->pdriverobj = &pPDev->devobj;
  166. //
  167. // If there is no OEM plugin, return success
  168. //
  169. if (pPDev->pOemPlugins->dwCount == 0)
  170. return TRUE;
  171. //
  172. // Call OEM plugin's OEMEnableDriver entrypoint
  173. // and find out if any of them has hook out DDI entrypoints
  174. //
  175. pPDev->pOemHookInfo = MemAllocZ(sizeof(OEM_HOOK_INFO) * MAX_OEMHOOKS);
  176. if (pPDev->pOemHookInfo == NULL)
  177. return FALSE;
  178. START_OEMENTRYPOINT_LOOP(pPDev)
  179. // this macro defined in oemkm.h in conjunction with its partner END_OEMENTRYPOINT_LOOP,
  180. // acts like a for() loop initializing and incrementing pOemEntry each pass through the
  181. // loop.
  182. ZeroMemory(&ded, sizeof(ded));
  183. //
  184. // COM Plug-in case
  185. //
  186. if (pOemEntry->pIntfOem != NULL)
  187. {
  188. HRESULT hr;
  189. hr = HComOEMEnableDriver(pOemEntry,
  190. PRINTER_OEMINTF_VERSION,
  191. sizeof(ded),
  192. &ded);
  193. if (hr == E_NOTIMPL)
  194. goto UNIDRV_SPECIFIC;
  195. if (FAILED(hr))
  196. {
  197. ERR(("OEMEnableDriver failed for '%ws': %d\n",
  198. pOemEntry->ptstrDriverFile,
  199. GetLastError()));
  200. break;
  201. }
  202. }
  203. //
  204. // Non-COM Plug-in case
  205. //
  206. else
  207. {
  208. if (!(pfnOEMEnableDriver = GET_OEM_ENTRYPOINT(pOemEntry, OEMEnableDriver)))
  209. goto UNIDRV_SPECIFIC;
  210. //
  211. // Call OEM plugin's entrypoint
  212. //
  213. if (! pfnOEMEnableDriver(PRINTER_OEMINTF_VERSION, sizeof(ded), &ded))
  214. {
  215. ERR(("OEMEnableDriver failed for '%ws': %d\n",
  216. pOemEntry->ptstrDriverFile,
  217. GetLastError()));
  218. break;
  219. }
  220. //
  221. // Verify the driver version (do this only if not COM)
  222. //
  223. if (ded.iDriverVersion != PRINTER_OEMINTF_VERSION)
  224. {
  225. ERR(("Invalid driver version for '%ws': 0x%x\n",
  226. pOemEntry->ptstrDriverFile,
  227. ded.iDriverVersion));
  228. break;
  229. }
  230. }
  231. pOemEntry->dwFlags |= OEMENABLEDRIVER_CALLED;
  232. //
  233. // Check if OEM plugin has hooked out any DDI entrypoints
  234. //
  235. for (dwCount=ded.c, pdrvfn=ded.pdrvfn; dwCount-- > 0; pdrvfn++)
  236. {
  237. if ((iIndex = IMapDDIIndexToOEMIndex(pdrvfn->iFunc)) >= 0)
  238. {
  239. if (pPDev->pOemHookInfo[iIndex].pfnHook != NULL)
  240. {
  241. WARNING(("Multiple hooks for entrypoint: %d\n"
  242. " %ws\n"
  243. " %ws\n",
  244. iIndex,
  245. pOemEntry->ptstrDriverFile,
  246. pPDev->pOemHookInfo[iIndex].pOemEntry->ptstrDriverFile));
  247. }
  248. else
  249. {
  250. pPDev->pOemHookInfo[iIndex].pfnHook = (OEMPROC) pdrvfn->pfn;
  251. pPDev->pOemHookInfo[iIndex].pOemEntry = pOemEntry;
  252. }
  253. }
  254. }
  255. //
  256. // check if OEM plugin has any Unidrv-specific callbacks exported
  257. //
  258. UNIDRV_SPECIFIC:
  259. for (dwCount = 0; dwCount < MAX_UNIDRV_ONLY_HOOKS; dwCount++)
  260. {
  261. oemproc = NULL;
  262. if(pOemEntry->pIntfOem) // is this a COM component, do special processing
  263. {
  264. if(S_OK == HComGetImplementedMethod(pOemEntry, COMUnidrvProcNames[dwCount]) )
  265. oemproc = (OEMPROC)pOemEntry;
  266. // note oemproc/pfnHook only used as a BOOLEAN in COM path code.
  267. // do not use pfnHook to call a COM function! we will use
  268. // ganeshp's wrapper functions (declared in unidrv2\inc\oemkm.h) to do this.
  269. }
  270. else if (pOemEntry->hInstance != NULL)
  271. oemproc = (OEMPROC) GetProcAddress(pOemEntry->hInstance,
  272. OEMUnidrvProcNames[dwCount]) ;
  273. if(oemproc)
  274. {
  275. //
  276. // check if another OEM has already hooked out this function.
  277. // If so, ignore this one.
  278. //
  279. iIndex = dwCount + EP_UNIDRV_ONLY_FIRST;
  280. if (pPDev->pOemHookInfo[iIndex].pfnHook != NULL)
  281. {
  282. WARNING(("Multiple hooks for entrypoint: %d\n"
  283. " %ws\n"
  284. " %ws\n",
  285. iIndex,
  286. pOemEntry->ptstrDriverFile,
  287. pPDev->pOemHookInfo[iIndex].pOemEntry->ptstrDriverFile));
  288. }
  289. else
  290. {
  291. DWORD dwSize;
  292. HRESULT hr;
  293. pPDev->pOemHookInfo[iIndex].pfnHook = oemproc;
  294. pPDev->pOemHookInfo[iIndex].pOemEntry = pOemEntry;
  295. //
  296. // Set WritePrinter flag (OEMWRITEPRINTER_HOOKED).
  297. // Plug-in DLL needs to return S_OK with pBuff = NULL, size = 0,
  298. // and pdevobj = NULL.
  299. //
  300. if (iIndex == EP_OEMWritePrinter)
  301. {
  302. hr = HComWritePrinter(pOemEntry,
  303. NULL,
  304. NULL,
  305. 0,
  306. &dwSize);
  307. if (hr == S_OK)
  308. {
  309. //
  310. // Set WritePrinter hook flag in plug-in info.
  311. //
  312. pOemEntry->dwFlags |= OEMWRITEPRINTER_HOOKED;
  313. //
  314. // Set WritePrinter hook flag in UNIDRV PDEV.
  315. //
  316. pPDev->fMode2 |= PF2_WRITE_PRINTER_HOOKED;
  317. }
  318. }
  319. }
  320. }
  321. }
  322. END_OEMENTRYPOINT_LOOP
  323. //
  324. // cache callback function ptrs
  325. //
  326. pPDev->pfnOemCmdCallback =
  327. (PFN_OEMCommandCallback)pPDev->pOemHookInfo[EP_OEMCommandCallback].pfnHook;
  328. return TRUE;
  329. }
  330. VOID
  331. VUnloadOemPlugins(
  332. PDEV *pPDev
  333. )
  334. /*++
  335. Routine Description:
  336. Unload OEM plugins and free all relevant resources
  337. Arguments:
  338. pPDev - Points to our device data structure
  339. Return Value:
  340. NONE
  341. --*/
  342. {
  343. PFN_OEMDisableDriver pfnOEMDisableDriver;
  344. PFN_OEMDisablePDEV pfnOEMDisablePDEV;
  345. if (pPDev->pOemPlugins == NULL)
  346. return;
  347. //
  348. // Call OEMDisablePDEV for all OEM plugins, if necessary
  349. //
  350. START_OEMENTRYPOINT_LOOP(pPDev)
  351. if (pOemEntry->dwFlags & OEMENABLEPDEV_CALLED)
  352. {
  353. if (pOemEntry->pIntfOem != NULL)
  354. {
  355. (VOID)HComOEMDisablePDEV(pOemEntry, (PDEVOBJ)pPDev);
  356. }
  357. else
  358. {
  359. if (pfnOEMDisablePDEV = GET_OEM_ENTRYPOINT(pOemEntry, OEMDisablePDEV))
  360. {
  361. pfnOEMDisablePDEV((PDEVOBJ) pPDev);
  362. }
  363. }
  364. }
  365. END_OEMENTRYPOINT_LOOP
  366. //
  367. // Call OEMDisableDriver for all OEM plugins, if necessary
  368. //
  369. START_OEMENTRYPOINT_LOOP(pPDev)
  370. if (pOemEntry->dwFlags & OEMENABLEDRIVER_CALLED)
  371. {
  372. if (pOemEntry->pIntfOem != NULL)
  373. {
  374. (VOID)HComOEMDisableDriver(pOemEntry);
  375. }
  376. else
  377. {
  378. if ((pfnOEMDisableDriver = GET_OEM_ENTRYPOINT(pOemEntry, OEMDisableDriver)))
  379. {
  380. pfnOEMDisableDriver();
  381. }
  382. }
  383. }
  384. END_OEMENTRYPOINT_LOOP
  385. MemFree(pPDev->pOemHookInfo);
  386. pPDev->pOemHookInfo = NULL;
  387. VFreeOemPluginInfo(pPDev->pOemPlugins);
  388. pPDev->pOemPlugins = NULL;
  389. }
  390. BOOL
  391. BGetDriverSettingForOEM(
  392. PDEV *pPDev,
  393. PCSTR pFeatureKeyword,
  394. PVOID pOutput,
  395. DWORD cbSize,
  396. PDWORD pcbNeeded,
  397. PDWORD pdwOptionsReturned
  398. )
  399. /*++
  400. Routine Description:
  401. Provide OEM plugins access to driver private settings
  402. Arguments:
  403. pDev - Points to our device data structure
  404. pFeatureKeyword - Specifies the keyword the caller is interested in
  405. pOutput - Points to output buffer
  406. cbSize - Size of output buffer
  407. pcbNeeded - Returns the expected size of output buffer
  408. pdwOptionsReturned - Returns the number of options selected
  409. Return Value:
  410. TRUE if successful, FALSE if there is an error
  411. --*/
  412. {
  413. ULONG_PTR dwIndex;
  414. BOOL bResult;
  415. ASSERT_VALID_PDEV(pPDev);
  416. //
  417. // This is not very portable: If the pointer value for pFeatureKeyword
  418. // is less than 0x10000, we assume that the pointer value actually
  419. // specifies a predefined index.
  420. //
  421. // ASSERT(sizeof(pFeatureKeyword) == sizeof(DWORD)); changed for sundown
  422. dwIndex = (ULONG_PTR) pFeatureKeyword;
  423. if (dwIndex >= OEMGDS_MIN_DOCSTICKY && dwIndex < OEMGDS_MIN_PRINTERSTICKY)
  424. {
  425. bResult = BGetDevmodeSettingForOEM(
  426. pPDev->pdm,
  427. (DWORD)dwIndex,
  428. pOutput,
  429. cbSize,
  430. pcbNeeded);
  431. if (bResult)
  432. *pdwOptionsReturned = 1;
  433. }
  434. else if (dwIndex >= OEMGDS_MIN_PRINTERSTICKY && dwIndex < OEMGDS_MAX)
  435. {
  436. bResult = BGetPrinterDataSettingForOEM(
  437. &pPDev->PrinterData,
  438. (DWORD)dwIndex,
  439. pOutput,
  440. cbSize,
  441. pcbNeeded);
  442. if (bResult)
  443. *pdwOptionsReturned = 1;
  444. }
  445. else
  446. {
  447. bResult = BGetGenericOptionSettingForOEM(
  448. pPDev->pUIInfo,
  449. pPDev->pOptionsArray,
  450. pFeatureKeyword,
  451. pOutput,
  452. cbSize,
  453. pcbNeeded,
  454. pdwOptionsReturned);
  455. }
  456. return bResult;
  457. }
  458. BOOL
  459. BGetStandardVariable(
  460. PDEV *pPDev,
  461. DWORD dwIndex,
  462. PVOID pBuffer,
  463. DWORD cbSize,
  464. PDWORD pcbNeeded
  465. )
  466. /*++
  467. Routine Description:
  468. Provide OEM plugins access to driver private settings
  469. Arguments:
  470. pDev - Points to our device data structure
  471. dwIndex - an index into the arStdPtr array defined in pdev.h and gpd.h
  472. pBuffer - the data is returned in this buffer
  473. cbSize - size of the pBuffer
  474. pcbNeeded - number of bytes actually written into pBuffer
  475. Return Value:
  476. TRUE if successful, FALSE if there is an error
  477. --*/
  478. {
  479. BOOL bResult = FALSE;
  480. DWORD dwData;
  481. if (dwIndex >= SVI_MAX) // how could a DWORD be < 0?
  482. {
  483. ERR(("Index must be >= 0 or < SVI_MAX \n"));
  484. return( FALSE);
  485. }
  486. else
  487. {
  488. if(!pcbNeeded)
  489. {
  490. ERR(("pcbNeeded must not be NULL \n"));
  491. return( FALSE);
  492. }
  493. *pcbNeeded = sizeof(dwData);
  494. if(!pBuffer)
  495. return(TRUE);
  496. if(*pcbNeeded > cbSize)
  497. return(FALSE);
  498. dwData = *(pPDev->arStdPtrs[dwIndex]);
  499. memcpy( pBuffer, &dwData, *pcbNeeded );
  500. bResult = TRUE;
  501. }
  502. return bResult;
  503. }
  504. BOOL
  505. BGetGPDData(
  506. PDEV *pPDev,
  507. DWORD dwType, // Type of the data
  508. PVOID pInputData, // reserved. Should be set to 0
  509. PVOID pBuffer, // Caller allocated Buffer to be copied
  510. DWORD cbSize, // Size of the buffer
  511. PDWORD pcbNeeded // New Size of the buffer if needed.
  512. )
  513. /*++
  514. Routine Description:
  515. Provide OEM plugins access to GPD data.
  516. Arguments:
  517. pDev - Points to our device data structure
  518. dwType, // Type of the data
  519. at this time
  520. #define GPD_OEMCUSTOMDATA 1
  521. pInputData will be ignored.
  522. In NT6, we will
  523. #define GPD_OEMDATA 2
  524. at which time the caller will supply pInputData
  525. which points to a data specifier , catagory or label.
  526. (Specifics to be determined when we get there.)
  527. pInputData - reserved. Should be set to 0
  528. pBuffer - the data is returned in this buffer
  529. cbSize - size of the pBuffer
  530. pcbNeeded - number of bytes actually written into pBuffer
  531. Return Value:
  532. TRUE if successful, FALSE if there is an error or dwType not
  533. supported
  534. --*/
  535. {
  536. BOOL bResult = FALSE;
  537. DWORD dwData;
  538. if(!pcbNeeded)
  539. {
  540. ERR(("pcbNeeded must not be NULL \n"));
  541. return( FALSE);
  542. }
  543. switch(dwType)
  544. {
  545. case GPD_OEMCUSTOMDATA:
  546. *pcbNeeded = pPDev->pGlobals->dwOEMCustomData ;
  547. if( !pBuffer)
  548. {
  549. return TRUE; // all goes well.
  550. }
  551. if(*pcbNeeded > cbSize)
  552. return FALSE ; // caller supplied buffer too small.
  553. CopyMemory(pBuffer,
  554. pPDev->pGlobals->pOEMCustomData,
  555. *pcbNeeded);
  556. return TRUE; // all goes well.
  557. break;
  558. default:
  559. break;
  560. }
  561. return bResult ;
  562. }
  563. #ifdef WINNT_40
  564. PVOID
  565. DrvMemAllocZ(
  566. ULONG ulSize
  567. )
  568. /*++
  569. Routine Description:
  570. Arguments:
  571. Return Value:
  572. --*/
  573. {
  574. return(MemAllocZ(ulSize));
  575. }
  576. VOID
  577. DrvMemFree(
  578. PVOID pMem
  579. )
  580. /*++
  581. Routine Description:
  582. Arguments:
  583. Return Value:
  584. --*/
  585. {
  586. MemFree(pMem);
  587. }
  588. LONG
  589. DrvInterlockedIncrement(
  590. PLONG pRef
  591. )
  592. /*++
  593. Routine Description:
  594. Arguments:
  595. Return Value:
  596. --*/
  597. {
  598. ENTER_CRITICAL_SECTION();
  599. ++(*pRef);
  600. LEAVE_CRITICAL_SECTION();
  601. return (*pRef);
  602. }
  603. LONG
  604. DrvInterlockedDecrement(
  605. PLONG pRef
  606. )
  607. /*++
  608. Routine Description:
  609. Arguments:
  610. Return Value:
  611. --*/
  612. {
  613. ENTER_CRITICAL_SECTION();
  614. --(*pRef);
  615. LEAVE_CRITICAL_SECTION();
  616. return (*pRef);
  617. }
  618. BOOL
  619. BHandleOEMInitialize(
  620. POEM_PLUGIN_ENTRY pOemEntry,
  621. ULONG ulReason
  622. )
  623. /*++
  624. Routine Description:
  625. Manage reference counting for OEM render plugin DLLs to determine
  626. when plugin's DLLInitliaze() should be called.
  627. This function is supported only for NT4 kernel mode render plugin
  628. DLLs because only in that situation plugin needs to use kernel
  629. semaphore to implement COM's AddRef and Release.
  630. If the plugin DLL is loaded for the first time, call its
  631. DLLInitialize(DLL_PROCESS_ATTACH) so it can initialize its
  632. semaphore.
  633. If the plugin DLL is unloaded by its last client, call its
  634. DLLInitialize(DLL_PROCESS_DETACH) so it can delete its
  635. semaphore.
  636. Arguments:
  637. pOemEntry - Points to information about the OEM plugin
  638. ulReason - either DLL_PROCESS_ATTACH or DLL_PROCESS_DETACH
  639. Return Value:
  640. TRUE is succeeded, FALSE otherwise.
  641. --*/
  642. {
  643. LPFNDLLINITIALIZE pfnDllInitialize;
  644. BOOL bCallDllInitialize;
  645. BOOL bRetVal = TRUE;
  646. if (pOemEntry->hInstance &&
  647. (pfnDllInitialize = (LPFNDLLINITIALIZE)GetProcAddress(
  648. (HMODULE) pOemEntry->hInstance,
  649. (CHAR *) szDllInitialize)))
  650. {
  651. switch (ulReason) {
  652. case DLL_PROCESS_ATTACH:
  653. ENTER_CRITICAL_SECTION();
  654. //
  655. // Managing the global ref count link list must be done
  656. // inside critical section.
  657. //
  658. bCallDllInitialize = BOEMPluginFirstLoad(pOemEntry->ptstrDriverFile,
  659. &gpOEMPluginRefCount);
  660. LEAVE_CRITICAL_SECTION();
  661. if (bCallDllInitialize)
  662. {
  663. //
  664. // The render plugin DLL is loaded for the first time.
  665. //
  666. bRetVal = pfnDllInitialize(ulReason);
  667. }
  668. break;
  669. case DLL_PROCESS_DETACH:
  670. ENTER_CRITICAL_SECTION();
  671. //
  672. // Managing the global ref count link list must be done
  673. // inside critical section.
  674. //
  675. bCallDllInitialize = BOEMPluginLastUnload(pOemEntry->ptstrDriverFile,
  676. &gpOEMPluginRefCount);
  677. LEAVE_CRITICAL_SECTION();
  678. if (bCallDllInitialize)
  679. {
  680. //
  681. // The render plugin DLL is unloaded by its last client.
  682. //
  683. bRetVal = pfnDllInitialize(ulReason);
  684. }
  685. break;
  686. default:
  687. ERR(("BHandleOEMInitialize is called with an unknown ulReason.\n"));
  688. break;
  689. }
  690. }
  691. return bRetVal;
  692. }
  693. #endif // WINNT_40