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.

629 lines
17 KiB

  1. //==========================================================================;
  2. //
  3. // startaud.c
  4. //
  5. // Copyright (c) 1991-2002 Microsoft Corporation. All Rights Reserved.
  6. //
  7. // Description:
  8. //
  9. //
  10. // History:
  11. // 07/02 tsharp (Trey Sharp);
  12. //
  13. //
  14. //==========================================================================;
  15. #include "mmcpl.h"
  16. #include <windowsx.h>
  17. #include <mmsystem.h>
  18. #include <dbt.h>
  19. #include <mmreg.h>
  20. #include <msacm.h>
  21. #include <msacmdrv.h>
  22. #include <msacmdlg.h>
  23. #include <stdlib.h>
  24. #include "gfxui.h"
  25. #include "drivers.h"
  26. #include "advaudio.h"
  27. #include "roland.h"
  28. #include <objbase.h>
  29. #include <setupapi.h>
  30. #include <cfgmgr32.h>
  31. #include <initguid.h>
  32. #include <devguid.h>
  33. #include <mmddkp.h>
  34. #include <ks.h>
  35. #include <ksmedia.h>
  36. #include <memory.h>
  37. #include <commctrl.h>
  38. #include <prsht.h>
  39. #include <regstr.h>
  40. #include "trayvol.h"
  41. #include "utils.h"
  42. #include "medhelp.h"
  43. #include "start.h"
  44. #include <wincred.h>
  45. #include <strsafe.h>
  46. /*
  47. ***************************************************************
  48. * Typedefs
  49. ***************************************************************
  50. */
  51. /*
  52. ***************************************************************
  53. * File Globals
  54. ***************************************************************
  55. */
  56. HWND ghStartDlg;
  57. /*
  58. ***************************************************************
  59. * extern
  60. ***************************************************************
  61. */
  62. /*
  63. ***************************************************************
  64. * Prototypes
  65. ***************************************************************
  66. */
  67. BOOL PASCAL DoStartPropCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify);
  68. BOOL PASCAL DoStartCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify);
  69. BOOL MarkRegistryForReboot(void);
  70. //
  71. //
  72. //
  73. BOOL QueryPnpAudioDeviceAvailable(void)
  74. {
  75. HDEVINFO hDevInfo;
  76. BOOL fFound;
  77. int i;
  78. GUID guidAudio = KSCATEGORY_AUDIO;
  79. GUID guidRender = KSCATEGORY_RENDER;
  80. GUID guidCapture = KSCATEGORY_CAPTURE;
  81. hDevInfo = SetupDiGetClassDevs(&guidAudio, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
  82. if (INVALID_HANDLE_VALUE == hDevInfo) return FALSE;
  83. for (i = 0, fFound = FALSE; !fFound; i++)
  84. {
  85. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  86. SP_DEVICE_INTERFACE_DATA AliasDeviceInterfaceData;
  87. BOOL fRender;
  88. BOOL fCapture;
  89. DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData);
  90. if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &guidAudio, i, &DeviceInterfaceData)) break;
  91. AliasDeviceInterfaceData.cbSize = sizeof(AliasDeviceInterfaceData);
  92. fRender = SetupDiGetDeviceInterfaceAlias(hDevInfo, &DeviceInterfaceData, &guidRender, &AliasDeviceInterfaceData);
  93. AliasDeviceInterfaceData.cbSize = sizeof(AliasDeviceInterfaceData);
  94. fCapture = SetupDiGetDeviceInterfaceAlias(hDevInfo, &DeviceInterfaceData, &guidCapture, &AliasDeviceInterfaceData);
  95. fFound = (fRender || fCapture);
  96. }
  97. SetupDiDestroyDeviceInfoList(hDevInfo);
  98. return fFound;
  99. }
  100. //
  101. // OUT pStartType is starttype of audiosrv. Normally SERVICE_AUTO_START.
  102. //
  103. // Return value is a winerror.h code.
  104. //
  105. DWORD QueryAudiosrvStartType(OUT PDWORD pStartType)
  106. {
  107. SC_HANDLE schScm;
  108. LONG error = NO_ERROR;
  109. HANDLE hHeap;
  110. hHeap = GetProcessHeap();
  111. if (!hHeap) return GetLastError();
  112. //
  113. // Attempt to start the AudioSrv Win32 service
  114. //
  115. schScm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  116. if (schScm) {
  117. SC_HANDLE schAudioSrv;
  118. schAudioSrv = OpenService(schScm, TEXT("AudioSrv"), SERVICE_QUERY_CONFIG);
  119. if (schAudioSrv) {
  120. BOOL success;
  121. DWORD cbBytesNeeded;
  122. // Read the start type
  123. success = QueryServiceConfig(schAudioSrv, NULL, 0, &cbBytesNeeded);
  124. if (success) error = ERROR_INVALID_PARAMETER; // Highly unexpected.
  125. else error = GetLastError();
  126. if (ERROR_INSUFFICIENT_BUFFER == error)
  127. {
  128. LPQUERY_SERVICE_CONFIG pServiceConfig;
  129. error = NO_ERROR;
  130. pServiceConfig = (LPQUERY_SERVICE_CONFIG)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbBytesNeeded);
  131. if (!pServiceConfig) error = ERROR_OUTOFMEMORY;
  132. if (!error)
  133. {
  134. success = QueryServiceConfig(schAudioSrv, pServiceConfig, cbBytesNeeded, &cbBytesNeeded);
  135. if (success)
  136. {
  137. *pStartType = pServiceConfig->dwStartType;
  138. }
  139. HeapFree(hHeap, 0, pServiceConfig);
  140. }
  141. }
  142. CloseServiceHandle(schAudioSrv);
  143. } else {
  144. error = GetLastError();
  145. }
  146. CloseServiceHandle(schScm);
  147. } else {
  148. error = GetLastError();
  149. }
  150. return error;
  151. }
  152. //
  153. // Return value is a winerror.h code.
  154. // ERROR_ACCESS_DENIED - user hasn't proper credentials
  155. //
  156. DWORD SetAudiosrvAsAutoStart(void)
  157. {
  158. SC_HANDLE schScm;
  159. LONG error = NO_ERROR;
  160. //
  161. // Attempt to start the AudioSrv Win32 service
  162. //
  163. schScm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  164. if (schScm) {
  165. SC_HANDLE schAudioSrv;
  166. schAudioSrv = OpenService(schScm, TEXT("AudioSrv"), SERVICE_CHANGE_CONFIG);
  167. if (schAudioSrv) {
  168. BOOL success;
  169. // Change the start type to automatic
  170. success = ChangeServiceConfig(schAudioSrv,
  171. SERVICE_NO_CHANGE, // ServiceType
  172. SERVICE_AUTO_START, // StartType
  173. SERVICE_NO_CHANGE, // ErrorControl
  174. NULL, // BinaryPathName
  175. NULL, // LoadOrderGroup
  176. NULL, // TagId
  177. NULL, // Dependencies
  178. NULL, // ServiceStartName
  179. NULL, // Password
  180. NULL // DisplayName
  181. );
  182. if (!success) error = GetLastError();
  183. CloseServiceHandle(schAudioSrv);
  184. } else {
  185. error = GetLastError();
  186. }
  187. CloseServiceHandle(schScm);
  188. } else {
  189. error = GetLastError();
  190. }
  191. return error;
  192. }
  193. DWORD RetrieveCredentials( TCHAR* pszUserName, DWORD cbUserNameSize,
  194. TCHAR* pszDomain, DWORD cbDomainSize,
  195. TCHAR* pszPassword, DWORD cbPasswordSize,
  196. UINT nPromptId )
  197. {
  198. TCHAR achTitle[CREDUI_TITLE_MAX_LENGTH];
  199. TCHAR achPrompt[CREDUI_PROMPT_MAX_LENGTH];
  200. CREDUI_INFO uiInfo;
  201. TCHAR achUserName[CREDUI_MAX_USERNAME_LENGTH + 1];
  202. TCHAR achDomain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1];
  203. TCHAR achPassword[CREDUI_MAX_PASSWORD_LENGTH + 1];
  204. DWORD dwError = ERROR_CANCELLED;
  205. if( pszUserName == NULL || pszDomain == NULL || pszPassword == NULL )
  206. {
  207. return ERROR_CANCELLED;
  208. }
  209. LoadString( ghInstance, IDS_CREDUI_TITLE, achTitle, CREDUI_TITLE_MAX_LENGTH );
  210. LoadString( ghInstance, nPromptId, achPrompt, CREDUI_PROMPT_MAX_LENGTH );
  211. ZeroMemory( &uiInfo, sizeof(uiInfo) );
  212. uiInfo.cbSize = sizeof(uiInfo);
  213. uiInfo.hwndParent = ghStartDlg;
  214. uiInfo.pszMessageText = achPrompt;
  215. uiInfo.pszCaptionText = achTitle;
  216. ZeroMemory( achUserName, sizeof(achUserName) );
  217. ZeroMemory( achDomain, sizeof(achDomain) );
  218. ZeroMemory( achPassword, sizeof(achPassword) );
  219. dwError = CredUIPromptForCredentials( &uiInfo, NULL, NULL,
  220. NO_ERROR,
  221. achUserName, CREDUI_MAX_USERNAME_LENGTH + 1,
  222. achPassword, CREDUI_MAX_PASSWORD_LENGTH + 1,
  223. NULL,
  224. CREDUI_FLAGS_DO_NOT_PERSIST | \
  225. CREDUI_FLAGS_VALIDATE_USERNAME | \
  226. CREDUI_FLAGS_EXCLUDE_CERTIFICATES | \
  227. CREDUI_FLAGS_REQUEST_ADMINISTRATOR | \
  228. CREDUI_FLAGS_GENERIC_CREDENTIALS );
  229. if( dwError == NO_ERROR )
  230. {
  231. dwError = CredUIParseUserName( achUserName,
  232. pszUserName, (cbUserNameSize / sizeof(pszUserName[0])),
  233. pszDomain, (cbDomainSize / sizeof(pszDomain[0])) );
  234. if( dwError == NO_ERROR )
  235. {
  236. if( StringCbCopy(pszPassword, cbPasswordSize, achPassword) != S_OK )
  237. {
  238. dwError = ERROR_INSUFFICIENT_BUFFER;
  239. }
  240. }
  241. }
  242. // Check to see if an error occurred along the way
  243. if( dwError != NO_ERROR )
  244. {
  245. // Clear domain/username/password from memory
  246. SecureZeroMemory( pszUserName, cbUserNameSize );
  247. SecureZeroMemory( pszDomain, cbDomainSize );
  248. SecureZeroMemory( pszPassword, cbPasswordSize );
  249. if( dwError != ERROR_CANCELLED )
  250. {
  251. TCHAR achTitle[CREDUI_TITLE_MAX_LENGTH];
  252. int nError = GetLastError();
  253. LPTSTR pszMessageBuffer;
  254. LoadString( ghInstance, IDS_CREDUI_TITLE, achTitle, CREDUI_TITLE_MAX_LENGTH );
  255. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  256. NULL,
  257. nError,
  258. MAKELANGID(LANG_NEUTRAL,
  259. SUBLANG_DEFAULT),
  260. (LPTSTR)&pszMessageBuffer,
  261. 0,
  262. NULL );
  263. MessageBox( ghStartDlg, pszMessageBuffer, achTitle, MB_OK );
  264. LocalFree( pszMessageBuffer );
  265. }
  266. }
  267. return dwError;
  268. }
  269. DWORD AttemptToGetAdminPrivilege( HANDLE* phToken, UINT nPromptId )
  270. {
  271. TCHAR achUserName[CREDUI_MAX_USERNAME_LENGTH + 1];
  272. TCHAR achDomain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1];
  273. TCHAR achPassword[CREDUI_MAX_PASSWORD_LENGTH + 1];
  274. DWORD dwError = ERROR_CANCELLED;
  275. if( phToken == NULL )
  276. {
  277. return ERROR_CANCELLED;
  278. }
  279. *phToken = NULL;
  280. // Ask for administrator credentials
  281. dwError = RetrieveCredentials( achUserName, sizeof(achUserName),
  282. achDomain, sizeof(achDomain),
  283. achPassword, sizeof(achPassword),
  284. nPromptId );
  285. if( dwError == NO_ERROR )
  286. {
  287. HANDLE hAdminToken;
  288. // Attempt to logon
  289. if( LogonUser(achUserName, achDomain, achPassword,
  290. LOGON32_LOGON_INTERACTIVE,
  291. LOGON32_PROVIDER_DEFAULT, &hAdminToken) )
  292. {
  293. // Attempt to impersonate logged on user
  294. if( ImpersonateLoggedOnUser(hAdminToken) )
  295. {
  296. *phToken = hAdminToken;
  297. }
  298. else
  299. {
  300. // Impersonation failed
  301. CloseHandle( hAdminToken );
  302. dwError = ERROR_CANNOT_IMPERSONATE;
  303. }
  304. }
  305. else
  306. {
  307. // Logon failed
  308. dwError = ERROR_LOGON_FAILURE;
  309. }
  310. // Was logon successful?
  311. if( dwError != NO_ERROR )
  312. {
  313. // Logon failed
  314. TCHAR achTitle[CREDUI_TITLE_MAX_LENGTH];
  315. LPTSTR pszMessageBuffer;
  316. int nError;
  317. LoadString( ghInstance, IDS_CREDUI_TITLE, achTitle, CREDUI_TITLE_MAX_LENGTH );
  318. nError = GetLastError();
  319. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  320. NULL,
  321. nError,
  322. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  323. (LPTSTR)&pszMessageBuffer,
  324. 0,
  325. NULL );
  326. MessageBox( ghStartDlg, pszMessageBuffer, achTitle, MB_OK );
  327. LocalFree( pszMessageBuffer );
  328. }
  329. }
  330. // Clear domain/username/password from memory
  331. SecureZeroMemory( achUserName, sizeof(achUserName) );
  332. SecureZeroMemory( achDomain, sizeof(achDomain) );
  333. SecureZeroMemory( achPassword, sizeof(achPassword) );
  334. return dwError;
  335. }
  336. HANDLE GetAdminPrivilege( UINT nPromptId )
  337. {
  338. HANDLE hToken = NULL;
  339. BOOL fDone = FALSE;
  340. do
  341. {
  342. DWORD dwError = AttemptToGetAdminPrivilege( &hToken, nPromptId );
  343. if( dwError == NO_ERROR || dwError == ERROR_CANCELLED )
  344. {
  345. fDone = TRUE;
  346. }
  347. }
  348. while( fDone == FALSE );
  349. return hToken;
  350. }
  351. void ReleaseAdminPrivilege( HANDLE hToken )
  352. {
  353. if( hToken )
  354. {
  355. RevertToSelf();
  356. CloseHandle( hToken );
  357. }
  358. }
  359. STATIC void STARTAUDIOInit(HWND hDlg)
  360. {
  361. ghStartDlg = hDlg;
  362. }
  363. const static DWORD aStartHelpIds[] = { // Context Help IDs
  364. IDC_GROUPBOX_START_1, NO_HELP,
  365. IDC_ICON_START_1, NO_HELP,
  366. IDC_TEXT_START_1, NO_HELP,
  367. IDC_START_CHECK, NO_HELP,
  368. IDC_TEXT_START_2, NO_HELP,
  369. IDC_TEXT_START_3, NO_HELP,
  370. IDC_TEXT_START_4, NO_HELP,
  371. 0, 0
  372. };
  373. BOOL CALLBACK StartDlg(HWND hDlg, UINT uMsg, WPARAM wParam,
  374. LPARAM lParam)
  375. {
  376. NMHDR FAR *lpnm;
  377. switch (uMsg)
  378. {
  379. case WM_NOTIFY:
  380. {
  381. lpnm = (NMHDR FAR *)lParam;
  382. switch(lpnm->code)
  383. {
  384. case PSN_KILLACTIVE:
  385. FORWARD_WM_COMMAND(hDlg, IDOK, 0, 0, SendMessage);
  386. break;
  387. case PSN_APPLY:
  388. FORWARD_WM_COMMAND(hDlg, ID_APPLY, 0, 0, SendMessage);
  389. break;
  390. case PSN_SETACTIVE:
  391. FORWARD_WM_COMMAND(hDlg, ID_INIT, 0, 0, SendMessage);
  392. break;
  393. case PSN_RESET:
  394. FORWARD_WM_COMMAND(hDlg, IDCANCEL, 0, 0, SendMessage);
  395. break;
  396. }
  397. }
  398. break;
  399. case WM_INITDIALOG:
  400. {
  401. STARTAUDIOInit(hDlg);
  402. }
  403. break;
  404. case WM_DESTROY:
  405. {
  406. }
  407. break;
  408. case WM_CONTEXTMENU:
  409. {
  410. WinHelp ((HWND) wParam, NULL, HELP_CONTEXTMENU, (DWORD_PTR) (LPSTR) aStartHelpIds);
  411. return TRUE;
  412. }
  413. break;
  414. case WM_HELP:
  415. {
  416. LPHELPINFO lphi = (LPVOID) lParam;
  417. WinHelp (lphi->hItemHandle, NULL, HELP_WM_HELP, (DWORD_PTR) (LPSTR) aStartHelpIds);
  418. return TRUE;
  419. }
  420. break;
  421. case WM_COMMAND:
  422. {
  423. HANDLE_WM_COMMAND(hDlg, wParam, lParam, DoStartCommand);
  424. }
  425. break;
  426. default:
  427. {
  428. }
  429. break;
  430. }
  431. return FALSE;
  432. }
  433. void ErrorStartMsgBox(HWND hDlg, UINT uTitle, UINT uMessage)
  434. {
  435. TCHAR szMsg[MAXSTR];
  436. TCHAR szTitle[MAXSTR];
  437. LoadString(ghInstance, uTitle, szTitle, sizeof(szTitle)/sizeof(TCHAR));
  438. LoadString(ghInstance, uMessage, szMsg, sizeof(szMsg)/sizeof(TCHAR));
  439. MessageBox(hDlg, szMsg,szTitle,MB_OK);
  440. }
  441. BOOL PASCAL DoStartCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
  442. {
  443. switch (id)
  444. {
  445. case IDOK:
  446. {
  447. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_START_CHECK))
  448. {
  449. DWORD dwError;
  450. dwError = SetAudiosrvAsAutoStart();
  451. if( dwError == NO_ERROR )
  452. {
  453. MarkRegistryForReboot();
  454. RebootSystem( hDlg, FALSE, TRUE, TRUE );
  455. }
  456. else
  457. {
  458. while( dwError == ERROR_ACCESS_DENIED )
  459. {
  460. HANDLE hToken = GetAdminPrivilege( IDS_CREDUI_PROMPT );
  461. if( hToken )
  462. {
  463. dwError = SetAudiosrvAsAutoStart();
  464. if( dwError == NO_ERROR )
  465. {
  466. MarkRegistryForReboot();
  467. RebootSystem( hDlg, TRUE, TRUE, TRUE );
  468. }
  469. ReleaseAdminPrivilege( hToken );
  470. }
  471. else
  472. {
  473. // User cancelled credentials UI, so force CPL to remain open
  474. gfRedisplayCPL = TRUE;
  475. // Force break from while statement
  476. dwError = ERROR_CANCELLED;
  477. }
  478. }
  479. }
  480. }
  481. }
  482. break;
  483. }
  484. return FALSE;
  485. }
  486. BOOL MarkRegistryForReboot(void)
  487. {
  488. HKEY hkTmp;
  489. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE
  490. ,REGSTR_TEMP_REBOOT
  491. ,0
  492. ,NULL
  493. ,REG_OPTION_VOLATILE
  494. ,KEY_WRITE
  495. ,NULL
  496. ,&hkTmp
  497. ,NULL ) == ERROR_SUCCESS)
  498. {
  499. RegCloseKey(hkTmp);
  500. return TRUE;
  501. }
  502. return FALSE;
  503. }
  504. BOOL AudioServiceStarted(void)
  505. {
  506. if (QueryPnpAudioDeviceAvailable())
  507. {
  508. DWORD dwRetCode = 0;
  509. DWORD dwStartType = 0;
  510. dwRetCode = QueryAudiosrvStartType(&dwStartType); // Check return nessesary?
  511. if (SERVICE_AUTO_START == dwStartType)
  512. {
  513. return TRUE;
  514. } else
  515. {
  516. return FALSE;
  517. }
  518. }
  519. return TRUE;
  520. }