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.

255 lines
8.1 KiB

  1. /* File: audiosrvc.c */
  2. /* Copyright (c) 2000-2001 Microsoft Corporation */
  3. #define UNICODE
  4. #define _UNICODE
  5. #include "winmmi.h"
  6. #include "audiosrv.h"
  7. #define RPC_CALL_START RpcTryExcept {
  8. #define RPC_CALL_END_(status) } RpcExcept(1) { status = RpcExceptionCode(); } RpcEndExcept
  9. #define RPC_CALL_END } RpcExcept(1) { RpcExceptionCode(); } RpcEndExcept
  10. void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t cb)
  11. {
  12. return HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cb);
  13. }
  14. void __RPC_USER MIDL_user_free( void __RPC_FAR * pv)
  15. {
  16. HeapFree(hHeap, 0, pv);
  17. }
  18. LONG AudioSrvBinding(void)
  19. {
  20. RPC_STATUS status;
  21. PTSTR pszUuid = NULL;
  22. PTSTR pszProtocolSequence = TEXT("ncalrpc");
  23. PTSTR pszNetworkAddress = NULL;
  24. PTSTR pszEndpoint = TEXT("AudioSrv");
  25. PTSTR pszOptions = NULL;
  26. PTSTR pszStringBinding = NULL;
  27. PTSTR pszString = NULL;
  28. // dprintf(("AudioSrvBinding"));
  29. WinAssert(NULL == AudioSrv_IfHandle);
  30. status = RpcStringBindingCompose(pszUuid,
  31. pszProtocolSequence,
  32. pszNetworkAddress,
  33. pszEndpoint,
  34. pszOptions,
  35. &pszStringBinding);
  36. if (RPC_S_OK == status)
  37. {
  38. status = RpcBindingFromStringBinding(pszStringBinding, &AudioSrv_IfHandle);
  39. RpcStringFree(&pszStringBinding);
  40. }
  41. if (RPC_S_OK != status) dprintf(("AudioSrvBinding: returning %d", status));
  42. return status;
  43. }
  44. void AudioSrvBindingFree(void)
  45. {
  46. RPC_STATUS status;
  47. // dprintf(("AudioSrvBindingFree"));
  48. status = AudioSrv_IfHandle ? RpcBindingFree(&AudioSrv_IfHandle) : RPC_S_OK;
  49. if (RPC_S_OK == status) WinAssert(NULL == AudioSrv_IfHandle);
  50. if (RPC_S_OK != status) dprintf(("AudioSrvBindingFree: RpcBindingFree returned %d", status));
  51. }
  52. BOOL winmmWaitForService(void)
  53. {
  54. static BOOL fWaited = FALSE;
  55. static BOOL fStarted = FALSE;
  56. const LONG Timeout = 120000;
  57. SC_HANDLE schScm = NULL;
  58. SC_HANDLE schAudioSrv = NULL;
  59. if (fWaited) return fStarted;
  60. schScm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  61. if (!schScm)
  62. {
  63. DWORD dw = GetLastError();
  64. dprintf(("winmmWaitForService: could not OpenSCManager, LastError=%d", dw));
  65. return FALSE;
  66. }
  67. schAudioSrv = OpenService(schScm, TEXT("AudioSrv"), SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS);
  68. if (schAudioSrv)
  69. {
  70. int cWaits = 0;
  71. while (!fWaited) {
  72. SERVICE_STATUS ServiceStatus;
  73. if (QueryServiceStatus(schAudioSrv, &ServiceStatus))
  74. {
  75. if ( (ServiceStatus.dwCurrentState == SERVICE_RUNNING) ||
  76. (ServiceStatus.dwCurrentState == SERVICE_CONTINUE_PENDING) ||
  77. (ServiceStatus.dwCurrentState == SERVICE_PAUSE_PENDING) ||
  78. (ServiceStatus.dwCurrentState == SERVICE_PAUSED) )
  79. {
  80. fStarted = TRUE;
  81. fWaited = TRUE;
  82. } else if (ServiceStatus.dwCurrentState == SERVICE_STOPPED &&
  83. ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED)
  84. {
  85. if (cWaits == 0)
  86. {
  87. DWORD cbNeeded;
  88. // Check that the service StartType is set such that
  89. // it will start
  90. if (QueryServiceConfig(schAudioSrv, NULL, 0, &cbNeeded) || ERROR_INSUFFICIENT_BUFFER == GetLastError())
  91. {
  92. QUERY_SERVICE_CONFIG *ServiceConfig;
  93. ServiceConfig = HeapAlloc(hHeap, 0, cbNeeded);
  94. if (ServiceConfig) {
  95. if (QueryServiceConfig(schAudioSrv, ServiceConfig, cbNeeded, &cbNeeded)) {
  96. if (ServiceConfig->dwStartType != SERVICE_AUTO_START) {
  97. fWaited = TRUE;
  98. }
  99. } else {
  100. DWORD dwLastError = GetLastError();
  101. dprintf(("winmmWaitForService: QueryServiceConfig failed LastError=%d", dwLastError));
  102. fWaited = TRUE;
  103. }
  104. HeapFree(hHeap, 0, ServiceConfig);
  105. } else {
  106. dprintf(("winmmWaitForService: HeapAlloc failed"));
  107. }
  108. } else {
  109. DWORD dwLastError = GetLastError();
  110. dprintf(("winmmWaitForService: QueryServiceConfig failed LastError=%d", dwLastError));
  111. fWaited = TRUE;
  112. }
  113. }
  114. } else if (ServiceStatus.dwCurrentState != SERVICE_START_PENDING)
  115. {
  116. // Unfamiliar dwCurrentState, or was started and then stopped
  117. fWaited = TRUE;
  118. }
  119. } else {
  120. DWORD dwLastError = GetLastError();
  121. dprintf(("winmmWaitForService: QueryServiceStatus failed LastError=%d", dwLastError));
  122. fWaited = TRUE;
  123. }
  124. if (!fWaited && ((cWaits * 2000) > Timeout))
  125. {
  126. dprintf(("winmmWaitForService timed out. Could be design problem. Open a bug!"));
  127. WinAssert(FALSE);
  128. fWaited = TRUE;
  129. }
  130. if (!fWaited) {
  131. Sleep(2000);
  132. cWaits++;
  133. }
  134. }
  135. CloseServiceHandle(schAudioSrv);
  136. } else {
  137. DWORD dwLastError = GetLastError();
  138. dprintf(("winmmWaitForService: OpenService failed LastError=%d", dwLastError));
  139. }
  140. CloseServiceHandle(schScm);
  141. return fStarted;
  142. }
  143. LONG winmmRegisterSessionNotificationEvent(HANDLE hEvent, PHANDLE phRegNotify)
  144. {
  145. LONG lresult;
  146. winmmWaitForService();
  147. RPC_CALL_START;
  148. lresult = s_winmmRegisterSessionNotificationEvent(GetCurrentProcessId(), (RHANDLE)hEvent, (PHANDLE_SESSIONNOTIFICATION)phRegNotify);
  149. RPC_CALL_END_(lresult);
  150. return lresult;
  151. }
  152. LONG winmmUnregisterSessionNotification(HANDLE hRegNotify)
  153. {
  154. LONG lresult;
  155. winmmWaitForService();
  156. RPC_CALL_START;
  157. // if (!AudioSrv_IfHandle) dprintf(("winmmUnregisterSessionNotification : warning: called with AudioSrv_IfHandle == NULL"));
  158. // If we have a binding handle, then let's call the server to close this
  159. // context handle otherwise we need to call RpcSsDestroyClientContext to
  160. // destroy it without contacting the server
  161. if (AudioSrv_IfHandle)
  162. {
  163. lresult = s_winmmUnregisterSessionNotification((PHANDLE_SESSIONNOTIFICATION)&hRegNotify);
  164. }
  165. else
  166. {
  167. RpcSsDestroyClientContext(&hRegNotify);
  168. lresult = RPC_S_OK;
  169. }
  170. RPC_CALL_END_(lresult);
  171. return lresult;
  172. }
  173. LONG winmmSessionConnectState(PINT ConnectState)
  174. {
  175. LONG lresult;
  176. winmmWaitForService();
  177. RPC_CALL_START;
  178. lresult = s_winmmSessionConnectState(GetCurrentProcessId(), ConnectState);
  179. RPC_CALL_END_(lresult);
  180. return lresult;
  181. }
  182. LONG wdmDriverOpenDrvRegKey(IN PCTSTR DeviceInterface, IN REGSAM samDesired, OUT HKEY *phkey)
  183. {
  184. LONG lresult;
  185. winmmWaitForService();
  186. RPC_CALL_START;
  187. lresult = s_wdmDriverOpenDrvRegKey(GetCurrentProcessId(), DeviceInterface, samDesired, (RHANDLE*)phkey);
  188. RPC_CALL_END_(lresult);
  189. return lresult;
  190. }
  191. void winmmAdvisePreferredDeviceChange(void)
  192. {
  193. winmmWaitForService();
  194. RPC_CALL_START;
  195. s_winmmAdvisePreferredDeviceChange();
  196. RPC_CALL_END;
  197. return;
  198. }
  199. LONG winmmGetPnpInfo(OUT LONG *pcbPnpInfo, OUT PMMPNPINFO *ppPnpInfo)
  200. {
  201. LONG cbPnpInfo = 0;
  202. BYTE *pPnpInfo = NULL;
  203. LONG lresult;
  204. winmmWaitForService();
  205. RPC_CALL_START;
  206. lresult = s_winmmGetPnpInfo(&cbPnpInfo, &pPnpInfo);
  207. RPC_CALL_END_(lresult);
  208. if (ERROR_SUCCESS == lresult)
  209. {
  210. *pcbPnpInfo = cbPnpInfo;
  211. *ppPnpInfo = (PMMPNPINFO)pPnpInfo;
  212. }
  213. return lresult;
  214. }