369 lines
8.1 KiB
C++
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;
|
|
}
|
|
|