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.

723 lines
16 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1994-1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: w95hack.c
  6. * Content: Win95 hack-o-rama code
  7. * This is a HACK to handle the fact that Win95 doesn't notify
  8. * a DLL when a process is destroyed.
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 28-mar-95 craige initial implementation
  13. * 01-apr-95 craige happy fun joy updated header file
  14. * 06-apr-95 craige reworked for new ddhelp
  15. * 09-may-95 craige loading any DLL
  16. * 16-sep-95 craige bug 1117: must UnmapViewOfFile before closing handle
  17. * 29-nov-95 angusm added HelperCreateDSFocusThread
  18. * 18-jul-96 andyco added Helper(Add/)DeleteDPlayServer
  19. * 12-oct-96 colinmc added new service to get DDHELP to get its own handle
  20. * for communicating with the DirectSound VXD
  21. * 22-jan-97 kipo return an HRESULT from HelperAddDPlayServer()
  22. * 29-jan-97 colinmc vxd handling stuff is no longer win16 lock specific
  23. *
  24. ***************************************************************************/
  25. #undef WIN32_LEAN_AND_MEAN
  26. #define WIN32_LEAN_AND_MEAN
  27. #include <windows.h>
  28. #include <mmsystem.h>
  29. #include <mmreg.h>
  30. #include "w95help.h"
  31. #include "dpf.h"
  32. #undef E_FAIL
  33. #define E_FAIL 0x80004005L
  34. //extern DWORD * pdwHelperPid;
  35. //extern HANDLE * phModule; // must be defined
  36. extern DWORD dwHelperPid;
  37. extern HINSTANCE hModule; // must be defined
  38. /*
  39. * sendRequest
  40. *
  41. * communicate a request to DDHELP
  42. */
  43. static BOOL sendRequest( LPDDHELPDATA req_phd )
  44. {
  45. LPDDHELPDATA phd;
  46. HANDLE hmem;
  47. HANDLE hmutex;
  48. HANDLE hackevent;
  49. HANDLE hstartevent;
  50. BOOL rc;
  51. /*
  52. * get events start/ack events
  53. */
  54. hstartevent = CreateEvent( NULL, FALSE, FALSE, DDHELP_EVENT_NAME );
  55. if( hstartevent == NULL )
  56. {
  57. return FALSE;
  58. }
  59. hackevent = CreateEvent( NULL, FALSE, FALSE, DDHELP_ACK_EVENT_NAME );
  60. if( hackevent == NULL )
  61. {
  62. CloseHandle( hstartevent );
  63. return FALSE;
  64. }
  65. /*
  66. * create shared memory area
  67. */
  68. hmem = CreateFileMapping( (HANDLE) 0xffffffff, NULL,
  69. PAGE_READWRITE, 0, sizeof( DDHELPDATA ),
  70. DDHELP_SHARED_NAME );
  71. if( hmem == NULL )
  72. {
  73. DPF( 1, "Could not create file mapping!" );
  74. CloseHandle( hstartevent );
  75. CloseHandle( hackevent );
  76. return FALSE;
  77. }
  78. phd = (LPDDHELPDATA) MapViewOfFile( hmem, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
  79. if( phd == NULL )
  80. {
  81. DPF( 1, "Could not create view of file!" );
  82. CloseHandle( hmem );
  83. CloseHandle( hstartevent );
  84. CloseHandle( hackevent );
  85. return FALSE;
  86. }
  87. /*
  88. * wait for access to the shared memory
  89. */
  90. hmutex = OpenMutex( SYNCHRONIZE, FALSE, DDHELP_MUTEX_NAME );
  91. if( hmutex == NULL )
  92. {
  93. DPF( 1, "Could not create mutex!" );
  94. UnmapViewOfFile( phd );
  95. CloseHandle( hmem );
  96. CloseHandle( hstartevent );
  97. CloseHandle( hackevent );
  98. return FALSE;
  99. }
  100. WaitForSingleObject( hmutex, INFINITE );
  101. /*
  102. * wake up DDHELP with our request
  103. */
  104. memcpy( phd, req_phd, sizeof( DDHELPDATA ) );
  105. phd->req_id = hModule;
  106. if( SetEvent( hstartevent ) )
  107. {
  108. WaitForSingleObject( hackevent, INFINITE );
  109. memcpy( req_phd, phd, sizeof( DDHELPDATA ) );
  110. rc = TRUE;
  111. }
  112. else
  113. {
  114. DPF( 1, "Could not signal event to notify DDHELP" );
  115. rc = FALSE;
  116. }
  117. /*
  118. * done with things
  119. */
  120. ReleaseMutex( hmutex );
  121. CloseHandle( hmutex );
  122. CloseHandle( hstartevent );
  123. CloseHandle( hackevent );
  124. UnmapViewOfFile( phd );
  125. CloseHandle( hmem );
  126. return rc;
  127. } /* sendRequest */
  128. /*
  129. * DoneWithHelperProcess
  130. */
  131. void DoneWithHelperProcess( void )
  132. {
  133. DDHELPDATA hd;
  134. if( dwHelperPid == 0 )
  135. {
  136. return;
  137. }
  138. hd.req = DDHELPREQ_FREEDCLIST;
  139. sendRequest( &hd );
  140. } /* DoneWithHelperProcess */
  141. /*
  142. * WaitForHelperStartup
  143. */
  144. BOOL WaitForHelperStartup( void )
  145. {
  146. HANDLE hevent;
  147. DWORD rc;
  148. hevent = CreateEvent( NULL, TRUE, FALSE, DDHELP_STARTUP_EVENT_NAME );
  149. if( hevent == NULL )
  150. {
  151. return FALSE;
  152. }
  153. DPF( 3, "Wait DDHELP startup event to be triggered" );
  154. rc = WaitForSingleObject( hevent, 100000 ); // fail if this doesn't work within 100 seconds
  155. CloseHandle( hevent );
  156. if( rc == WAIT_TIMEOUT )
  157. {
  158. return FALSE;
  159. }
  160. return TRUE;
  161. } /* WaitForHelperStartup */
  162. /*
  163. * HelperLoadDLL
  164. *
  165. * get the helper to load a DLL for us.
  166. */
  167. DWORD HelperLoadDLL( LPSTR dllname, LPSTR fnname, DWORD context )
  168. {
  169. DDHELPDATA hd;
  170. DWORD rc = 0;
  171. if( dllname != NULL )
  172. {
  173. hd.req = DDHELPREQ_LOADDLL;
  174. lstrcpy( hd.fname, dllname );
  175. if( fnname != NULL )
  176. {
  177. strcpy( hd.func, fnname );
  178. hd.context = context;
  179. DPF( 3, "Context=%08lx", context );
  180. }
  181. else
  182. {
  183. hd.func[0] = 0;
  184. }
  185. DPF( 3, "Asking DDHELP to load DLL %s", dllname );
  186. sendRequest( &hd );
  187. rc = (DWORD)hd.dwReturn;
  188. }
  189. return rc;
  190. } /* HelperLoadDLL */
  191. /*
  192. * HelperCreateThread
  193. */
  194. void HelperCreateThread( void )
  195. {
  196. DDHELPDATA hd;
  197. hd.req = DDHELPREQ_CREATEHELPERTHREAD;
  198. sendRequest( &hd );
  199. } /* HelperCreateThread */
  200. /*
  201. * SignalNewProcess
  202. *
  203. * Signal DDHELP that a new process has arrived. This is called with the
  204. * DLL lock taken, so global vars are safe
  205. */
  206. void SignalNewProcess( DWORD pid, LPHELPNOTIFYPROC proc )
  207. {
  208. DDHELPDATA hd;
  209. if( pid == dwHelperPid )
  210. {
  211. DPF( 3, "Helper connected to DLL - no signal required" );
  212. return;
  213. }
  214. DPF( 3, "Signalling DDHELP that a new process has connected" );
  215. hd.req = DDHELPREQ_NEWPID;
  216. hd.pid = pid;
  217. hd.lpNotify = proc;
  218. sendRequest( &hd );
  219. } /* SignalNewProcess */
  220. /*
  221. * StopWatchProcess
  222. *
  223. * Signal DDHELP to stop watching a process. This is called with the
  224. * DLL lock taken, so global vars are safe
  225. */
  226. void StopWatchProcess( DWORD pid, LPHELPNOTIFYPROC proc )
  227. {
  228. DDHELPDATA hd;
  229. if( pid == dwHelperPid )
  230. {
  231. DPF( 3, "Helper connected to DLL - no signal required" );
  232. return;
  233. }
  234. DPF( 3, "Signalling DDHELP to stop watching a process" );
  235. hd.req = DDHELPREQ_STOPWATCHPID;
  236. hd.pid = pid;
  237. hd.lpNotify = proc;
  238. sendRequest( &hd );
  239. } /* SignalNewProcess */
  240. /*
  241. * SignalNewDriver
  242. *
  243. * Signal DDHELP that a new driver has been loaded. This is called with the
  244. * DLL lock taken, so global vars are safe
  245. */
  246. void SignalNewDriver( LPSTR fname, BOOL isdisp )
  247. {
  248. DDHELPDATA hd;
  249. DPF( 3, "Signalling DDHELP to create a new DC" );
  250. hd.req = DDHELPREQ_NEWDC;
  251. hd.isdisp = isdisp;
  252. lstrcpy( hd.fname, fname );
  253. sendRequest( &hd );
  254. } /* SignalNewDriver */
  255. /*
  256. * CreateHelperProcess
  257. */
  258. BOOL CreateHelperProcess( LPDWORD ppid )
  259. {
  260. if( dwHelperPid == 0 )
  261. {
  262. STARTUPINFO si;
  263. PROCESS_INFORMATION pi;
  264. HANDLE h;
  265. h = OpenEvent( SYNCHRONIZE, FALSE, DDHELP_STARTUP_EVENT_NAME );
  266. if( h == NULL )
  267. {
  268. si.cb = sizeof(STARTUPINFO);
  269. si.lpReserved = NULL;
  270. si.lpDesktop = NULL;
  271. si.lpTitle = NULL;
  272. si.dwFlags = 0;
  273. si.cbReserved2 = 0;
  274. si.lpReserved2 = NULL;
  275. DPF( 3, "Creating helper process now" );
  276. if( !CreateProcess(NULL, "ddhelp.exe", NULL, NULL, FALSE,
  277. NORMAL_PRIORITY_CLASS,
  278. NULL, NULL, &si, &pi) )
  279. {
  280. DPF( 2, "Could not create DDHELP.EXE" );
  281. return FALSE;
  282. }
  283. dwHelperPid = pi.dwProcessId;
  284. DPF( 3, "Helper rocess created" );
  285. }
  286. else
  287. {
  288. DDHELPDATA hd;
  289. DPF( 3, "DDHELP already exists, waiting for DDHELP event" );
  290. WaitForSingleObject( h, INFINITE );
  291. CloseHandle( h );
  292. DPF( 3, "Asking for DDHELP pid" );
  293. hd.req = DDHELPREQ_RETURNHELPERPID;
  294. sendRequest( &hd );
  295. dwHelperPid = hd.pid;
  296. DPF( 3, "DDHELP pid = %08lx", dwHelperPid );
  297. }
  298. *ppid = dwHelperPid;
  299. return TRUE;
  300. }
  301. *ppid = dwHelperPid;
  302. return FALSE;
  303. } /* CreateHelperProcess */
  304. #ifndef WINNT //this is Just For Now... dsound will get the help it needs..jeffno 951206
  305. /*
  306. * HelperWaveOpen
  307. *
  308. * get the helper to load a DLL for us.
  309. */
  310. DWORD HelperWaveOpen( LPVOID lphwo, DWORD dwDeviceID, LPVOID pwfx )
  311. {
  312. DDHELPDATA hd;
  313. if( (lphwo != NULL) && (pwfx != NULL) )
  314. {
  315. hd.req = DDHELPREQ_WAVEOPEN;
  316. hd.pData1 = lphwo;
  317. hd.dwData1 = dwDeviceID;
  318. hd.dwData2 = (DWORD)pwfx;
  319. DPF( 3, "Asking DDHELP to Open Wave Device %d", dwDeviceID );
  320. sendRequest( &hd );
  321. return hd.dwReturn;
  322. }
  323. else
  324. {
  325. DPF( 3, "Helper Wave Open param error");
  326. return MMSYSERR_ERROR;
  327. }
  328. } /* HelperWaveOpen */
  329. /*
  330. * HelperWaveClose
  331. *
  332. * get the helper to load a DLL for us.
  333. */
  334. DWORD HelperWaveClose( DWORD hwo )
  335. {
  336. DDHELPDATA hd;
  337. if( (hwo != 0) )
  338. {
  339. hd.req = DDHELPREQ_WAVECLOSE;
  340. hd.dwData1 = hwo;
  341. DPF( 3, "Asking DDHELP to Close Wave Device ");
  342. sendRequest( &hd );
  343. return hd.dwReturn;
  344. }
  345. else
  346. {
  347. DPF( 3, "Helper Wave Close param error");
  348. return MMSYSERR_ERROR;
  349. }
  350. } /* HelperWaveClose */
  351. /*
  352. * HelperCreateTimer
  353. *
  354. * get the helper to load a DLL for us.
  355. */
  356. DWORD HelperCreateTimer( DWORD dwResolution,
  357. LPVOID pTimerProc,
  358. DWORD dwInstanceData )
  359. {
  360. DDHELPDATA hd;
  361. if( (dwResolution != 0) && (pTimerProc != NULL) )
  362. {
  363. hd.req = DDHELPREQ_CREATETIMER;
  364. hd.pData1 = pTimerProc;
  365. hd.dwData1 = dwResolution;
  366. hd.dwData2 = dwInstanceData;
  367. DPF( 3, "Asking DDHELP to Create Timer" );
  368. sendRequest( &hd );
  369. return hd.dwReturn;
  370. }
  371. else
  372. {
  373. DPF( 3, "Helper Wave Close param error");
  374. return MMSYSERR_ERROR;
  375. }
  376. } /* HelperCreateTimer */
  377. /*
  378. * HelperKillTimer
  379. *
  380. * get the helper to load a DLL for us.
  381. */
  382. DWORD HelperKillTimer( DWORD dwTimerID )
  383. {
  384. DDHELPDATA hd;
  385. if( (dwTimerID != 0) )
  386. {
  387. hd.req = DDHELPREQ_KILLTIMER;
  388. hd.dwData1 = dwTimerID;
  389. DPF( 3, "Asking DDHELP to KILL Timer %X", dwTimerID );
  390. sendRequest( &hd );
  391. return hd.dwReturn;
  392. }
  393. else
  394. {
  395. DPF( 3, "Helper Wave Close param error");
  396. return MMSYSERR_ERROR;
  397. }
  398. } /* HelperKillTimer */
  399. /*
  400. * HelperCreateDSMixerThread
  401. *
  402. * get the helper to create a mixer thread.
  403. */
  404. HANDLE HelperCreateDSMixerThread( LPTHREAD_START_ROUTINE pfnThreadFunc,
  405. LPDWORD pdwThreadParam,
  406. DWORD dwFlags,
  407. LPDWORD pThreadId )
  408. {
  409. DDHELPDATA hd;
  410. hd.req = DDHELPREQ_CREATEDSMIXERTHREAD;
  411. hd.pData1 = pfnThreadFunc;
  412. hd.dwData1 = (DWORD)pdwThreadParam;
  413. hd.dwData2 = dwFlags;
  414. hd.pData2 = pThreadId;
  415. sendRequest( &hd );
  416. return (HANDLE)hd.dwReturn;
  417. } /* HelperCreateDSMixerThread
  418. /*
  419. * HelperCreateDSFocusThread
  420. *
  421. * get the helper to create a sound focus thread.
  422. */
  423. HANDLE HelperCreateDSFocusThread( LPTHREAD_START_ROUTINE pfnThreadFunc,
  424. LPDWORD pdwThreadParam,
  425. DWORD dwFlags,
  426. LPDWORD pThreadId )
  427. {
  428. DDHELPDATA hd;
  429. hd.req = DDHELPREQ_CREATEDSFOCUSTHREAD;
  430. hd.pData1 = pfnThreadFunc;
  431. hd.dwData1 = (DWORD)pdwThreadParam;
  432. hd.dwData2 = dwFlags;
  433. hd.pData2 = pThreadId;
  434. sendRequest( &hd );
  435. return (HANDLE)hd.dwReturn;
  436. } /* HelperCreateDSFocusThread
  437. /*
  438. * HelperCallDSEmulatorCleanup
  439. *
  440. * Call the DirectSound function which cleans up MMSYSTEM handles
  441. */
  442. void HelperCallDSEmulatorCleanup( LPVOID callback,
  443. LPVOID pDirectSound )
  444. {
  445. DDHELPDATA hd;
  446. hd.req = DDHELPREQ_CALLDSCLEANUP;
  447. hd.pData1 = callback;
  448. hd.pData2 = pDirectSound;
  449. sendRequest( &hd );
  450. }
  451. #endif //not winnt -just for now-jeffno
  452. /*
  453. * HelperCreateModeSetThread
  454. *
  455. * get the helper to load a DLL for us.
  456. */
  457. BOOL HelperCreateModeSetThread(
  458. LPVOID callback,
  459. HANDLE *ph,
  460. LPVOID lpdd,
  461. DWORD hInstance )
  462. {
  463. DDHELPDATA hd;
  464. HANDLE h;
  465. char str[64];
  466. hd.req = DDHELPREQ_CREATEMODESETTHREAD;
  467. hd.lpModeSetNotify = callback;
  468. hd.pData1 = lpdd;
  469. hd.dwData1 = hInstance;
  470. sendRequest( &hd );
  471. wsprintf( str, DDHELP_MODESET_EVENT_NAME, hInstance );
  472. DPF( 3, "Trying to open event \"%s\"", str );
  473. h = OpenEvent( SYNCHRONIZE, FALSE, str );
  474. if( h == NULL )
  475. {
  476. DPF( 3, "Could not open modeset event!" );
  477. *ph = NULL;
  478. return FALSE;
  479. }
  480. *ph = h;
  481. DPF( 1, "HelperCreateModeSetThread GotEvent: %08lx", h );
  482. return TRUE;
  483. } /* HelperCreateModeSetThread */
  484. /*
  485. * HelperKillModeSetThread
  486. *
  487. * get the helper to load a DLL for us.
  488. */
  489. void HelperKillModeSetThread( DWORD hInstance )
  490. {
  491. DDHELPDATA hd;
  492. hd.req = DDHELPREQ_KILLMODESETTHREAD;
  493. hd.dwData1 = hInstance;
  494. sendRequest( &hd );
  495. } /* HelperKillModeSetThread */
  496. #ifndef WINNT
  497. /*
  498. * HelperCreateDOSBoxThread
  499. *
  500. * get the helper to create a thread so kernel mode can notify us of DOS box
  501. * changes.
  502. */
  503. BOOL HelperCreateDOSBoxThread(
  504. LPVOID callback,
  505. HANDLE *ph,
  506. LPVOID lpdd,
  507. DWORD hInstance )
  508. {
  509. DDHELPDATA hd;
  510. HANDLE h;
  511. char str[64];
  512. hd.req = DDHELPREQ_CREATEDOSBOXTHREAD;
  513. hd.lpModeSetNotify = callback;
  514. hd.pData1 = lpdd;
  515. hd.dwData1 = hInstance;
  516. sendRequest( &hd );
  517. wsprintf( str, DDHELP_DOSBOX_EVENT_NAME, hInstance );
  518. DPF( 3, "Trying to open event \"%s\"", str );
  519. h = OpenEvent( SYNCHRONIZE, FALSE, str );
  520. if( h == NULL )
  521. {
  522. DPF( 3, "Could not open DOS box event!" );
  523. *ph = NULL;
  524. return FALSE;
  525. }
  526. *ph = h;
  527. DPF( 1, "HelperCreateDOSBoxThread GotEvent: %08lx", h );
  528. return TRUE;
  529. } /* HelperCreateDOSBoxThread */
  530. /*
  531. * HelperKillDOSBoxThread
  532. *
  533. * get the helper to load a DLL for us.
  534. */
  535. void HelperKillDOSBoxThread( DWORD hInstance )
  536. {
  537. DDHELPDATA hd;
  538. hd.req = DDHELPREQ_KILLDOSBOXTHREAD;
  539. hd.dwData1 = hInstance;
  540. sendRequest( &hd );
  541. } /* HelperKillDOSBoxThread */
  542. #endif //!winnt
  543. // notify dphelp.c that we have a new server on this system
  544. DWORD HelperAddDPlayServer(DWORD port)
  545. {
  546. DDHELPDATA hd;
  547. DWORD pid = GetCurrentProcessId();
  548. memset(&hd, 0, sizeof(DDHELPDATA));
  549. hd.req = DDHELPREQ_DPLAYADDSERVER;
  550. hd.pid = pid;
  551. hd. dwData1 = port;
  552. if (sendRequest(&hd))
  553. return (DWORD)hd.dwReturn;
  554. else
  555. return ((DWORD) E_FAIL);
  556. } // HelperAddDPlayServer
  557. // server is going away
  558. BOOL HelperDeleteDPlayServer(void)
  559. {
  560. DDHELPDATA hd;
  561. DWORD pid = GetCurrentProcessId();
  562. hd.req = DDHELPREQ_DPLAYDELETESERVER;
  563. hd.pid = pid;
  564. return sendRequest(&hd);
  565. } // HelperDeleteDPlayServer
  566. #ifdef WIN95
  567. /*
  568. * Get DDHELP to load the DirectSound VXD (if it has not
  569. * already done so) and return a handle to the VXD)
  570. */
  571. HANDLE HelperGetDSVxd( void )
  572. {
  573. DDHELPDATA hd;
  574. hd.req = DDHELPREQ_GETDSVXDHANDLE;
  575. sendRequest( &hd );
  576. return (HANDLE) hd.dwReturn;
  577. } /* HelperGetDSVxd */
  578. /*
  579. * Get DDHELP to load the DirectDraw VXD (if it has not
  580. * already done so) and return a handle to the VXD)
  581. */
  582. HANDLE HelperGetDDVxd( void )
  583. {
  584. DDHELPDATA hd;
  585. hd.req = DDHELPREQ_GETDDVXDHANDLE;
  586. sendRequest( &hd );
  587. return (HANDLE) hd.dwReturn;
  588. } /* HelperGetDDVxd */
  589. #endif /* WIN95 */
  590. /*
  591. * HelperSetOnDisplayChangeNotify
  592. *
  593. * get the helper to call us back if there is DisplayChange
  594. * message. (This is for multi-mon topology changes.)
  595. */
  596. void HelperSetOnDisplayChangeNotify( void *pfn )
  597. {
  598. DDHELPDATA hd;
  599. hd.req = DDHELPREQ_NOTIFYONDISPLAYCHANGE;
  600. hd.dwData1 = (DWORD_PTR)pfn;
  601. sendRequest( &hd );
  602. return;
  603. }
  604. HINSTANCE HelperLoadLibrary(LPCSTR pszLibraryName)
  605. {
  606. DDHELPDATA hd;
  607. hd.req = DDHELPREQ_LOADLIBRARY;
  608. hd.dwData1 = (DWORD_PTR)pszLibraryName;
  609. sendRequest(&hd);
  610. return (HINSTANCE)hd.dwReturn;
  611. }
  612. BOOL HelperFreeLibrary(HINSTANCE hInst)
  613. {
  614. DDHELPDATA hd;
  615. hd.req = DDHELPREQ_FREELIBRARY;
  616. hd.dwData1 = (DWORD_PTR)hInst;
  617. sendRequest(&hd);
  618. return (BOOL)hd.dwReturn;
  619. }
  620. void HelperAddDeviceChangeNotify(LPDEVICECHANGENOTIFYPROC lpNotify)
  621. {
  622. DDHELPDATA hd;
  623. hd.req = DDHELPREQ_ADDDEVICECHANGENOTIFY;
  624. hd.pData1 = lpNotify;
  625. sendRequest(&hd);
  626. }
  627. void HelperDelDeviceChangeNotify(LPDEVICECHANGENOTIFYPROC lpNotify)
  628. {
  629. DDHELPDATA hd;
  630. hd.req = DDHELPREQ_DELDEVICECHANGENOTIFY;
  631. hd.pData1 = lpNotify;
  632. sendRequest(&hd);
  633. }