Source code of Windows XP (NT5)
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.

1203 lines
34 KiB

  1. /******************************************************************************
  2. Copyright (c) 1985-1998 Microsoft Corporation
  3. Title: drvrrare.c - Installable driver code. Less common code
  4. Version: 1.00
  5. Date: 10-Jun-1990
  6. Author: DAVIDDS ROBWI
  7. ------------------------------------------------------------------------------
  8. Change log:
  9. DATE REV DESCRIPTION
  10. ----------- ----- -----------------------------------------------------------
  11. 28-FEB-1992 ROBINSP Port to NT
  12. 23-Apr-1992 StephenE Unicoded
  13. 22-Apr-1993 RobinSp Add NT multithread protection
  14. Multithread design :
  15. Uses 2 critical sections :
  16. DriverListCritSec :
  17. protects the list of drivers :
  18. hInstalledDriverList - handle of global driver list
  19. cInstalledDrivers - high water mark of installed drivers
  20. so that only 1 thread at a time has the list locked and can refer
  21. to or update it.
  22. DriverLoadFreeCritSec
  23. Makes sure that actual loads and frees of drivers don't overlap
  24. and that the actual loading of a driver via LoadLibrary coincides
  25. with its first message being DRV_LOAD.
  26. This can easily happen if the DRV_OPEN from another thread can get
  27. in before the DRV_LOAD has been sent.
  28. *****************************************************************************/
  29. #include <nt.h>
  30. #include <ntrtl.h>
  31. #include <nturtl.h>
  32. #define MMNOSOUND
  33. #define MMNOWAVE
  34. #define MMNOMIDI
  35. #define MMNOSEQ
  36. #define MMNOTIMER
  37. #define MMNOJOY
  38. #define MMNOMCI
  39. #define NOTIMERDEV
  40. #define NOJOYDEV
  41. #define NOMCIDEV
  42. #define NOSEQDEV
  43. #define NOWAVEDEV
  44. #define NOMIDIDEV
  45. #define NOTASKDEV
  46. #include <winmmi.h>
  47. #include "drvr.h"
  48. extern HANDLE hInstalledDriverList; // List of installed driver instances
  49. extern int cInstalledDrivers; // High water count of installed driver instances
  50. extern DWORD FAR PASCAL DriverProc(DWORD dwID, HDRVR hdrv, UINT msg, DWORD dw1, DWORD dw2);
  51. /* Support for using 3.1 APIs if available */
  52. typedef HANDLE (FAR PASCAL *OPENDRIVER31)(LPCSTR, LPCSTR, LPARAM);
  53. typedef LONG (FAR PASCAL *CLOSEDRIVER31)(HANDLE, LPARAM, LPARAM);
  54. typedef HANDLE (FAR PASCAL *GETDRIVERMODULEHANDLE31)(HANDLE);
  55. typedef LONG (FAR PASCAL *SENDDRIVERMESSAGE31)(HANDLE, UINT, LPARAM, LPARAM);
  56. typedef LONG (FAR PASCAL *DEFDRIVERPROC31)(DWORD, HANDLE, UINT, LPARAM, LPARAM);
  57. OPENDRIVER31 lpOpenDriver;
  58. CLOSEDRIVER31 lpCloseDriver;
  59. GETDRIVERMODULEHANDLE31 lpGetDriverModuleHandle;
  60. SENDDRIVERMESSAGE31 lpSendDriverMessage;
  61. DEFDRIVERPROC31 lpDefDriverProc;
  62. #if 0
  63. BOOL fUseWinAPI = 0;
  64. // NOTE: fUseWinAPI is not being used at present
  65. // as we only have a partial device loading story
  66. #endif
  67. /***************************************************************************
  68. strings
  69. ****************************************************************************/
  70. #if 0
  71. extern char far szBoot[];
  72. extern char far szUser[];
  73. extern char far szOpenDriver[];
  74. extern char far szCloseDriver[];
  75. extern char far szDrvModuleHandle[];
  76. extern char far szSendDriverMessage[];
  77. extern char far szDefDriverProc[];
  78. extern char far szDriverProc[];
  79. #endif
  80. /***************************************************************************
  81. *
  82. * @doc DDK
  83. *
  84. * @api LONG | DrvClose | This function closes an open driver
  85. * instance and decrements
  86. * the driver's open count. Once the driver's open count becomes zero,
  87. * the driver is unloaded.
  88. *
  89. * @parm HANDLE | hDriver | Specifies the handle of the installable
  90. * driver to close.
  91. *
  92. * @parm LPARAM | lParam1 | Specifies the first message parameter for
  93. * the DRV_CLOSE message. This data is passed directly to the driver.
  94. *
  95. * @parm LPARAM | lParam2 | Specifies the second message parameter
  96. * for DRV_CLOSE message. This data is passed directly to the driver.
  97. *
  98. * @rdesc Returns zero if the driver aborted the close;
  99. * otherwise, returns the return result from the driver.
  100. * @xref DrvOpen
  101. *
  102. ***************************************************************************/
  103. LRESULT APIENTRY DrvClose(HANDLE hDriver, LPARAM lParam1, LPARAM lParam2)
  104. {
  105. /* The driver will receive the following message sequence:
  106. *
  107. * DRV_CLOSE
  108. * if DRV_CLOSE returns non-zero
  109. * if driver usage count = 1
  110. * DRV_DISABLE
  111. * DRV_FREE
  112. */
  113. if (fUseWinAPI)
  114. return ((*lpCloseDriver)(hDriver, lParam1, lParam2));
  115. else
  116. return InternalCloseDriver((UINT)(UINT_PTR)hDriver, lParam1, lParam2, TRUE);
  117. }
  118. /***************************************************************************
  119. *
  120. * @doc DDK
  121. *
  122. * @api LONG | DrvOpen | This function opens an installable driver.
  123. * The first time a driver is opened it is loaded
  124. * and enabled. A driver must be opened before messages are sent
  125. * to it.
  126. *
  127. * @parm LPSTR | szDriverName | Specifies a far pointer to a
  128. * null-terminated character string
  129. * containing a driver filename or a keyname from a
  130. * section of the SYSTEM.INI file.
  131. *
  132. * @parm LPSTR | szSectionName | Specifies a far pointer to a
  133. * null-terminated character string containing the name of
  134. * the driver section to search. If <p szSectionName> is
  135. * not null, the specified section of the SYSTEM.INI file is
  136. * searched instead of the [Drivers] section. If
  137. * <p szSectionName> is null, the default [Drivers] section is used.
  138. *
  139. * @parm LPARAM | lParam | Specifies a message parameter to
  140. * pass to the driver procedure with the <m DRV_OPEN> message.
  141. *
  142. * @rdesc Returns a handle to the driver.
  143. *
  144. * @comm Installable drivers must export a <f DriverProc> routine of
  145. * the form:
  146. *
  147. * @cb LONG FAR PASCAL | DriverProc | This entry point receives the
  148. * messages sent to an installable driver. This entry will always
  149. * handle the system messages as a minimum set of messages.
  150. *
  151. * @parm DWORD | dwDriverIdentifier | Specifies the device driver
  152. * identifier.
  153. *
  154. * @parm HANDLE | hDriver | Specifies the device driver handle.
  155. *
  156. * @parm UINT | wMessage | Specifies the message for the device
  157. * driver.
  158. *
  159. * @parm LONG | lParm1 | Specifies message dependent data.
  160. *
  161. * @parm LONG | lParm2 | Specifies message dependent data.
  162. *
  163. * @xref DrvClose
  164. *
  165. ****************************************************************************/
  166. HANDLE APIENTRY DrvOpen( LPCWSTR szDriverName,
  167. LPCWSTR szSectionName,
  168. LPARAM lParam2)
  169. {
  170. /* The driver will receive the following message sequence:
  171. *
  172. * if driver not loaded and can be found
  173. * DRV_LOAD
  174. * if DRV_LOAD returns non-zero
  175. * DRV_ENABLE
  176. * if driver loaded correctly
  177. * DRV_OPEN
  178. */
  179. HDRVR hdrv;
  180. if (fUseWinAPI) {
  181. /*------------------------------------------------------------*\
  182. * UNICODE: convert szDriver and szSectionName to ascii
  183. * and then call WIN31 driver
  184. \*------------------------------------------------------------*/
  185. LPSTR aszDriver;
  186. LPSTR aszSectionName;
  187. INT lenD;
  188. INT lenS;
  189. lenD = lstrlenW( szDriverName ) * sizeof( WCHAR ) + sizeof( WCHAR );
  190. aszDriver = HeapAlloc( hHeap, 0, lenD );
  191. if ( aszDriver == (LPSTR)NULL ) {
  192. return NULL;
  193. }
  194. lenS = lstrlenW( szSectionName ) * sizeof( WCHAR ) + sizeof( WCHAR );
  195. aszSectionName = HeapAlloc( hHeap, 0, lenS );
  196. if ( aszSectionName == (LPSTR)NULL ) {
  197. HeapFree( hHeap, 0, aszDriver );
  198. return NULL;
  199. }
  200. // Unicode to Ascii
  201. UnicodeStrToAsciiStr( (PBYTE)aszDriver,
  202. (PBYTE)aszDriver + lenD,
  203. szDriverName );
  204. UnicodeStrToAsciiStr( (PBYTE)aszSectionName,
  205. (PBYTE)aszSectionName + lenS,
  206. szSectionName );
  207. hdrv = (HDRVR)((*lpOpenDriver)( aszDriver, aszSectionName, lParam2 ));
  208. HeapFree( hHeap, 0, aszDriver );
  209. HeapFree( hHeap, 0, aszSectionName );
  210. }
  211. else {
  212. dprintf2(("DrvOpen(%ls), Looking in Win.ini [%ls]", szDriverName, szSectionName ? szSectionName : L"NULL !!" ));
  213. hdrv = (HDRVR)InternalOpenDriver(szDriverName, szSectionName, lParam2, TRUE);
  214. }
  215. #if DBG
  216. if (hdrv) {
  217. WCHAR ach[255];
  218. static SZCODE szFormat[] = "DrvOpen(): Opened %ls (%ls)\r\n";
  219. GetModuleFileNameW( DrvGetModuleHandle( hdrv ),
  220. ach,
  221. sizeof(ach) / sizeof(WCHAR)
  222. );
  223. dprintf2((szFormat, szDriverName, ach));
  224. }
  225. #endif
  226. return (HANDLE)hdrv;
  227. }
  228. /***************************************************************************
  229. *
  230. * @doc DDK
  231. *
  232. * @api HANDLE | DrvGetModuleHandle | This function returns the library
  233. * module handle of the specified installable driver.
  234. *
  235. * @parm HANDLE | hDriver | Specifies the handle of the installable driver.
  236. *
  237. * @rdesc Returns the module handle of the driver specified by the
  238. * driver handle <p hDriver>.
  239. *
  240. * @comm A module handle is not the same as an installable driver handle.
  241. *
  242. ***************************************************************************/
  243. HMODULE APIENTRY DrvGetModuleHandle(HDRVR hDriver)
  244. {
  245. LPDRIVERTABLE lpdt;
  246. HMODULE h = 0;
  247. if (fUseWinAPI)
  248. return ((*lpGetDriverModuleHandle)(hDriver));
  249. DrvEnter();
  250. if (hDriver && ((int)(UINT_PTR)hDriver <= cInstalledDrivers))
  251. {
  252. lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
  253. h = (HMODULE)lpdt[(UINT)(UINT_PTR)hDriver-1].hModule;
  254. GlobalUnlock(hInstalledDriverList);
  255. }
  256. DrvLeave();
  257. return(h);
  258. }
  259. LRESULT FAR PASCAL InternalCloseDriver(UINT hDriver,
  260. LPARAM lParam1,
  261. LPARAM lParam2,
  262. BOOL fSendDisable)
  263. {
  264. LRESULT result;
  265. // check handle in valid range.
  266. DrvEnter();
  267. if ((int)hDriver > cInstalledDrivers) {
  268. DrvLeave();
  269. return(FALSE);
  270. }
  271. DrvLeave();
  272. result = DrvSendMessage((HANDLE)(UINT_PTR)hDriver, DRV_CLOSE, lParam1, lParam2);
  273. if (result) {
  274. InternalFreeDriver(hDriver, fSendDisable);
  275. }
  276. return(result);
  277. }
  278. LRESULT FAR PASCAL InternalOpenDriver( LPCWSTR szDriverName,
  279. LPCWSTR szSectionName,
  280. LPARAM lParam2,
  281. BOOL fSendEnable)
  282. {
  283. DWORD_PTR hDriver;
  284. LPDRIVERTABLE lpdt;
  285. LRESULT result;
  286. WCHAR sz[128];
  287. if (0 != (hDriver = InternalLoadDriver( szDriverName,
  288. szSectionName,
  289. sz,
  290. sizeof(sz) / sizeof(WCHAR),
  291. fSendEnable ) ) )
  292. {
  293. /*
  294. * Set the driver identifier to the DRV_OPEN call to the
  295. * driver handle. This will let people build helper functions
  296. * that the driver can call with a unique identifier if they
  297. * want to.
  298. */
  299. DrvEnter();
  300. lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
  301. lpdt[hDriver-1].dwDriverIdentifier = (DWORD)hDriver;
  302. GlobalUnlock(hInstalledDriverList);
  303. DrvLeave();
  304. result = DrvSendMessage( (HANDLE)hDriver, DRV_OPEN, (LPARAM)(LPSTR)sz,
  305. lParam2);
  306. if (!result) {
  307. dprintf1(("DrvSendMessage failed, result = %8x",result));
  308. InternalFreeDriver((UINT)hDriver, fSendEnable);
  309. } else {
  310. DrvEnter();
  311. lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
  312. lpdt[hDriver-1].dwDriverIdentifier = result;
  313. GlobalUnlock(hInstalledDriverList);
  314. DrvLeave();
  315. result = hDriver;
  316. }
  317. }
  318. else
  319. result = 0L;
  320. return result;
  321. }
  322. /***************************************************************************
  323. *
  324. * @doc INTERNAL
  325. *
  326. * @api LONG | InternalLoadDriver | Loads an installable driver. If this is
  327. * the first time that the driver is opened, the driver will be loaded
  328. * and enabled.
  329. *
  330. * @parm LPSTR | szDriverName | A null-terminated character string
  331. * containing a driver filename or a keyname from the [Drivers]
  332. * section of system.ini.
  333. *
  334. * @parm LPSTR | szSectionName | A null-terminated character string
  335. * that specifies a driver section to search. If szSectionName is
  336. * not null, the specified section of system.ini is searched instead
  337. * of the [Drivers] section. If szSectionName is null, the
  338. * default [Drivers] section is used.
  339. *
  340. * @parm LPSTR | lpstrTail | caller supplied buffer to return the "tail"
  341. * of the system.ini line in. The tail is any characters that follow
  342. * the filename.
  343. *
  344. * @parm UINT | cbTail | size of supplied buffer as a character count.
  345. *
  346. * @parm BOOL | fSendEnable | TRUE if driver should be enabled
  347. *
  348. * @rdesc Returns a long whose loword is the handle to the driver and whose
  349. * high word is an error code or the module handle
  350. *
  351. * @xref InternalOpenDriver
  352. *
  353. ****************************************************************************/
  354. LRESULT FAR PASCAL InternalLoadDriver(LPCWSTR szDriverName,
  355. LPCWSTR szSectionName,
  356. LPWSTR lpstrTail,
  357. UINT cbTail,
  358. BOOL fSendEnable)
  359. {
  360. int index;
  361. LPDRIVERTABLE lpdt;
  362. LONG result;
  363. HANDLE h;
  364. DRIVERPROC lpDriverEntryPoint;
  365. /* The driver will receive the following message sequence:
  366. *
  367. * if driver not loaded and can be found
  368. * DRV_LOAD
  369. * if DRV_LOAD returns non-zero and fSendEnable
  370. * DRV_ENABLE
  371. */
  372. /* Allocate a table entry */
  373. // This can be made more efficient by keeping a count of how many drivers
  374. // we have loaded and how many entries there are in the table. Then when
  375. // we should reuse an entry we would not reallocate - unlike at present.
  376. DrvEnter();
  377. if (!hInstalledDriverList) {
  378. h = GlobalAlloc(GHND, (DWORD)((UINT)sizeof(DRIVERTABLE)));
  379. // Note: it is valid to assume that the memory has been ZERO'ed
  380. // ...might want to add a debug WinAssert to verify...
  381. } else {
  382. /* Alloc space for the next driver we will install. We may not really
  383. * install the driver in the last entry but rather in an intermediate
  384. * entry which was freed.
  385. */
  386. h = GlobalReAlloc(hInstalledDriverList,
  387. (DWORD)((UINT)sizeof(DRIVERTABLE)*(cInstalledDrivers+1)),
  388. GHND);
  389. // Note: it is valid to assume that the new memory has been ZERO'ed
  390. // ...might want to add a debug WinAssert to verify...
  391. }
  392. if (!h) {
  393. dprintf1(("Failed to allocate space for Installed driver list"));
  394. DrvLeave();
  395. return(0L);
  396. }
  397. cInstalledDrivers++;
  398. hInstalledDriverList = h;
  399. lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
  400. /* find an unused entry in the table */
  401. for (index=0;index<cInstalledDrivers;index++)
  402. {
  403. if (lpdt[index].hModule == 0 && !lpdt[index].fBusy)
  404. break;
  405. }
  406. if (index+1 < cInstalledDrivers) {
  407. /* The driver went into an unused entry in the middle somewhere so
  408. * restore table size.
  409. */
  410. cInstalledDrivers--;
  411. }
  412. /* Protect the entry we just allocated so that OpenDriver
  413. * can be called at any point from now on without overriding
  414. * the entry
  415. */
  416. lpdt[index].fBusy = 1;
  417. GlobalUnlock(hInstalledDriverList);
  418. DrvLeave();
  419. /*
  420. * Make sure Loadlibrary and DRV_LOAD messages to driver are consistent
  421. */
  422. EnterCriticalSection(&DriverLoadFreeCritSec);
  423. h = LoadAliasedLibrary( szDriverName,
  424. szSectionName ? szSectionName : wszDrivers,
  425. wszSystemIni,
  426. lpstrTail,
  427. cbTail );
  428. if (0 == h)
  429. {
  430. dprintf1(("Failed to LoadLibrary %ls Error is %d", szDriverName, GetLastError()));
  431. LeaveCriticalSection(&DriverLoadFreeCritSec);
  432. result = 0;
  433. goto LoadCleanUp;
  434. }
  435. lpDriverEntryPoint =
  436. (DRIVERPROC)GetProcAddress(h, DRIVER_PROC_NAME);
  437. if (lpDriverEntryPoint == NULL)
  438. {
  439. // Driver does not have correct entry point
  440. dprintf1(("Cannot find entry point %ls in %ls", DRIVER_PROC_NAME, szDriverName));
  441. FreeLibrary(h);
  442. LeaveCriticalSection(&DriverLoadFreeCritSec);
  443. result = 0L;
  444. goto LoadCleanUp;
  445. }
  446. DrvEnter();
  447. lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
  448. lpdt[index].lpDriverEntryPoint = lpDriverEntryPoint;
  449. // Set hModule here so that GetDrvrUsage() and DrvSendMessage() work
  450. lpdt[index].hModule = (UINT_PTR)h;
  451. GlobalUnlock(hInstalledDriverList);
  452. DrvLeave();
  453. if (GetDrvrUsage(h) == 1)
  454. {
  455. LRESULT LoadResult;
  456. // First instance of the driver.
  457. LoadResult = DrvSendMessage((HANDLE)(UINT_PTR)(index+1), DRV_LOAD, 0L, 0L);
  458. DrvEnter();
  459. lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
  460. if (!LoadResult)
  461. {
  462. // Driver failed load call.
  463. lpdt[index].lpDriverEntryPoint = NULL;
  464. lpdt[index].hModule = (UINT_PTR)NULL;
  465. GlobalUnlock(hInstalledDriverList);
  466. DrvLeave();
  467. FreeLibrary(h);
  468. LeaveCriticalSection(&DriverLoadFreeCritSec);
  469. result = 0L;
  470. goto LoadCleanUp;
  471. }
  472. lpdt[index].fFirstEntry = 1;
  473. GlobalUnlock(hInstalledDriverList);
  474. DrvLeave();
  475. if (fSendEnable) {
  476. DrvSendMessage((HANDLE)(UINT_PTR)(index+1), DRV_ENABLE, 0L, 0L);
  477. }
  478. }
  479. LeaveCriticalSection(&DriverLoadFreeCritSec);
  480. result = index + 1;
  481. LoadCleanUp:
  482. DrvEnter();
  483. lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
  484. lpdt[index].fBusy = 0;
  485. GlobalUnlock(hInstalledDriverList);
  486. DrvLeave();
  487. return(result);
  488. }
  489. /***************************************************************************
  490. *
  491. * @doc INTERNAL
  492. *
  493. * @api UINT | InternalFreeDriver | This function decrements the usage
  494. * count of the specified driver. When the driver usage count reaches
  495. * 0, the driver is sent a DRV_FREE message and then freed.
  496. *
  497. * @parm HANDLE | hDriver | Driver handle of the installable driver to be
  498. * freed.
  499. *
  500. * @parm BOOL | fSendDisable | TRUE if a DRV_DISABLE message should be sent
  501. * before the DRV_FREE message if the usage count reaches zero.
  502. *
  503. * @rdesc Returns current driver usage count.
  504. *
  505. * @comm Using LoadLibrary or FreeLibrary directly on a library installed
  506. * with OpenDriver will break this function. A module handle is not
  507. * the same as an installable driver handle.
  508. *
  509. * @xref CloseDriver
  510. *
  511. ***************************************************************************/
  512. UINT FAR PASCAL InternalFreeDriver(UINT hDriver, BOOL fSendDisable)
  513. {
  514. LPDRIVERTABLE lpdt;
  515. UINT w;
  516. int index;
  517. HMODULE hModule;
  518. /* The driver will receive the following message sequence:
  519. *
  520. * if usage count of driver is 1
  521. * DRV_DISABLE (normally)
  522. * DRV_FREE
  523. */
  524. EnterCriticalSection(&DriverLoadFreeCritSec);
  525. DrvEnter();
  526. if ((int)hDriver > cInstalledDrivers || !hDriver) {
  527. DrvLeave();
  528. LeaveCriticalSection(&DriverLoadFreeCritSec);
  529. return(0);
  530. }
  531. lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
  532. /*
  533. * If the driver usage count is 1, then send
  534. * free and disable messages.
  535. */
  536. /*
  537. Clear dwDriverIdentifier so that the sendmessage for
  538. DRV_OPEN and DRV_ENABLE have dwDriverIdentifier = 0
  539. if an entry gets reused and so that the DRV_DISABLE and DRV_FREE
  540. messages below also get dwDriverIdentifier = 0.
  541. */
  542. lpdt[hDriver-1].dwDriverIdentifier = 0;
  543. hModule = (HMODULE)lpdt[hDriver-1].hModule;
  544. GlobalUnlock(hInstalledDriverList);
  545. DrvLeave();
  546. w = GetDrvrUsage((HANDLE)hModule);
  547. if (w == 1)
  548. {
  549. if (fSendDisable)
  550. DrvSendMessage((HANDLE)(UINT_PTR)hDriver, DRV_DISABLE, 0L, 0L);
  551. DrvSendMessage((HANDLE)(UINT_PTR)hDriver, DRV_FREE, 0L, 0L);
  552. }
  553. FreeLibrary(hModule);
  554. DrvEnter();
  555. lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
  556. /* Only one entry for the driver in the driver list has the first
  557. * instance flag set. This is to make it easier to handle system
  558. * messages that only need to be sent to a driver once.
  559. *
  560. * To maintain the flag, we must set the flag in one of the other
  561. * entries if we remove the driver entry with the flag set.
  562. *
  563. * Note that InternalFreeDriver returns the new usage count of
  564. * the driver so if it is zero, we know that there are no other
  565. * entries for the driver in the list and so we don't have to
  566. * do this loop.
  567. */
  568. if (lpdt[hDriver - 1].fFirstEntry) {
  569. for (index=0;index<cInstalledDrivers;index++)
  570. if (lpdt[index].hModule == lpdt[hDriver-1].hModule && !lpdt[index].fFirstEntry)
  571. {
  572. lpdt[index].fFirstEntry = 1;
  573. break;
  574. }
  575. }
  576. // Clear the rest of the table entry
  577. lpdt[hDriver-1].hModule = 0; // this indicates free entry
  578. lpdt[hDriver-1].fFirstEntry = 0; // this is also just to be tidy
  579. lpdt[hDriver-1].lpDriverEntryPoint = 0; // this is also just to be tidy
  580. GlobalUnlock(hInstalledDriverList);
  581. DrvLeave();
  582. LeaveCriticalSection(&DriverLoadFreeCritSec);
  583. return(w-1);
  584. }
  585. #if 0
  586. UINT GetWinVer()
  587. {
  588. WORD w = GetVersion();
  589. return (w>>8) | (w<<8);
  590. }
  591. #endif
  592. #if 0
  593. void NEAR PASCAL DrvInit(void)
  594. {
  595. HANDLE hlibUser;
  596. LPDRIVERTABLE lpdt;
  597. /* If the window's driver interface is present then use it.
  598. */
  599. DOUT(("DrvInit\r\n"));
  600. hlibUser = GetModuleHandle(szUser);
  601. if(lpOpenDriver = (OPENDRIVER31)GetProcAddress(hlibUser,szOpenDriver))
  602. fUseWinAPI = TRUE;
  603. else
  604. {
  605. fUseWinAPI = FALSE;
  606. DOUT((" - No Windows Driver I/F detected. Using MMSYSTEM\r\n"));
  607. //
  608. // force MMSYSTEM into the driver table, without enabling it.
  609. //
  610. DrvEnter();
  611. cInstalledDrivers = 0;
  612. hInstalledDriverList = GlobalAlloc(GHND|GMEM_SHARE, (DWORD)((UINT)sizeof(DRIVERTABLE)));
  613. #if DBG
  614. if (hInstalledDriverList == NULL)
  615. {
  616. DOUT(("no memory for driver table\r\n"));
  617. // FatalExit(-1);
  618. return;
  619. }
  620. #endif
  621. lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
  622. //
  623. // NOTE! we are not setting fFirstEntry==TRUE
  624. //
  625. // because under windows 3.0 MMSOUND will enable/disable us
  626. // we *dont* wan't the driver interface doing it!
  627. //
  628. lpdt->lpDriverEntryPoint = (DRIVERPROC)DriverProc;
  629. lpdt->hModule = ghInst;
  630. lpdt->fFirstEntry = 0;
  631. GlobalUnlock(hInstalledDriverList);
  632. DrvLeave();
  633. }
  634. if (fUseWinAPI)
  635. {
  636. DOUT((" - Windows Driver I/F detected\r\n"));
  637. if (GetWinVer() < 0x30A)
  638. DOUT(("MMSYSTEM: WARNING !!! WINDOWS DRIVER I/F BUT VERSION LESS THAN 3.1\r\n"));
  639. // link to the relevant user APIs.
  640. lpCloseDriver = (CLOSEDRIVER31)GetProcAddress(hlibUser, szCloseDriver);
  641. lpGetDriverModuleHandle = (GETDRIVERMODULEHANDLE31)GetProcAddress(hlibUser, szDrvModuleHandle);
  642. lpSendDriverMessage = (SENDDRIVERMESSAGE31)GetProcAddress(hlibUser, szSendDriverMessage);
  643. lpDefDriverProc = (DEFDRIVERPROC31)GetProcAddress(hlibUser, szDefDriverProc);
  644. }
  645. }
  646. #endif
  647. #if 0
  648. /***************************************************************************
  649. *
  650. * @doc INTERNAL
  651. *
  652. * @api void | InternalInstallDriverChain | This function loads the
  653. * drivers specified on the Drivers= line of the [Boot] section
  654. * of system.ini. The Drivers are loaded but not opened.
  655. *
  656. * @rdesc None
  657. *
  658. ***************************************************************************/
  659. void FAR PASCAL InternalInstallDriverChain(void)
  660. {
  661. char szBuffer[150];
  662. BOOL bFinished;
  663. int iStart;
  664. int iEnd;
  665. if (!fUseWinAPI)
  666. {
  667. /* Load DLL's from DRIVERS section in system.ini
  668. */
  669. szBuffer[0] = TEXT('\0');
  670. winmmGetPrivateProfileString(szBoot, /* [Boot] section */
  671. szDrivers, /* Drivers= */
  672. szNull, /* Default if no match */
  673. szBuffer, /* Return buffer */
  674. sizeof(szBuffer),
  675. szSystemIni);
  676. if (!*szBuffer) {
  677. return;
  678. }
  679. bFinished = FALSE;
  680. iStart = 0;
  681. while (!bFinished)
  682. {
  683. iEnd = iStart;
  684. while (szBuffer[iEnd] && (szBuffer[iEnd] != ' ') &&
  685. (szBuffer[iEnd] != ','))
  686. iEnd++;
  687. if (szBuffer[iEnd] == NULL)
  688. bFinished = TRUE;
  689. else
  690. szBuffer[iEnd] = NULL;
  691. /* Load and enable the driver.
  692. */
  693. InternalLoadDriver(&(szBuffer[iStart]), NULL, NULL, 0, TRUE);
  694. iStart = iEnd+1;
  695. }
  696. }
  697. }
  698. #endif
  699. /***************************************************************************
  700. *
  701. * @doc INTERNAL
  702. *
  703. * @api void | InternalDriverEnable | This function enables all the
  704. * currently loaded installable drivers. If the user driver i/f
  705. * has been detected, this function will do nothing.
  706. *
  707. * @rdesc None
  708. *
  709. ***************************************************************************/
  710. void FAR PASCAL InternalDriverEnable(void)
  711. {
  712. if (!fUseWinAPI)
  713. InternalBroadcastDriverMessage(1, DRV_ENABLE, 0L, 0L, IBDM_ONEINSTANCEONLY);
  714. }
  715. /***************************************************************************
  716. *
  717. * @doc INTERNAL
  718. *
  719. * @api void | InternalDriverDisable | This function disables all the
  720. * currently loaded installable drivers. If the user driver I/F
  721. * has been detected, this function will do nothing.
  722. *
  723. *
  724. * @rdesc None
  725. *
  726. ***************************************************************************/
  727. void FAR PASCAL InternalDriverDisable(void)
  728. {
  729. if (!fUseWinAPI)
  730. InternalBroadcastDriverMessage(0, DRV_DISABLE, 0L, 0L,
  731. IBDM_ONEINSTANCEONLY | IBDM_REVERSE);
  732. }
  733. /***************************************************************************
  734. *
  735. * @doc INTERNAL
  736. *
  737. * @api BOOL | TestExeFormat | This function tests if the executable
  738. * supplied is loadable as a 32-bit executable
  739. *
  740. * @parm LPWSTR | szExe | The file to test
  741. *
  742. * @rdesc BOOL | TRUE if format was OK, FALSE otherwise
  743. *
  744. ***************************************************************************/
  745. BOOL TestExeFormat(LPWSTR szExe)
  746. {
  747. HANDLE SectionHandle;
  748. HANDLE FileHandle;
  749. PVOID BaseAddress;
  750. SIZE_T ViewSize;
  751. WCHAR ExpandedName[MAX_PATH];
  752. LPWSTR FilePart;
  753. //
  754. // See if it's already loaded
  755. //
  756. if (GetModuleHandleW(szExe)) {
  757. return TRUE;
  758. }
  759. //
  760. // Search for our DLL
  761. //
  762. if (!SearchPathW(NULL,
  763. szExe,
  764. NULL,
  765. MAX_PATH,
  766. ExpandedName,
  767. &FilePart)) {
  768. return FALSE;
  769. }
  770. //
  771. // Get a handle for it
  772. //
  773. FileHandle = CreateFileW(ExpandedName,
  774. GENERIC_READ,
  775. FILE_SHARE_READ,
  776. NULL,
  777. OPEN_EXISTING,
  778. 0,
  779. NULL);
  780. if (FileHandle == INVALID_HANDLE_VALUE) {
  781. return FALSE;
  782. }
  783. //
  784. // We create and map a section for this file as an IMAGE
  785. // to make sure it's recognized as such
  786. //
  787. if (!NT_SUCCESS(NtCreateSection(
  788. &SectionHandle,
  789. SECTION_ALL_ACCESS,
  790. NULL,
  791. NULL,
  792. PAGE_READONLY,
  793. SEC_IMAGE,
  794. FileHandle))) {
  795. CloseHandle(FileHandle);
  796. return FALSE;
  797. }
  798. //
  799. // Map it whereever it will go
  800. //
  801. ViewSize = 0;
  802. BaseAddress = NULL;
  803. //
  804. // See if the loader is happy with the format
  805. //
  806. if (!NT_SUCCESS(NtMapViewOfSection(SectionHandle,
  807. NtCurrentProcess(),
  808. &BaseAddress,
  809. 0L,
  810. 0L,
  811. NULL,
  812. &ViewSize,
  813. ViewShare,
  814. 0L,
  815. PAGE_READONLY))) {
  816. NtClose(SectionHandle);
  817. CloseHandle(FileHandle);
  818. return FALSE;
  819. }
  820. NtUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
  821. NtClose(SectionHandle);
  822. CloseHandle(FileHandle);
  823. return TRUE;
  824. }
  825. /***************************************************************************
  826. *
  827. * @doc INTERNAL
  828. *
  829. * @api HANDLE | LoadAliasedLibrary | This function loads the library module
  830. * contained in the specified file and returns its module handle
  831. * unless the specified name matches a keyname in the
  832. * specified section section of the specified ini file in which case
  833. * the library module in the file specified on the ini line is loaded.
  834. *
  835. * @parm LPSTR | szLibFileName | points to a null-terminated character
  836. * string containing the filename or system.ini keyname.
  837. *
  838. * @parm LPSTR | szSection | points to a null-terminated character
  839. * string containing the section name.
  840. *
  841. * @parm LPSTR | szIniFile | points to a null-terminated character
  842. * string containing the ini filename.
  843. *
  844. * @parm LPSTR | lpstrTail | caller supplied buffer to return the "tail"
  845. * of the system.ini line in. The tail is any characters that follow
  846. * the filename.
  847. *
  848. * @parm UINT | cbTail | size of supplied buffer.
  849. *
  850. * @rdesc Returns the library's module handle.
  851. *
  852. * @xref LoadLibrary
  853. *
  854. ***************************************************************************/
  855. HANDLE LoadAliasedLibrary( LPCWSTR szLibFileName,
  856. LPCWSTR szSection,
  857. LPWSTR szIniFile,
  858. LPWSTR lpstrTail,
  859. UINT cbTail)
  860. {
  861. #define SZ_SIZE 128
  862. #define SZ_SIZE_BYTES (SZ_SIZE * sizeof( WCHAR ))
  863. WCHAR sz[SZ_SIZE];
  864. LPWSTR pch;
  865. HANDLE hReturn;
  866. DWORD OldErrorMode;
  867. // OFSTRUCT of;
  868. if (!szLibFileName || !*szLibFileName)
  869. return(NULL); // File not found
  870. // read the filename and additional info. into sz
  871. sz[0] = L'\0';
  872. if (winmmGetPrivateProfileString(szSection, // ini section
  873. szLibFileName, // key name
  874. szLibFileName, // default if no match
  875. sz, // return buffer
  876. SZ_SIZE, // sizeof of return buffer
  877. szIniFile)==0) // ini. file
  878. {
  879. return NULL;
  880. }
  881. sz[SZ_SIZE - 1] = 0;
  882. #if 1
  883. if (0 == lstrcmpiW(sz, L"wdmaud.drv"))
  884. {
  885. if (0 != lstrcmpiW(sz, szLibFileName))
  886. {
  887. // Squirt("LoadAliasedLibrary: [%ls:%ls]", szLibFileName, sz);
  888. // Squirt("Should not load [%ls]", szLibFileName);
  889. return NULL;
  890. }
  891. }
  892. #endif
  893. //
  894. // strip off the additional info.
  895. //
  896. pch = (LPWSTR)sz;
  897. //
  898. // at exit from loop pch pts to ch after first space or null ch
  899. //
  900. while (*pch) {
  901. if ( *pch == ' ' ) {
  902. *pch++ = '\0';
  903. break;
  904. }
  905. pch++;
  906. }
  907. //
  908. // These lines are removed for unicode because:
  909. // there is not a unicode version of OpenFile.
  910. // LoadLibrary performs the same test as the one below anyway
  911. //
  912. // if (!GetModuleHandle( sz ) &&
  913. // OpenFile(sz, &of, OF_EXIST|OF_READ|OF_SHARE_DENY_NONE) == -1) {
  914. //
  915. // return(NULL);
  916. // }
  917. //
  918. // copy additional info. to lpstrTail
  919. //
  920. if (lpstrTail && cbTail) {
  921. while (cbTail-- && (0 != (*lpstrTail++ = *pch++)))
  922. ;
  923. *(lpstrTail-1) = 0;
  924. }
  925. //
  926. // If we're running in the server check if it's a good image.
  927. // The server bug checks if it tries to load bad images (LoadLibrary
  928. // inconsistency).
  929. //
  930. // To do this we simulate the load process far enough to make
  931. // the check that it's a valid image
  932. //
  933. if (WinmmRunningInServer && !TestExeFormat(sz)) {
  934. return NULL;
  935. }
  936. //
  937. // Disable hard error popups
  938. //
  939. OldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  940. //
  941. // Try to load it
  942. //
  943. hReturn = LoadLibraryW( sz );
  944. SetErrorMode(OldErrorMode);
  945. return hReturn;
  946. #undef SZ_SIZE_BYTES
  947. #undef SZ_SIZE
  948. }
  949. /***************************************************************************
  950. *
  951. * @doc INTERNAL
  952. *
  953. * @api int | GetDrvrUsage | Runs through the driver list and figures
  954. * out how many instances of this driver module handle we have.
  955. * We use this instead of GetModuleUsage so that we can have drivers
  956. * loaded as normal DLLs and as installable drivers.
  957. *
  958. * @parm HANDLE | h | Driver's module handle
  959. *
  960. * @rdesc Returns the library's driver usage count.
  961. *
  962. ***************************************************************************/
  963. int FAR PASCAL GetDrvrUsage(HANDLE h)
  964. {
  965. LPDRIVERTABLE lpdt;
  966. int index;
  967. int count;
  968. DrvEnter();
  969. if (!hInstalledDriverList || !cInstalledDrivers) {
  970. DrvLeave();
  971. return(0);
  972. }
  973. count = 0;
  974. lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
  975. for (index=0;index<cInstalledDrivers;index++)
  976. {
  977. if (lpdt->hModule==(UINT_PTR)h)
  978. {
  979. count++;
  980. }
  981. lpdt++;
  982. }
  983. GlobalUnlock(hInstalledDriverList);
  984. DrvLeave();
  985. return(count);
  986. }