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

//==========================================================================;
//
// startaud.c
//
// Copyright (c) 1991-2002 Microsoft Corporation. All Rights Reserved.
//
// Description:
//
//
// History:
// 07/02 tsharp (Trey Sharp);
//
//
//==========================================================================;
#include "mmcpl.h"
#include <windowsx.h>
#include <mmsystem.h>
#include <dbt.h>
#include <mmreg.h>
#include <msacm.h>
#include <msacmdrv.h>
#include <msacmdlg.h>
#include <stdlib.h>
#include "gfxui.h"
#include "drivers.h"
#include "advaudio.h"
#include "roland.h"
#include <objbase.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <initguid.h>
#include <devguid.h>
#include <mmddkp.h>
#include <ks.h>
#include <ksmedia.h>
#include <memory.h>
#include <commctrl.h>
#include <prsht.h>
#include <regstr.h>
#include "trayvol.h"
#include "utils.h"
#include "medhelp.h"
#include "start.h"
#include <wincred.h>
#include <strsafe.h>
/*
***************************************************************
* Typedefs
***************************************************************
*/
/*
***************************************************************
* File Globals
***************************************************************
*/
HWND ghStartDlg;
/*
***************************************************************
* extern
***************************************************************
*/
/*
***************************************************************
* Prototypes
***************************************************************
*/
BOOL PASCAL DoStartPropCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify);
BOOL PASCAL DoStartCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify);
BOOL MarkRegistryForReboot(void);
//
//
//
BOOL QueryPnpAudioDeviceAvailable(void)
{
HDEVINFO hDevInfo;
BOOL fFound;
int i;
GUID guidAudio = KSCATEGORY_AUDIO;
GUID guidRender = KSCATEGORY_RENDER;
GUID guidCapture = KSCATEGORY_CAPTURE;
hDevInfo = SetupDiGetClassDevs(&guidAudio, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (INVALID_HANDLE_VALUE == hDevInfo) return FALSE;
for (i = 0, fFound = FALSE; !fFound; i++)
{
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
SP_DEVICE_INTERFACE_DATA AliasDeviceInterfaceData;
BOOL fRender;
BOOL fCapture;
DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData);
if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &guidAudio, i, &DeviceInterfaceData)) break;
AliasDeviceInterfaceData.cbSize = sizeof(AliasDeviceInterfaceData);
fRender = SetupDiGetDeviceInterfaceAlias(hDevInfo, &DeviceInterfaceData, &guidRender, &AliasDeviceInterfaceData);
AliasDeviceInterfaceData.cbSize = sizeof(AliasDeviceInterfaceData);
fCapture = SetupDiGetDeviceInterfaceAlias(hDevInfo, &DeviceInterfaceData, &guidCapture, &AliasDeviceInterfaceData);
fFound = (fRender || fCapture);
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return fFound;
}
//
// OUT pStartType is starttype of audiosrv. Normally SERVICE_AUTO_START.
//
// Return value is a winerror.h code.
//
DWORD QueryAudiosrvStartType(OUT PDWORD pStartType)
{
SC_HANDLE schScm;
LONG error = NO_ERROR;
HANDLE hHeap;
hHeap = GetProcessHeap();
if (!hHeap) return GetLastError();
//
// Attempt to start the AudioSrv Win32 service
//
schScm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (schScm) {
SC_HANDLE schAudioSrv;
schAudioSrv = OpenService(schScm, TEXT("AudioSrv"), SERVICE_QUERY_CONFIG);
if (schAudioSrv) {
BOOL success;
DWORD cbBytesNeeded;
// Read the start type
success = QueryServiceConfig(schAudioSrv, NULL, 0, &cbBytesNeeded);
if (success) error = ERROR_INVALID_PARAMETER; // Highly unexpected.
else error = GetLastError();
if (ERROR_INSUFFICIENT_BUFFER == error)
{
LPQUERY_SERVICE_CONFIG pServiceConfig;
error = NO_ERROR;
pServiceConfig = (LPQUERY_SERVICE_CONFIG)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbBytesNeeded);
if (!pServiceConfig) error = ERROR_OUTOFMEMORY;
if (!error)
{
success = QueryServiceConfig(schAudioSrv, pServiceConfig, cbBytesNeeded, &cbBytesNeeded);
if (success)
{
*pStartType = pServiceConfig->dwStartType;
}
HeapFree(hHeap, 0, pServiceConfig);
}
}
CloseServiceHandle(schAudioSrv);
} else {
error = GetLastError();
}
CloseServiceHandle(schScm);
} else {
error = GetLastError();
}
return error;
}
//
// Return value is a winerror.h code.
// ERROR_ACCESS_DENIED - user hasn't proper credentials
//
DWORD SetAudiosrvAsAutoStart(void)
{
SC_HANDLE schScm;
LONG error = NO_ERROR;
//
// Attempt to start the AudioSrv Win32 service
//
schScm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (schScm) {
SC_HANDLE schAudioSrv;
schAudioSrv = OpenService(schScm, TEXT("AudioSrv"), SERVICE_CHANGE_CONFIG);
if (schAudioSrv) {
BOOL success;
// Change the start type to automatic
success = ChangeServiceConfig(schAudioSrv,
SERVICE_NO_CHANGE, // ServiceType
SERVICE_AUTO_START, // StartType
SERVICE_NO_CHANGE, // ErrorControl
NULL, // BinaryPathName
NULL, // LoadOrderGroup
NULL, // TagId
NULL, // Dependencies
NULL, // ServiceStartName
NULL, // Password
NULL // DisplayName
);
if (!success) error = GetLastError();
CloseServiceHandle(schAudioSrv);
} else {
error = GetLastError();
}
CloseServiceHandle(schScm);
} else {
error = GetLastError();
}
return error;
}
DWORD RetrieveCredentials( TCHAR* pszUserName, DWORD cbUserNameSize,
TCHAR* pszDomain, DWORD cbDomainSize,
TCHAR* pszPassword, DWORD cbPasswordSize,
UINT nPromptId )
{
TCHAR achTitle[CREDUI_TITLE_MAX_LENGTH];
TCHAR achPrompt[CREDUI_PROMPT_MAX_LENGTH];
CREDUI_INFO uiInfo;
TCHAR achUserName[CREDUI_MAX_USERNAME_LENGTH + 1];
TCHAR achDomain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1];
TCHAR achPassword[CREDUI_MAX_PASSWORD_LENGTH + 1];
DWORD dwError = ERROR_CANCELLED;
if( pszUserName == NULL || pszDomain == NULL || pszPassword == NULL )
{
return ERROR_CANCELLED;
}
LoadString( ghInstance, IDS_CREDUI_TITLE, achTitle, CREDUI_TITLE_MAX_LENGTH );
LoadString( ghInstance, nPromptId, achPrompt, CREDUI_PROMPT_MAX_LENGTH );
ZeroMemory( &uiInfo, sizeof(uiInfo) );
uiInfo.cbSize = sizeof(uiInfo);
uiInfo.hwndParent = ghStartDlg;
uiInfo.pszMessageText = achPrompt;
uiInfo.pszCaptionText = achTitle;
ZeroMemory( achUserName, sizeof(achUserName) );
ZeroMemory( achDomain, sizeof(achDomain) );
ZeroMemory( achPassword, sizeof(achPassword) );
dwError = CredUIPromptForCredentials( &uiInfo, NULL, NULL,
NO_ERROR,
achUserName, CREDUI_MAX_USERNAME_LENGTH + 1,
achPassword, CREDUI_MAX_PASSWORD_LENGTH + 1,
NULL,
CREDUI_FLAGS_DO_NOT_PERSIST | \
CREDUI_FLAGS_VALIDATE_USERNAME | \
CREDUI_FLAGS_EXCLUDE_CERTIFICATES | \
CREDUI_FLAGS_REQUEST_ADMINISTRATOR | \
CREDUI_FLAGS_GENERIC_CREDENTIALS );
if( dwError == NO_ERROR )
{
dwError = CredUIParseUserName( achUserName,
pszUserName, (cbUserNameSize / sizeof(pszUserName[0])),
pszDomain, (cbDomainSize / sizeof(pszDomain[0])) );
if( dwError == NO_ERROR )
{
if( StringCbCopy(pszPassword, cbPasswordSize, achPassword) != S_OK )
{
dwError = ERROR_INSUFFICIENT_BUFFER;
}
}
}
// Check to see if an error occurred along the way
if( dwError != NO_ERROR )
{
// Clear domain/username/password from memory
SecureZeroMemory( pszUserName, cbUserNameSize );
SecureZeroMemory( pszDomain, cbDomainSize );
SecureZeroMemory( pszPassword, cbPasswordSize );
if( dwError != ERROR_CANCELLED )
{
TCHAR achTitle[CREDUI_TITLE_MAX_LENGTH];
int nError = GetLastError();
LPTSTR pszMessageBuffer;
LoadString( ghInstance, IDS_CREDUI_TITLE, achTitle, CREDUI_TITLE_MAX_LENGTH );
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
nError,
MAKELANGID(LANG_NEUTRAL,
SUBLANG_DEFAULT),
(LPTSTR)&pszMessageBuffer,
0,
NULL );
MessageBox( ghStartDlg, pszMessageBuffer, achTitle, MB_OK );
LocalFree( pszMessageBuffer );
}
}
return dwError;
}
DWORD AttemptToGetAdminPrivilege( HANDLE* phToken, UINT nPromptId )
{
TCHAR achUserName[CREDUI_MAX_USERNAME_LENGTH + 1];
TCHAR achDomain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1];
TCHAR achPassword[CREDUI_MAX_PASSWORD_LENGTH + 1];
DWORD dwError = ERROR_CANCELLED;
if( phToken == NULL )
{
return ERROR_CANCELLED;
}
*phToken = NULL;
// Ask for administrator credentials
dwError = RetrieveCredentials( achUserName, sizeof(achUserName),
achDomain, sizeof(achDomain),
achPassword, sizeof(achPassword),
nPromptId );
if( dwError == NO_ERROR )
{
HANDLE hAdminToken;
// Attempt to logon
if( LogonUser(achUserName, achDomain, achPassword,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, &hAdminToken) )
{
// Attempt to impersonate logged on user
if( ImpersonateLoggedOnUser(hAdminToken) )
{
*phToken = hAdminToken;
}
else
{
// Impersonation failed
CloseHandle( hAdminToken );
dwError = ERROR_CANNOT_IMPERSONATE;
}
}
else
{
// Logon failed
dwError = ERROR_LOGON_FAILURE;
}
// Was logon successful?
if( dwError != NO_ERROR )
{
// Logon failed
TCHAR achTitle[CREDUI_TITLE_MAX_LENGTH];
LPTSTR pszMessageBuffer;
int nError;
LoadString( ghInstance, IDS_CREDUI_TITLE, achTitle, CREDUI_TITLE_MAX_LENGTH );
nError = GetLastError();
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
nError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&pszMessageBuffer,
0,
NULL );
MessageBox( ghStartDlg, pszMessageBuffer, achTitle, MB_OK );
LocalFree( pszMessageBuffer );
}
}
// Clear domain/username/password from memory
SecureZeroMemory( achUserName, sizeof(achUserName) );
SecureZeroMemory( achDomain, sizeof(achDomain) );
SecureZeroMemory( achPassword, sizeof(achPassword) );
return dwError;
}
HANDLE GetAdminPrivilege( UINT nPromptId )
{
HANDLE hToken = NULL;
BOOL fDone = FALSE;
do
{
DWORD dwError = AttemptToGetAdminPrivilege( &hToken, nPromptId );
if( dwError == NO_ERROR || dwError == ERROR_CANCELLED )
{
fDone = TRUE;
}
}
while( fDone == FALSE );
return hToken;
}
void ReleaseAdminPrivilege( HANDLE hToken )
{
if( hToken )
{
RevertToSelf();
CloseHandle( hToken );
}
}
STATIC void STARTAUDIOInit(HWND hDlg)
{
ghStartDlg = hDlg;
}
const static DWORD aStartHelpIds[] = { // Context Help IDs
IDC_GROUPBOX_START_1, NO_HELP,
IDC_ICON_START_1, NO_HELP,
IDC_TEXT_START_1, NO_HELP,
IDC_START_CHECK, NO_HELP,
IDC_TEXT_START_2, NO_HELP,
IDC_TEXT_START_3, NO_HELP,
IDC_TEXT_START_4, NO_HELP,
0, 0
};
BOOL CALLBACK StartDlg(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
NMHDR FAR *lpnm;
switch (uMsg)
{
case WM_NOTIFY:
{
lpnm = (NMHDR FAR *)lParam;
switch(lpnm->code)
{
case PSN_KILLACTIVE:
FORWARD_WM_COMMAND(hDlg, IDOK, 0, 0, SendMessage);
break;
case PSN_APPLY:
FORWARD_WM_COMMAND(hDlg, ID_APPLY, 0, 0, SendMessage);
break;
case PSN_SETACTIVE:
FORWARD_WM_COMMAND(hDlg, ID_INIT, 0, 0, SendMessage);
break;
case PSN_RESET:
FORWARD_WM_COMMAND(hDlg, IDCANCEL, 0, 0, SendMessage);
break;
}
}
break;
case WM_INITDIALOG:
{
STARTAUDIOInit(hDlg);
}
break;
case WM_DESTROY:
{
}
break;
case WM_CONTEXTMENU:
{
WinHelp ((HWND) wParam, NULL, HELP_CONTEXTMENU, (DWORD_PTR) (LPSTR) aStartHelpIds);
return TRUE;
}
break;
case WM_HELP:
{
LPHELPINFO lphi = (LPVOID) lParam;
WinHelp (lphi->hItemHandle, NULL, HELP_WM_HELP, (DWORD_PTR) (LPSTR) aStartHelpIds);
return TRUE;
}
break;
case WM_COMMAND:
{
HANDLE_WM_COMMAND(hDlg, wParam, lParam, DoStartCommand);
}
break;
default:
{
}
break;
}
return FALSE;
}
void ErrorStartMsgBox(HWND hDlg, UINT uTitle, UINT uMessage)
{
TCHAR szMsg[MAXSTR];
TCHAR szTitle[MAXSTR];
LoadString(ghInstance, uTitle, szTitle, sizeof(szTitle)/sizeof(TCHAR));
LoadString(ghInstance, uMessage, szMsg, sizeof(szMsg)/sizeof(TCHAR));
MessageBox(hDlg, szMsg,szTitle,MB_OK);
}
BOOL PASCAL DoStartCommand(HWND hDlg, int id, HWND hwndCtl, UINT codeNotify)
{
switch (id)
{
case IDOK:
{
if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_START_CHECK))
{
DWORD dwError;
dwError = SetAudiosrvAsAutoStart();
if( dwError == NO_ERROR )
{
MarkRegistryForReboot();
RebootSystem( hDlg, FALSE, TRUE, TRUE );
}
else
{
while( dwError == ERROR_ACCESS_DENIED )
{
HANDLE hToken = GetAdminPrivilege( IDS_CREDUI_PROMPT );
if( hToken )
{
dwError = SetAudiosrvAsAutoStart();
if( dwError == NO_ERROR )
{
MarkRegistryForReboot();
RebootSystem( hDlg, TRUE, TRUE, TRUE );
}
ReleaseAdminPrivilege( hToken );
}
else
{
// User cancelled credentials UI, so force CPL to remain open
gfRedisplayCPL = TRUE;
// Force break from while statement
dwError = ERROR_CANCELLED;
}
}
}
}
}
break;
}
return FALSE;
}
BOOL MarkRegistryForReboot(void)
{
HKEY hkTmp;
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE
,REGSTR_TEMP_REBOOT
,0
,NULL
,REG_OPTION_VOLATILE
,KEY_WRITE
,NULL
,&hkTmp
,NULL ) == ERROR_SUCCESS)
{
RegCloseKey(hkTmp);
return TRUE;
}
return FALSE;
}
BOOL AudioServiceStarted(void)
{
if (QueryPnpAudioDeviceAvailable())
{
DWORD dwRetCode = 0;
DWORD dwStartType = 0;
dwRetCode = QueryAudiosrvStartType(&dwStartType); // Check return nessesary?
if (SERVICE_AUTO_START == dwStartType)
{
return TRUE;
} else
{
return FALSE;
}
}
return TRUE;
}