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.

553 lines
15 KiB

  1. /* Installable drivers for windows. Less common code.
  2. */
  3. #include "user.h"
  4. /*--------------------------------------------------------------------------*\
  5. **
  6. ** NewSignalProc() -
  7. **
  8. \*--------------------------------------------------------------------------*/
  9. #define SG_EXIT 0x0020
  10. #define SG_LOAD_DLL 0x0040
  11. #define SG_EXIT_DLL 0x0080
  12. #define SG_GP_FAULT 0x0666
  13. BOOL
  14. CALLBACK NewSignalProc(
  15. HTASK hTask,
  16. WORD message,
  17. WPARAM wParam,
  18. LPARAM lParam
  19. )
  20. {
  21. BOOL fRet;
  22. // Notify installable drivers this app is going away.
  23. if ( message == SG_EXIT || message == SG_GP_FAULT ) {
  24. InternalBroadcastDriverMessage( NULL, DRV_EXITAPPLICATION,
  25. (message == SG_GP_FAULT
  26. ? DRVEA_ABNORMALEXIT
  27. : DRVEA_NORMALEXIT),
  28. 0L, IBDM_FIRSTINSTANCEONLY );
  29. }
  30. //
  31. // Pass notification on to WOW32 (which passes on to USER32)
  32. //
  33. fRet = SignalProc( hTask, message, wParam, lParam );
  34. //
  35. // After letting WOW32 and User32 cleanup, destroy the shadow
  36. // message queue created by InitApp.
  37. //
  38. if ( message == SG_EXIT || message == SG_GP_FAULT ) {
  39. DeleteQueue();
  40. }
  41. return fRet;
  42. }
  43. HINSTANCE LoadAliasedLibrary(LPCSTR szLibFileName,
  44. LPCSTR szSection,
  45. LPCSTR szIniFile,
  46. LPSTR lpstrTail,
  47. WORD cbTail)
  48. {
  49. char sz[128];
  50. LPSTR pch;
  51. HINSTANCE h;
  52. WORD errMode;
  53. if (!szLibFileName || !*szLibFileName)
  54. return((HINSTANCE)2); /* File not found */
  55. /* read the filename and additional info. into sz
  56. */
  57. GetPrivateProfileString(szSection, // ini section
  58. szLibFileName, // key name
  59. szLibFileName, // default if no match
  60. sz, // return buffer
  61. sizeof(sz), // return buffer size
  62. szIniFile); // ini. file
  63. sz[sizeof(sz)-1] = 0;
  64. /* strip off the additional info. Remember, DS!=SS so we need to get a lpstr
  65. * to our stack allocated sz.
  66. */
  67. pch = (LPSTR)sz;
  68. while (*pch)
  69. {
  70. if (*pch == ' ')
  71. {
  72. *pch++ = '\0';
  73. break;
  74. }
  75. pch++;
  76. }
  77. // pch pts to ch after first space or null ch
  78. /* copy additional info. to lpstrTail
  79. */
  80. if (lpstrTail && cbTail)
  81. {
  82. while (cbTail-- && (*lpstrTail++ = *pch++))
  83. ;
  84. *(lpstrTail-1) = 0;
  85. }
  86. errMode = SetErrorMode(0x8001);
  87. h = LoadLibrary(sz);
  88. SetErrorMode(errMode);
  89. return (h);
  90. }
  91. int GetDrvrUsage(HMODULE hModule)
  92. /* effects: Runs through the driver list and figures out how many instances of
  93. * this driver module handle we have. We use this instead of GetModuleUsage
  94. * so that we can have drivers loaded as normal DLLs and as installable
  95. * drivers.
  96. */
  97. {
  98. LPDRIVERTABLE lpdt;
  99. int index;
  100. int count;
  101. if (!hInstalledDriverList || !cInstalledDrivers || !hModule)
  102. return(0);
  103. count = 0;
  104. lpdt = (LPDRIVERTABLE)MAKELP(hInstalledDriverList,0);
  105. for (index=0;index<cInstalledDrivers;index++)
  106. {
  107. if (lpdt->hModule==hModule)
  108. count++;
  109. lpdt++;
  110. }
  111. return(count);
  112. }
  113. BOOL PASCAL CheckValidDriverProc(LPDRIVERTABLE lpdt, HDRVR hdrv)
  114. /* effects: Some vendors shipped multimedia style installable drivers with
  115. * bogus entry procs. This test checks for these bogus drivers and refuses to
  116. * install them.
  117. */
  118. {
  119. WORD currentSP;
  120. WORD saveSP;
  121. _asm mov saveSP, sp
  122. (void)(lpdt->lpDriverEntryPoint)(0, hdrv, 0, 0L, 0L);
  123. _asm mov currentSP, sp
  124. _asm mov sp, saveSP
  125. if (saveSP != currentSP)
  126. DebugErr(DBF_ERROR, "Invalid driver entry proc address");
  127. return (saveSP == currentSP);
  128. }
  129. LRESULT FAR InternalLoadDriver(LPCSTR szDriverName,
  130. LPCSTR szSectionName,
  131. LPCSTR lpstrTail,
  132. WORD cbTail,
  133. BOOL fSendEnable)
  134. {
  135. int index;
  136. int i;
  137. LPDRIVERTABLE lpdt;
  138. LPDRIVERTABLE lpdtBegin;
  139. LRESULT result;
  140. HGLOBAL h;
  141. HINSTANCE hInstance;
  142. char szDrivers[20];
  143. char szSystemIni[20];
  144. /* Drivers receive the following messages: if the driver was loaded,
  145. * DRV_LOAD. If DRV_LOAD returns non-zero and fSendEnable, DRV_ENABLE.
  146. */
  147. if (!hInstalledDriverList)
  148. h = GlobalAlloc(GHND|GMEM_SHARE, (DWORD)((WORD)sizeof(DRIVERTABLE)));
  149. else
  150. /* Alloc space for the next driver we will install. We may not really
  151. * install the driver in the last slot but rather in an intermediate
  152. * slot which was freed.
  153. */
  154. h = GlobalReAlloc(hInstalledDriverList,
  155. (DWORD)((WORD)sizeof(DRIVERTABLE)*(cInstalledDrivers+1)),
  156. GHND|GMEM_SHARE);
  157. if (!h)
  158. return(0L);
  159. cInstalledDrivers++;
  160. hInstalledDriverList = h;
  161. if (!szSectionName)
  162. LoadString(hInstanceWin, STR_DRIVERS, szDrivers, sizeof(szDrivers));
  163. LoadString(hInstanceWin, STR_SYSTEMINI, szSystemIni, sizeof(szSystemIni));
  164. lpdtBegin = lpdt = (LPDRIVERTABLE)MAKELP(hInstalledDriverList, NULL);
  165. /* Find an empty driver entry */
  166. for (i = 0; i < cInstalledDrivers; i++)
  167. {
  168. if (lpdt->hModule == NULL)
  169. {
  170. index = i;
  171. break;
  172. }
  173. lpdt++;
  174. }
  175. if (index + 1 < cInstalledDrivers)
  176. /* The driver went into an unused slot in the middle somewhere so
  177. * decrement cInstalledDrivers count.
  178. */
  179. cInstalledDrivers--;
  180. /* Temporarly use an hModule to 1 to reserve this entry in case the driver
  181. * loads another driver in its LibMain.
  182. */
  183. lpdt->hModule = (HMODULE)1;
  184. hInstance = LoadAliasedLibrary((LPSTR)szDriverName,
  185. (LPSTR)(szSectionName ? szSectionName : szDrivers),
  186. szSystemIni,
  187. (LPSTR)lpstrTail,
  188. cbTail);
  189. if (hInstance < HINSTANCE_ERROR)
  190. {
  191. lpdt->hModule = NULL;
  192. /* Load failed with an error. Return error code in highword.
  193. */
  194. return(MAKELRESULT(0, hInstance));
  195. }
  196. (FARPROC)lpdt->lpDriverEntryPoint = GetProcAddress(hInstance, "DriverProc");
  197. if (!lpdt->lpDriverEntryPoint)
  198. {
  199. FreeLibrary(hInstance);
  200. lpdt->hModule = 0;
  201. result = 0L;
  202. goto LoadCleanUp;
  203. }
  204. lpdt->hModule = hInstance;
  205. /* Save either the alias or filename of this driver. (depends on what the
  206. * app passed to us to load it)
  207. */
  208. lstrcpy(lpdt->szAliasName, szDriverName);
  209. if (GetDrvrUsage(hInstance) == 1)
  210. {
  211. /* If this is the first instance, send the drv_load message. Don't use
  212. * SendDriverMessage because we haven't initialized the linked list yet
  213. */
  214. if (!CheckValidDriverProc(lpdt, (HDRVR)(index+1)) ||
  215. !(lpdt->lpDriverEntryPoint)(lpdt->dwDriverIdentifier,
  216. (HDRVR)(index+1),
  217. DRV_LOAD,
  218. 0L, 0L))
  219. {
  220. /* Driver failed load call.
  221. */
  222. lpdt->lpDriverEntryPoint = NULL;
  223. lpdt->hModule = NULL;
  224. FreeLibrary(hInstance);
  225. result = 0L;
  226. goto LoadCleanUp;
  227. }
  228. lpdt->fFirstEntry = 1;
  229. }
  230. /* Put driver in the load order linked list
  231. */
  232. if (idFirstDriver == -1)
  233. {
  234. /* Initialize everything when first driver is loaded.
  235. */
  236. idFirstDriver = index;
  237. idLastDriver = index;
  238. lpdt->idNextDriver = -1;
  239. lpdt->idPrevDriver = -1;
  240. }
  241. else
  242. {
  243. /* Insert this driver at the end of the load chain.
  244. */
  245. lpdtBegin[idLastDriver].idNextDriver = index;
  246. lpdt->idPrevDriver = idLastDriver;
  247. lpdt->idNextDriver = -1;
  248. idLastDriver = index;
  249. }
  250. if (fSendEnable && lpdt->fFirstEntry)
  251. SendDriverMessage((HDRVR)(index+1), DRV_ENABLE, 0L, 0L);
  252. result = MAKELRESULT(index+1, hInstance);
  253. LoadCleanUp:
  254. return(result);
  255. }
  256. WORD FAR InternalFreeDriver(HDRVR hDriver, BOOL fSendDisable)
  257. {
  258. LPDRIVERTABLE lpdt;
  259. WORD w;
  260. int id;
  261. /* The driver will receive the following message sequence:
  262. *
  263. * if usage count of driver is 1
  264. * DRV_DISABLE (normally)
  265. * DRV_FREE
  266. */
  267. if ((int)hDriver > cInstalledDrivers || !hDriver)
  268. return(0);
  269. lpdt = (LPDRIVERTABLE)MAKELP(hInstalledDriverList,0);
  270. if (!lpdt[(int)hDriver-1].hModule)
  271. return(0);
  272. /* If the driver usage count is 1, then send free and disable messages.
  273. */
  274. /* Clear dwDriverIdentifier so that the sendmessage for DRV_OPEN and
  275. * DRV_ENABLE have dwDriverIdentifier = 0 if an entry gets reused and so
  276. * that the DRV_DISABLE and DRV_FREE messages below also get
  277. * dwDriverIdentifier = 0.
  278. */
  279. lpdt[(int)hDriver-1].dwDriverIdentifier = 0;
  280. w = GetDrvrUsage(lpdt[(int)hDriver-1].hModule);
  281. if (w == 1)
  282. {
  283. if (fSendDisable)
  284. SendDriverMessage(hDriver, DRV_DISABLE, 0L, 0L);
  285. SendDriverMessage(hDriver, DRV_FREE, 0L, 0L);
  286. }
  287. FreeLibrary(lpdt[(int)hDriver-1].hModule);
  288. // Clear the rest of the table entry
  289. lpdt[(int)hDriver-1].hModule = 0; // this indicates free entry
  290. lpdt[(int)hDriver-1].fFirstEntry = 0; // this is also just to be tidy
  291. lpdt[(int)hDriver-1].lpDriverEntryPoint = 0; // this is also just to be tidy
  292. /* Fix up the driver load linked list */
  293. if (idFirstDriver == (int)hDriver-1)
  294. {
  295. idFirstDriver = lpdt[(int)hDriver-1].idNextDriver;
  296. if (idFirstDriver == -1)
  297. {
  298. /* No more drivers in the chain */
  299. idFirstDriver = -1;
  300. idLastDriver = -1;
  301. cInstalledDrivers= 0;
  302. goto Done;
  303. }
  304. else
  305. {
  306. /* Make prev entry of new first driver -1 */
  307. lpdt[idFirstDriver].idPrevDriver = -1;
  308. }
  309. }
  310. else if (idLastDriver == (int)hDriver-1)
  311. {
  312. /* We are freeing the last driver. So find a new last driver. */
  313. idLastDriver = lpdt[(int)hDriver-1].idPrevDriver;
  314. lpdt[idLastDriver].idNextDriver = -1;
  315. }
  316. else
  317. {
  318. /* We are freeing a driver in the middle of the list somewhere. */
  319. id = lpdt[(int)hDriver-1].idPrevDriver;
  320. lpdt[id].idNextDriver = lpdt[(int)hDriver-1].idNextDriver;
  321. id = lpdt[(int)hDriver-1].idNextDriver;
  322. lpdt[id].idPrevDriver = lpdt[(int)hDriver-1].idPrevDriver;
  323. }
  324. Done:
  325. return(w-1);
  326. }
  327. LRESULT InternalOpenDriver(LPCSTR szDriverName,
  328. LPCSTR szSectionName,
  329. LPARAM lParam2,
  330. BOOL fSendEnable)
  331. {
  332. HDRVR hDriver;
  333. LPDRIVERTABLE lpdt;
  334. LRESULT result;
  335. char sz[128];
  336. if (hDriver = (HDRVR)LOWORD(InternalLoadDriver(szDriverName, szSectionName,
  337. sz, sizeof(sz), fSendEnable)))
  338. {
  339. /* Set the driver identifier to the DRV_OPEN call to the driver
  340. * handle. This will let people build helper functions that the driver
  341. * can call with a unique identifier if they want to.
  342. */
  343. lpdt = (LPDRIVERTABLE)MAKELP(hInstalledDriverList,0);
  344. lpdt[(int)hDriver-1].dwDriverIdentifier = (DWORD)(WORD)hDriver;
  345. result = SendDriverMessage(hDriver,
  346. DRV_OPEN,
  347. (LPARAM)(LPSTR)sz,
  348. lParam2);
  349. if (!result)
  350. InternalFreeDriver(hDriver, fSendEnable);
  351. else
  352. {
  353. lpdt = (LPDRIVERTABLE)MAKELONG(0,hInstalledDriverList);
  354. lpdt[(int)hDriver-1].dwDriverIdentifier = (DWORD)result;
  355. result = (LRESULT)(DWORD)(WORD)hDriver;
  356. }
  357. }
  358. else
  359. result = 0L;
  360. return(result);
  361. }
  362. LRESULT InternalCloseDriver(HDRVR hDriver, LPARAM lParam1, LPARAM lParam2, BOOL fSendDisable)
  363. {
  364. LPDRIVERTABLE lpdt;
  365. LRESULT result;
  366. int index;
  367. BOOL f;
  368. HMODULE hm;
  369. // check handle in valid range.
  370. if ((int)hDriver > cInstalledDrivers)
  371. return(FALSE);
  372. lpdt = (LPDRIVERTABLE)MAKELP(hInstalledDriverList,0);
  373. if (!lpdt[(int)hDriver-1].hModule)
  374. return(FALSE);
  375. result = SendDriverMessage(hDriver, DRV_CLOSE, lParam1, lParam2);
  376. if (result)
  377. {
  378. // Driver didn't abort close
  379. f = lpdt[(int)hDriver-1].fFirstEntry;
  380. hm = lpdt[(int)hDriver-1].hModule;
  381. if (InternalFreeDriver(hDriver, fSendDisable) && f)
  382. {
  383. lpdt = (LPDRIVERTABLE)MAKELP(hInstalledDriverList,0);
  384. /* Only one entry for the driver in the driver list has the first
  385. * instance flag set. This is to make it easier to handle system
  386. * messages that only need to be sent to a driver once.
  387. *
  388. * To maintain the flag, we must set the flag in one of the other
  389. * entries if we remove the driver entry with the flag set.
  390. *
  391. * Note that InternalFreeDriver returns the new usage count of
  392. * the driver so if it is zero, we know that there are no other
  393. * entries for the driver in the list and so we don't have to
  394. * do this loop.
  395. */
  396. for (index=0;index<cInstalledDrivers;index++)
  397. if (lpdt[index].hModule == hm && !lpdt[index].fFirstEntry)
  398. {
  399. lpdt[index].fFirstEntry = 1;
  400. break;
  401. }
  402. }
  403. }
  404. return(result);
  405. }
  406. HDRVR API IOpenDriver(LPCSTR szDriverName, LPCSTR szSectionName, LPARAM lParam)
  407. {
  408. LRESULT result;
  409. /* The driver receives the following messages when it is opened. If it isn't
  410. * loaded, the library is loaded and the DRV_LOAD message is sent. If
  411. * DRV_LOAD returns nonzero, the DRV_ENABLE message is sent. Once the
  412. * driver is loaded or if it was previously loaded, the DRV_OPEN message is
  413. * sent.
  414. */
  415. result = InternalOpenDriver(szDriverName, szSectionName, lParam, TRUE);
  416. return((HDRVR)LOWORD(result));
  417. }
  418. LRESULT API ICloseDriver(HDRVR hDriver, LPARAM lParam1, LPARAM lParam2)
  419. {
  420. /* The driver will receive the following message sequence:
  421. *
  422. * DRV_CLOSE
  423. * if DRV_CLOSE returns non-zero
  424. * if driver usage count = 1
  425. * DRV_DISABLE
  426. * DRV_FREE
  427. */
  428. return(InternalCloseDriver(hDriver, lParam1, lParam2, TRUE));
  429. }
  430. HINSTANCE API IGetDriverModuleHandle(HDRVR hDriver)
  431. /* effects: Returns the module handle associated with the given driver ID.
  432. */
  433. {
  434. LPDRIVERTABLE lpdt;
  435. HINSTANCE hModule = NULL;
  436. if (hDriver && ((int)hDriver <= cInstalledDrivers))
  437. {
  438. lpdt = (LPDRIVERTABLE)MAKELP(hInstalledDriverList,0);
  439. return lpdt[(int)hDriver-1].hModule;
  440. }
  441. else
  442. return NULL;
  443. }