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.

368 lines
8.1 KiB

  1. /****************************************************************************
  2. *
  3. * spuser.cpp
  4. *
  5. * Dev applet to change the default speech user
  6. *
  7. * Owner: cthrash
  8. * Copyright (c) 1999 Microsoft Corporation All Rights Reserved.
  9. *
  10. *****************************************************************************/
  11. #include "stdafx.h"
  12. #include "spuser.h"
  13. /**********************************************************************
  14. * main *
  15. *------*
  16. *
  17. * Description:
  18. *
  19. * Main entry point.
  20. *
  21. * Return:
  22. *
  23. * S_OK, E_INVALIDARG
  24. *
  25. ************************************************************* cthrash */
  26. BOOL g_fVerbose = FALSE;
  27. int APIENTRY
  28. WinMain(
  29. HINSTANCE hInstance,
  30. HINSTANCE hPrevInstance,
  31. LPSTR lpCmdLine,
  32. int nCmdShow)
  33. {
  34. SearchArgument_t SearchArgument;
  35. SearchOption_t SearchOption = ParseCmdLine(lpCmdLine, &SearchArgument);
  36. HRESULT hr;
  37. if (SearchOption != eHelp)
  38. {
  39. hr = CoInitialize(NULL);
  40. if (SUCCEEDED(hr))
  41. {
  42. if (SearchOption == eNone)
  43. {
  44. hr = ShowDefaultUser();
  45. }
  46. else
  47. {
  48. hr = SwitchDefaultUser(SearchOption, &SearchArgument);
  49. }
  50. CoUninitialize();
  51. }
  52. }
  53. else
  54. {
  55. hr = Report("Usage:\tspuser [-v] {user-name}\n"
  56. "\tspuser [-v] -{local-id}\n"
  57. "\tspuser -?\n",
  58. E_INVALIDARG);
  59. }
  60. return (int)hr;
  61. }
  62. /**********************************************************************
  63. * ParseCmdLine *
  64. *--------------*
  65. *
  66. * Description:
  67. *
  68. * Parse the command line. Argument can be a name, or a locale
  69. * specification preceeded by a dash. Locale specifications can
  70. * be one of the stock names, or a a numeric LCID.
  71. *
  72. * Return:
  73. *
  74. * One of the SearchOption_t enumerated types
  75. *
  76. ************************************************************* cthrash */
  77. const struct NameValuePair aNameValuePair[] =
  78. {
  79. { "ameng", 1033 },
  80. { "enu", 1033 },
  81. { "japanese", 1041 },
  82. { "jpn", 1041 },
  83. { "chs", 2051 }
  84. };
  85. SearchOption_t
  86. ParseCmdLine(
  87. LPSTR pszCmdLine,
  88. SearchArgument_t *pSearchArgument)
  89. {
  90. SearchOption_t SearchOption;
  91. if (*pszCmdLine)
  92. {
  93. // Check first for the 'verbose' option.
  94. if (0 == strnicmp(pszCmdLine, "-v", 2))
  95. {
  96. g_fVerbose = TRUE;
  97. for (pszCmdLine += 2;isspace((unsigned)(unsigned char)*pszCmdLine); pszCmdLine++);
  98. }
  99. // A dash means the user specified a locale.
  100. if (*pszCmdLine == '-')
  101. {
  102. if (pszCmdLine[1] == '?')
  103. {
  104. SearchOption = eHelp;
  105. }
  106. else
  107. {
  108. LCID lcid = 0;
  109. pszCmdLine++;
  110. // first check the names we recognize
  111. for (int i=sizeof(aNameValuePair) / sizeof(aNameValuePair[0]); i--;)
  112. {
  113. if (0 == lstrcmpA(aNameValuePair[i].pszName, pszCmdLine))
  114. {
  115. lcid = aNameValuePair[i].lcid;
  116. break;
  117. }
  118. }
  119. // next see if it was specified numerically
  120. if (!lcid)
  121. {
  122. lcid = atoi(pszCmdLine);
  123. }
  124. pSearchArgument->lcid = lcid;
  125. SearchOption = pSearchArgument->lcid ? eSearchByLcid : eHelp;
  126. }
  127. }
  128. else
  129. {
  130. USES_CONVERSION;
  131. pSearchArgument->dstrName = A2W(pszCmdLine);
  132. SearchOption = eSearchByName;
  133. }
  134. }
  135. else
  136. {
  137. SearchOption = eNone;
  138. }
  139. return SearchOption;
  140. }
  141. /**********************************************************************
  142. * ShowDefaultUser *
  143. *-----------------*
  144. *
  145. * Description:
  146. *
  147. * Show the default user's name.
  148. *
  149. * Return:
  150. *
  151. * HRESULT
  152. *
  153. ************************************************************* cthrash */
  154. HRESULT
  155. ShowDefaultUser()
  156. {
  157. HRESULT hr;
  158. CComPtr<ISpObjectToken> cpToken;
  159. CSpDynamicString dstrName;
  160. hr = SpGetDefaultTokenFromCategoryId(SPCAT_SPEECHUSER, &cpToken);
  161. if (SUCCEEDED(hr))
  162. {
  163. hr = SpGetDescription(cpToken, &dstrName);
  164. }
  165. if (SUCCEEDED(hr))
  166. {
  167. ShowUserName(dstrName);
  168. }
  169. return hr;
  170. }
  171. /**********************************************************************
  172. * SwitchDefaultUser *
  173. *-------------------*
  174. *
  175. * Description:
  176. *
  177. * Parse the command line. Argument can be a name, or a locale
  178. * specification preceeded by a dash. Locale specifications can
  179. * be one of the stock names, or a a numeric LCID.
  180. *
  181. * Return:
  182. *
  183. * One of the SearchOption_t enumerated types
  184. *
  185. ************************************************************* cthrash */
  186. HRESULT
  187. SwitchDefaultUser(
  188. SearchOption_t SearchOption,
  189. SearchArgument_t * pSearchArgument)
  190. {
  191. HRESULT hr;
  192. CComPtr<IEnumSpObjectTokens> cpEnum;
  193. ULONG celtFetched;
  194. BOOL fFoundMatch = 0;
  195. CSpDynamicString dstrName;
  196. hr = SpEnumTokens(SPCAT_SPEECHUSER, NULL, NULL, &cpEnum);
  197. if (SUCCEEDED(hr))
  198. {
  199. hr = cpEnum->GetCount(&celtFetched);
  200. }
  201. while (!fFoundMatch && SUCCEEDED(hr))
  202. {
  203. ISpRegistryObjectToken *pRegToken = 0;
  204. CSpDynamicString dstrID;
  205. ISpUser * pSpUser = 0;
  206. hr = cpEnum->Next(1, (ISpObjectToken**)&pRegToken, &celtFetched);
  207. if (hr != S_OK)
  208. {
  209. break;
  210. }
  211. hr = pRegToken->GetId(&dstrID);
  212. if (SUCCEEDED(hr))
  213. {
  214. hr = pRegToken->CreateInstance(NULL, CLSCTX_INPROC_SERVER, IID_ISpUser, (void**)&pSpUser);
  215. }
  216. if (SUCCEEDED(hr))
  217. {
  218. BOOL fSwitch;
  219. CSpDynamicString dstrNameT;
  220. hr = SpGetDescription(pRegToken, &dstrNameT);
  221. switch (SearchOption)
  222. {
  223. case eSearchByName:
  224. {
  225. fSwitch = SUCCEEDED(hr) && (0 == wcsicmp(pSearchArgument->dstrName, dstrNameT));
  226. }
  227. break;
  228. case eSearchByLcid:
  229. {
  230. SPUSERINFO UserInfo;
  231. hr = pSpUser->GetInfo(&UserInfo);
  232. fSwitch = SUCCEEDED(hr) && (UserInfo.cLanguages > 0) && (UserInfo.aLanguage[0] == pSearchArgument->lcid);
  233. }
  234. break;
  235. default:
  236. fSwitch = FALSE; // in case somebody adds an enum
  237. break;
  238. }
  239. if (fSwitch)
  240. {
  241. dstrName = dstrNameT;
  242. if (SUCCEEDED(hr))
  243. {
  244. hr = cpResMgr->SetDefault(pRegToken);
  245. }
  246. if (SUCCEEDED(hr))
  247. {
  248. fFoundMatch = 1;
  249. }
  250. }
  251. }
  252. if (pSpUser)
  253. {
  254. pSpUser->Release();
  255. }
  256. if (pRegToken)
  257. {
  258. pRegToken->Release();
  259. }
  260. }
  261. hr = SUCCEEDED(hr) ? (fFoundMatch ? S_OK : E_INVALIDARG) : hr;
  262. if (FAILED(hr))
  263. {
  264. Report("Couldn't find an appropriate user", E_INVALIDARG);
  265. }
  266. else if (g_fVerbose)
  267. {
  268. ShowUserName(dstrName);
  269. }
  270. return hr;
  271. }
  272. void
  273. ShowUserName(WCHAR * pszName)
  274. {
  275. USES_CONVERSION;
  276. CSpDynamicString dstrOutput;
  277. dstrOutput = "Current default user: ";
  278. dstrOutput.Append(pszName);
  279. g_fVerbose = TRUE;
  280. Report(W2T(dstrOutput), S_FALSE);
  281. }
  282. /**********************************************************************
  283. * Report *
  284. *--------*
  285. *
  286. * Description:
  287. *
  288. * Show a message box, possibly indicating an error.
  289. *
  290. * Return:
  291. *
  292. * The HRESULT passed in is returned, for the convenience of
  293. * the caller.
  294. *
  295. ************************************************************* cthrash */
  296. HRESULT Report(char * lpMsg, HRESULT hr)
  297. {
  298. if (hr != S_OK || g_fVerbose)
  299. {
  300. const UINT uType = MB_OK | (FAILED(hr) ? MB_ICONERROR : MB_ICONINFORMATION);
  301. MessageBox(HWND_DESKTOP, lpMsg, "spuser.exe", uType);
  302. }
  303. return hr;
  304. }