windows-nt/Source/XPSP1/NT/enduser/speech/tools/spuser/spuser.cpp
2020-09-26 16:20:57 +08:00

369 lines
8.1 KiB
C++

/****************************************************************************
*
* spuser.cpp
*
* Dev applet to change the default speech user
*
* Owner: cthrash
* Copyright (c) 1999 Microsoft Corporation All Rights Reserved.
*
*****************************************************************************/
#include "stdafx.h"
#include "spuser.h"
/**********************************************************************
* main *
*------*
*
* Description:
*
* Main entry point.
*
* Return:
*
* S_OK, E_INVALIDARG
*
************************************************************* cthrash */
BOOL g_fVerbose = FALSE;
int APIENTRY
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
SearchArgument_t SearchArgument;
SearchOption_t SearchOption = ParseCmdLine(lpCmdLine, &SearchArgument);
HRESULT hr;
if (SearchOption != eHelp)
{
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
if (SearchOption == eNone)
{
hr = ShowDefaultUser();
}
else
{
hr = SwitchDefaultUser(SearchOption, &SearchArgument);
}
CoUninitialize();
}
}
else
{
hr = Report("Usage:\tspuser [-v] {user-name}\n"
"\tspuser [-v] -{local-id}\n"
"\tspuser -?\n",
E_INVALIDARG);
}
return (int)hr;
}
/**********************************************************************
* ParseCmdLine *
*--------------*
*
* Description:
*
* Parse the command line. Argument can be a name, or a locale
* specification preceeded by a dash. Locale specifications can
* be one of the stock names, or a a numeric LCID.
*
* Return:
*
* One of the SearchOption_t enumerated types
*
************************************************************* cthrash */
const struct NameValuePair aNameValuePair[] =
{
{ "ameng", 1033 },
{ "enu", 1033 },
{ "japanese", 1041 },
{ "jpn", 1041 },
{ "chs", 2051 }
};
SearchOption_t
ParseCmdLine(
LPSTR pszCmdLine,
SearchArgument_t *pSearchArgument)
{
SearchOption_t SearchOption;
if (*pszCmdLine)
{
// Check first for the 'verbose' option.
if (0 == strnicmp(pszCmdLine, "-v", 2))
{
g_fVerbose = TRUE;
for (pszCmdLine += 2;isspace((unsigned)(unsigned char)*pszCmdLine); pszCmdLine++);
}
// A dash means the user specified a locale.
if (*pszCmdLine == '-')
{
if (pszCmdLine[1] == '?')
{
SearchOption = eHelp;
}
else
{
LCID lcid = 0;
pszCmdLine++;
// first check the names we recognize
for (int i=sizeof(aNameValuePair) / sizeof(aNameValuePair[0]); i--;)
{
if (0 == lstrcmpA(aNameValuePair[i].pszName, pszCmdLine))
{
lcid = aNameValuePair[i].lcid;
break;
}
}
// next see if it was specified numerically
if (!lcid)
{
lcid = atoi(pszCmdLine);
}
pSearchArgument->lcid = lcid;
SearchOption = pSearchArgument->lcid ? eSearchByLcid : eHelp;
}
}
else
{
USES_CONVERSION;
pSearchArgument->dstrName = A2W(pszCmdLine);
SearchOption = eSearchByName;
}
}
else
{
SearchOption = eNone;
}
return SearchOption;
}
/**********************************************************************
* ShowDefaultUser *
*-----------------*
*
* Description:
*
* Show the default user's name.
*
* Return:
*
* HRESULT
*
************************************************************* cthrash */
HRESULT
ShowDefaultUser()
{
HRESULT hr;
CComPtr<ISpObjectToken> cpToken;
CSpDynamicString dstrName;
hr = SpGetDefaultTokenFromCategoryId(SPCAT_SPEECHUSER, &cpToken);
if (SUCCEEDED(hr))
{
hr = SpGetDescription(cpToken, &dstrName);
}
if (SUCCEEDED(hr))
{
ShowUserName(dstrName);
}
return hr;
}
/**********************************************************************
* SwitchDefaultUser *
*-------------------*
*
* Description:
*
* Parse the command line. Argument can be a name, or a locale
* specification preceeded by a dash. Locale specifications can
* be one of the stock names, or a a numeric LCID.
*
* Return:
*
* One of the SearchOption_t enumerated types
*
************************************************************* cthrash */
HRESULT
SwitchDefaultUser(
SearchOption_t SearchOption,
SearchArgument_t * pSearchArgument)
{
HRESULT hr;
CComPtr<IEnumSpObjectTokens> cpEnum;
ULONG celtFetched;
BOOL fFoundMatch = 0;
CSpDynamicString dstrName;
hr = SpEnumTokens(SPCAT_SPEECHUSER, NULL, NULL, &cpEnum);
if (SUCCEEDED(hr))
{
hr = cpEnum->GetCount(&celtFetched);
}
while (!fFoundMatch && SUCCEEDED(hr))
{
ISpRegistryObjectToken *pRegToken = 0;
CSpDynamicString dstrID;
ISpUser * pSpUser = 0;
hr = cpEnum->Next(1, (ISpObjectToken**)&pRegToken, &celtFetched);
if (hr != S_OK)
{
break;
}
hr = pRegToken->GetId(&dstrID);
if (SUCCEEDED(hr))
{
hr = pRegToken->CreateInstance(NULL, CLSCTX_INPROC_SERVER, IID_ISpUser, (void**)&pSpUser);
}
if (SUCCEEDED(hr))
{
BOOL fSwitch;
CSpDynamicString dstrNameT;
hr = SpGetDescription(pRegToken, &dstrNameT);
switch (SearchOption)
{
case eSearchByName:
{
fSwitch = SUCCEEDED(hr) && (0 == wcsicmp(pSearchArgument->dstrName, dstrNameT));
}
break;
case eSearchByLcid:
{
SPUSERINFO UserInfo;
hr = pSpUser->GetInfo(&UserInfo);
fSwitch = SUCCEEDED(hr) && (UserInfo.cLanguages > 0) && (UserInfo.aLanguage[0] == pSearchArgument->lcid);
}
break;
default:
fSwitch = FALSE; // in case somebody adds an enum
break;
}
if (fSwitch)
{
dstrName = dstrNameT;
if (SUCCEEDED(hr))
{
hr = cpResMgr->SetDefault(pRegToken);
}
if (SUCCEEDED(hr))
{
fFoundMatch = 1;
}
}
}
if (pSpUser)
{
pSpUser->Release();
}
if (pRegToken)
{
pRegToken->Release();
}
}
hr = SUCCEEDED(hr) ? (fFoundMatch ? S_OK : E_INVALIDARG) : hr;
if (FAILED(hr))
{
Report("Couldn't find an appropriate user", E_INVALIDARG);
}
else if (g_fVerbose)
{
ShowUserName(dstrName);
}
return hr;
}
void
ShowUserName(WCHAR * pszName)
{
USES_CONVERSION;
CSpDynamicString dstrOutput;
dstrOutput = "Current default user: ";
dstrOutput.Append(pszName);
g_fVerbose = TRUE;
Report(W2T(dstrOutput), S_FALSE);
}
/**********************************************************************
* Report *
*--------*
*
* Description:
*
* Show a message box, possibly indicating an error.
*
* Return:
*
* The HRESULT passed in is returned, for the convenience of
* the caller.
*
************************************************************* cthrash */
HRESULT Report(char * lpMsg, HRESULT hr)
{
if (hr != S_OK || g_fVerbose)
{
const UINT uType = MB_OK | (FAILED(hr) ? MB_ICONERROR : MB_ICONINFORMATION);
MessageBox(HWND_DESKTOP, lpMsg, "spuser.exe", uType);
}
return hr;
}