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.

644 lines
14 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 HANDLE 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( INVALID_HANDLE_VALUE, 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, INFINITE );
  155. CloseHandle( hevent );
  156. return TRUE;
  157. } /* WaitForHelperStartup */
  158. /*
  159. * HelperLoadDLL
  160. *
  161. * get the helper to load a DLL for us.
  162. */
  163. DWORD HelperLoadDLL( LPSTR dllname, LPSTR fnname, DWORD context )
  164. {
  165. DDHELPDATA hd;
  166. DWORD rc = 0;
  167. if( dllname != NULL )
  168. {
  169. hd.req = DDHELPREQ_LOADDLL;
  170. lstrcpy( hd.fname, dllname );
  171. if( fnname != NULL )
  172. {
  173. strcpy( hd.func, fnname );
  174. hd.context = context;
  175. DPF( 3, "Context=%08lx", context );
  176. }
  177. else
  178. {
  179. hd.func[0] = 0;
  180. }
  181. DPF( 3, "Asking DDHELP to load DLL %s", dllname );
  182. sendRequest( &hd );
  183. rc = hd.dwReturn;
  184. }
  185. return rc;
  186. } /* HelperLoadDLL */
  187. /*
  188. * HelperCreateThread
  189. */
  190. void HelperCreateThread( void )
  191. {
  192. DDHELPDATA hd;
  193. hd.req = DDHELPREQ_CREATEHELPERTHREAD;
  194. sendRequest( &hd );
  195. } /* HelperCreateThread */
  196. /*
  197. * SignalNewProcess
  198. *
  199. * Signal DDHELP that a new process has arrived. This is called with the
  200. * DLL lock taken, so global vars are safe
  201. */
  202. void SignalNewProcess( DWORD pid, LPHELPNOTIFYPROC proc )
  203. {
  204. DDHELPDATA hd;
  205. if( pid == dwHelperPid )
  206. {
  207. DPF( 3, "Helper connected to DLL - no signal required" );
  208. return;
  209. }
  210. DPF( 3, "Signalling DDHELP that a new process has connected" );
  211. hd.req = DDHELPREQ_NEWPID;
  212. hd.pid = pid;
  213. hd.lpNotify = proc;
  214. sendRequest( &hd );
  215. } /* SignalNewProcess */
  216. /*
  217. * SignalNewDriver
  218. *
  219. * Signal DDHELP that a new driver has been loaded. This is called with the
  220. * DLL lock taken, so global vars are safe
  221. */
  222. void SignalNewDriver( LPSTR fname, BOOL isdisp )
  223. {
  224. DDHELPDATA hd;
  225. DPF( 3, "Signalling DDHELP to create a new DC" );
  226. hd.req = DDHELPREQ_NEWDC;
  227. hd.isdisp = isdisp;
  228. lstrcpy( hd.fname, fname );
  229. sendRequest( &hd );
  230. } /* SignalNewDriver */
  231. /*
  232. * CreateHelperProcess
  233. */
  234. BOOL CreateHelperProcess( LPDWORD ppid )
  235. {
  236. if( dwHelperPid == 0 )
  237. {
  238. STARTUPINFO si;
  239. PROCESS_INFORMATION pi;
  240. HANDLE h;
  241. h = OpenEvent( SYNCHRONIZE, FALSE, DDHELP_STARTUP_EVENT_NAME );
  242. if( h == NULL )
  243. {
  244. si.cb = sizeof(STARTUPINFO);
  245. si.lpReserved = NULL;
  246. si.lpDesktop = NULL;
  247. si.lpTitle = NULL;
  248. si.dwFlags = 0;
  249. si.cbReserved2 = 0;
  250. si.lpReserved2 = NULL;
  251. DPF( 3, "Creating helper process now" );
  252. if( !CreateProcess(NULL, "ddhelp.exe", NULL, NULL, FALSE,
  253. NORMAL_PRIORITY_CLASS,
  254. NULL, NULL, &si, &pi) )
  255. {
  256. DPF( 2, "Could not create DDHELP.EXE" );
  257. return FALSE;
  258. }
  259. dwHelperPid = pi.dwProcessId;
  260. DPF( 3, "Helper rocess created" );
  261. }
  262. else
  263. {
  264. DDHELPDATA hd;
  265. DPF( 3, "DDHELP already exists, waiting for DDHELP event" );
  266. WaitForSingleObject( h, INFINITE );
  267. CloseHandle( h );
  268. DPF( 3, "Asking for DDHELP pid" );
  269. hd.req = DDHELPREQ_RETURNHELPERPID;
  270. sendRequest( &hd );
  271. dwHelperPid = hd.pid;
  272. DPF( 3, "DDHELP pid = %08lx", dwHelperPid );
  273. }
  274. *ppid = dwHelperPid;
  275. return TRUE;
  276. }
  277. *ppid = dwHelperPid;
  278. return FALSE;
  279. } /* CreateHelperProcess */
  280. #ifndef WINNT //this is Just For Now... dsound will get the help it needs..jeffno 951206
  281. /*
  282. * HelperWaveOpen
  283. *
  284. * get the helper to load a DLL for us.
  285. */
  286. DWORD HelperWaveOpen( LPVOID lphwo, DWORD dwDeviceID, LPVOID pwfx )
  287. {
  288. DDHELPDATA hd;
  289. if( (lphwo != NULL) && (pwfx != NULL) )
  290. {
  291. hd.req = DDHELPREQ_WAVEOPEN;
  292. hd.pData1 = lphwo;
  293. hd.dwData1 = dwDeviceID;
  294. hd.dwData2 = (DWORD)pwfx;
  295. DPF( 3, "Asking DDHELP to Open Wave Device %d", dwDeviceID );
  296. sendRequest( &hd );
  297. return hd.dwReturn;
  298. }
  299. else
  300. {
  301. DPF( 3, "Helper Wave Open param error");
  302. return MMSYSERR_ERROR;
  303. }
  304. } /* HelperWaveOpen */
  305. /*
  306. * HelperWaveClose
  307. *
  308. * get the helper to load a DLL for us.
  309. */
  310. DWORD HelperWaveClose( DWORD hwo )
  311. {
  312. DDHELPDATA hd;
  313. if( (hwo != 0) )
  314. {
  315. hd.req = DDHELPREQ_WAVECLOSE;
  316. hd.dwData1 = hwo;
  317. DPF( 3, "Asking DDHELP to Close Wave Device ");
  318. sendRequest( &hd );
  319. return hd.dwReturn;
  320. }
  321. else
  322. {
  323. DPF( 3, "Helper Wave Close param error");
  324. return MMSYSERR_ERROR;
  325. }
  326. } /* HelperWaveClose */
  327. /*
  328. * HelperCreateTimer
  329. *
  330. * get the helper to load a DLL for us.
  331. */
  332. DWORD HelperCreateTimer( DWORD dwResolution,
  333. LPVOID pTimerProc,
  334. DWORD dwInstanceData )
  335. {
  336. DDHELPDATA hd;
  337. if( (dwResolution != 0) && (pTimerProc != NULL) )
  338. {
  339. hd.req = DDHELPREQ_CREATETIMER;
  340. hd.pData1 = pTimerProc;
  341. hd.dwData1 = dwResolution;
  342. hd.dwData2 = dwInstanceData;
  343. DPF( 3, "Asking DDHELP to Create Timer" );
  344. sendRequest( &hd );
  345. return hd.dwReturn;
  346. }
  347. else
  348. {
  349. DPF( 3, "Helper Wave Close param error");
  350. return MMSYSERR_ERROR;
  351. }
  352. } /* HelperCreateTimer */
  353. /*
  354. * HelperKillTimer
  355. *
  356. * get the helper to load a DLL for us.
  357. */
  358. DWORD HelperKillTimer( DWORD dwTimerID )
  359. {
  360. DDHELPDATA hd;
  361. if( (dwTimerID != 0) )
  362. {
  363. hd.req = DDHELPREQ_KILLTIMER;
  364. hd.dwData1 = dwTimerID;
  365. DPF( 3, "Asking DDHELP to KILL Timer %X", dwTimerID );
  366. sendRequest( &hd );
  367. return hd.dwReturn;
  368. }
  369. else
  370. {
  371. DPF( 3, "Helper Wave Close param error");
  372. return MMSYSERR_ERROR;
  373. }
  374. } /* HelperKillTimer */
  375. /*
  376. * HelperCreateDSMixerThread
  377. *
  378. * get the helper to create a mixer thread.
  379. */
  380. HANDLE HelperCreateDSMixerThread( LPTHREAD_START_ROUTINE pfnThreadFunc,
  381. LPDWORD pdwThreadParam,
  382. DWORD dwFlags,
  383. LPDWORD pThreadId )
  384. {
  385. DDHELPDATA hd;
  386. hd.req = DDHELPREQ_CREATEDSMIXERTHREAD;
  387. hd.pData1 = pfnThreadFunc;
  388. hd.dwData1 = (DWORD)pdwThreadParam;
  389. hd.dwData2 = dwFlags;
  390. hd.pData2 = pThreadId;
  391. sendRequest( &hd );
  392. return (HANDLE)hd.dwReturn;
  393. } /* HelperCreateDSMixerThread
  394. /*
  395. * HelperCreateDSFocusThread
  396. *
  397. * get the helper to create a sound focus thread.
  398. */
  399. HANDLE HelperCreateDSFocusThread( LPTHREAD_START_ROUTINE pfnThreadFunc,
  400. LPDWORD pdwThreadParam,
  401. DWORD dwFlags,
  402. LPDWORD pThreadId )
  403. {
  404. DDHELPDATA hd;
  405. hd.req = DDHELPREQ_CREATEDSFOCUSTHREAD;
  406. hd.pData1 = pfnThreadFunc;
  407. hd.dwData1 = (DWORD)pdwThreadParam;
  408. hd.dwData2 = dwFlags;
  409. hd.pData2 = pThreadId;
  410. sendRequest( &hd );
  411. return (HANDLE)hd.dwReturn;
  412. } /* HelperCreateDSFocusThread
  413. /*
  414. * HelperCallDSEmulatorCleanup
  415. *
  416. * Call the DirectSound function which cleans up MMSYSTEM handles
  417. */
  418. void HelperCallDSEmulatorCleanup( LPVOID callback,
  419. LPVOID pDirectSound )
  420. {
  421. DDHELPDATA hd;
  422. hd.req = DDHELPREQ_CALLDSCLEANUP;
  423. hd.pData1 = callback;
  424. hd.pData2 = pDirectSound;
  425. sendRequest( &hd );
  426. }
  427. #endif //not winnt -just for now-jeffno
  428. /*
  429. * HelperCreateModeSetThread
  430. *
  431. * get the helper to load a DLL for us.
  432. */
  433. BOOL HelperCreateModeSetThread(
  434. LPVOID callback,
  435. HANDLE *ph,
  436. LPVOID lpdd,
  437. DWORD hInstance )
  438. {
  439. DDHELPDATA hd;
  440. HANDLE h;
  441. char str[64];
  442. hd.req = DDHELPREQ_CREATEMODESETTHREAD;
  443. hd.lpModeSetNotify = callback;
  444. hd.pData1 = lpdd;
  445. hd.dwData1 = hInstance;
  446. sendRequest( &hd );
  447. wsprintf( str, DDHELP_MODESET_EVENT_NAME, hInstance );
  448. DPF( 3, "Trying to open event \"%s\"", str );
  449. h = OpenEvent( SYNCHRONIZE, FALSE, str );
  450. if( h == NULL )
  451. {
  452. DPF( 3, "Could not open modeset event!" );
  453. *ph = NULL;
  454. return FALSE;
  455. }
  456. *ph = h;
  457. DPF( 1, "HelperCreateModeSetThread GotEvent: %08lx", h );
  458. return TRUE;
  459. } /* HelperCreateModeSetThread */
  460. /*
  461. * HelperKillModeSetThread
  462. *
  463. * get the helper to load a DLL for us.
  464. */
  465. void HelperKillModeSetThread( DWORD hInstance )
  466. {
  467. DDHELPDATA hd;
  468. hd.req = DDHELPREQ_KILLMODESETTHREAD;
  469. hd.dwData1 = hInstance;
  470. sendRequest( &hd );
  471. } /* HelperKillModeSetThread */
  472. /*
  473. * HelperCreateDOSBoxThread
  474. *
  475. * get the helper to create a thread so kernel mode can notify us of DOS box
  476. * changes.
  477. */
  478. BOOL HelperCreateDOSBoxThread(
  479. LPVOID callback,
  480. HANDLE *ph,
  481. LPVOID lpdd,
  482. DWORD hInstance )
  483. {
  484. DDHELPDATA hd;
  485. HANDLE h;
  486. char str[64];
  487. hd.req = DDHELPREQ_CREATEDOSBOXTHREAD;
  488. hd.lpModeSetNotify = callback;
  489. hd.pData1 = lpdd;
  490. hd.dwData1 = hInstance;
  491. sendRequest( &hd );
  492. wsprintf( str, DDHELP_DOSBOX_EVENT_NAME, hInstance );
  493. DPF( 3, "Trying to open event \"%s\"", str );
  494. h = OpenEvent( SYNCHRONIZE, FALSE, str );
  495. if( h == NULL )
  496. {
  497. DPF( 3, "Could not open DOS box event!" );
  498. *ph = NULL;
  499. return FALSE;
  500. }
  501. *ph = h;
  502. DPF( 1, "HelperCreateDOSBoxThread GotEvent: %08lx", h );
  503. return TRUE;
  504. } /* HelperCreateDOSBoxThread */
  505. /*
  506. * HelperKillDOSBoxThread
  507. *
  508. * get the helper to load a DLL for us.
  509. */
  510. void HelperKillDOSBoxThread( DWORD hInstance )
  511. {
  512. DDHELPDATA hd;
  513. hd.req = DDHELPREQ_KILLDOSBOXTHREAD;
  514. hd.dwData1 = hInstance;
  515. sendRequest( &hd );
  516. } /* HelperKillDOSBoxThread */
  517. // notify dphelp.c that we have a new server on this system
  518. DWORD HelperAddDPlayServer(DWORD port)
  519. {
  520. DDHELPDATA hd;
  521. DWORD pid = GetCurrentProcessId();
  522. memset(&hd, 0, sizeof(DDHELPDATA));
  523. hd.req = DDHELPREQ_DPLAYADDSERVER;
  524. hd.pid = pid;
  525. hd. dwData1 = port;
  526. if (sendRequest(&hd))
  527. return (hd.dwReturn);
  528. else
  529. return ((DWORD) E_FAIL);
  530. } // HelperAddDPlayServer
  531. // server is going away
  532. BOOL HelperDeleteDPlayServer(void)
  533. {
  534. DDHELPDATA hd;
  535. DWORD pid = GetCurrentProcessId();
  536. hd.req = DDHELPREQ_DPLAYDELETESERVER;
  537. hd.pid = pid;
  538. return sendRequest(&hd);
  539. } // HelperDeleteDPlayServer
  540. #ifdef WIN95
  541. /*
  542. * Get DDHELP to load the DirectSound VXD (if it has not
  543. * already done so) and return a handle to the VXD)
  544. */
  545. HANDLE HelperGetDSVxd( void )
  546. {
  547. DDHELPDATA hd;
  548. hd.req = DDHELPREQ_GETDSVXDHANDLE;
  549. sendRequest( &hd );
  550. return (HANDLE) hd.dwReturn;
  551. } /* HelperGetDSVxd */
  552. #endif /* WIN95 */
  553. /*
  554. * HelperSetOnDisplayChangeNotify
  555. *
  556. * get the helper to call us back if there is DisplayChange
  557. * message. (This is for multi-mon topology changes.)
  558. */
  559. void HelperSetOnDisplayChangeNotify( void *pfn )
  560. {
  561. DDHELPDATA hd;
  562. hd.req = DDHELPREQ_NOTIFYONDISPLAYCHANGE;
  563. hd.dwData1 = (DWORD)pfn;
  564. sendRequest( &hd );
  565. return;
  566. }