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.

384 lines
8.5 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<ISpResourceManager> cpResMgr;
  159. CComPtr<ISpObjectToken> cpToken;
  160. CSpDynamicString dstrName;
  161. hr = cpResMgr.CoCreateInstance(CLSID_SpResourceManager);
  162. if (SUCCEEDED(hr))
  163. {
  164. hr = cpResMgr->GetObjectToken(SPCAT_SPEECHUSER, &cpToken);
  165. }
  166. if (SUCCEEDED(hr))
  167. {
  168. hr = SpGetDescription(cpToken, &dstrName);
  169. }
  170. if (SUCCEEDED(hr))
  171. {
  172. ShowUserName(dstrName);
  173. }
  174. return hr;
  175. }
  176. /**********************************************************************
  177. * SwitchDefaultUser *
  178. *-------------------*
  179. *
  180. * Description:
  181. *
  182. * Parse the command line. Argument can be a name, or a locale
  183. * specification preceeded by a dash. Locale specifications can
  184. * be one of the stock names, or a a numeric LCID.
  185. *
  186. * Return:
  187. *
  188. * One of the SearchOption_t enumerated types
  189. *
  190. ************************************************************* cthrash */
  191. HRESULT
  192. SwitchDefaultUser(
  193. SearchOption_t SearchOption,
  194. SearchArgument_t * pSearchArgument)
  195. {
  196. HRESULT hr;
  197. CComPtr<ISpResourceManager> cpResMgr;
  198. CComPtr<IEnumSpObjectTokens> cpEnum;
  199. ULONG celtFetched;
  200. BOOL fFoundMatch = 0;
  201. CSpDynamicString dstrName;
  202. hr = cpResMgr.CoCreateInstance(CLSID_SpResourceManager);
  203. if (SUCCEEDED(hr))
  204. {
  205. hr = cpResMgr->EnumTokens(SPCAT_SPEECHUSER, NULL, NULL, &cpEnum);
  206. }
  207. if(hr == S_FALSE)
  208. {
  209. hr = SPERR_NOT_FOUND;
  210. }
  211. if (SUCCEEDED(hr))
  212. {
  213. hr = cpEnum->GetCount(&celtFetched);
  214. }
  215. while (!fFoundMatch && SUCCEEDED(hr))
  216. {
  217. ISpRegistryObjectToken *pRegToken = 0;
  218. CSpDynamicString dstrID;
  219. ISpUser * pSpUser = 0;
  220. hr = cpEnum->Next(1, (ISpObjectToken**)&pRegToken, &celtFetched);
  221. if (hr != S_OK)
  222. {
  223. break;
  224. }
  225. hr = pRegToken->GetID(&dstrID);
  226. if (SUCCEEDED(hr))
  227. {
  228. hr = pRegToken->CreateInstance(NULL, CLSCTX_INPROC_SERVER, IID_ISpUser, (void**)&pSpUser);
  229. }
  230. if (SUCCEEDED(hr))
  231. {
  232. BOOL fSwitch;
  233. CSpDynamicString dstrNameT;
  234. hr = SpGetDescription(pRegToken, &dstrNameT);
  235. switch (SearchOption)
  236. {
  237. case eSearchByName:
  238. {
  239. fSwitch = SUCCEEDED(hr) && (0 == wcsicmp(pSearchArgument->dstrName, dstrNameT));
  240. }
  241. break;
  242. case eSearchByLcid:
  243. {
  244. SPUSERINFO UserInfo;
  245. hr = pSpUser->GetInfo(&UserInfo);
  246. fSwitch = SUCCEEDED(hr) && (UserInfo.cLanguages > 0) && (UserInfo.aLanguage[0] == pSearchArgument->lcid);
  247. }
  248. break;
  249. default:
  250. fSwitch = FALSE; // in case somebody adds an enum
  251. break;
  252. }
  253. if (fSwitch)
  254. {
  255. dstrName = dstrNameT;
  256. if (SUCCEEDED(hr))
  257. {
  258. hr = cpResMgr->SetDefault(pRegToken);
  259. }
  260. if (SUCCEEDED(hr))
  261. {
  262. fFoundMatch = 1;
  263. }
  264. }
  265. }
  266. if (pSpUser)
  267. {
  268. pSpUser->Release();
  269. }
  270. if (pRegToken)
  271. {
  272. pRegToken->Release();
  273. }
  274. }
  275. hr = SUCCEEDED(hr) ? (fFoundMatch ? S_OK : E_INVALIDARG) : hr;
  276. if (FAILED(hr))
  277. {
  278. Report("Couldn't find an appropriate user", E_INVALIDARG);
  279. }
  280. else if (g_fVerbose)
  281. {
  282. ShowUserName(dstrName);
  283. }
  284. return hr;
  285. }
  286. void
  287. ShowUserName(WCHAR * pszName)
  288. {
  289. USES_CONVERSION;
  290. CSpDynamicString dstrOutput;
  291. dstrOutput = "Current default user: ";
  292. dstrOutput.Append(pszName);
  293. g_fVerbose = TRUE;
  294. Report(W2T(dstrOutput), S_FALSE);
  295. }
  296. /**********************************************************************
  297. * Report *
  298. *--------*
  299. *
  300. * Description:
  301. *
  302. * Show a message box, possibly indicating an error.
  303. *
  304. * Return:
  305. *
  306. * The HRESULT passed in is returned, for the convenience of
  307. * the caller.
  308. *
  309. ************************************************************* cthrash */
  310. HRESULT Report(char * lpMsg, HRESULT hr)
  311. {
  312. if (hr != S_OK || g_fVerbose)
  313. {
  314. const UINT uType = MB_OK | (FAILED(hr) ? MB_ICONERROR : MB_ICONINFORMATION);
  315. MessageBox(HWND_DESKTOP, lpMsg, "spuser.exe", uType);
  316. }
  317. return hr;
  318. }