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.

332 lines
7.5 KiB

  1. /****************************************************************************
  2. *
  3. * resetusr.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 "resetusr.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. char * pszUserName;
  35. BOOL fReset = ParseCmdLine(lpCmdLine, &pszUserName);
  36. HRESULT hr;
  37. if (fReset)
  38. {
  39. hr = CoInitialize(NULL);
  40. if (SUCCEEDED(hr))
  41. {
  42. hr = ResetUser(pszUserName);
  43. CoUninitialize();
  44. }
  45. }
  46. else
  47. {
  48. hr = Report("Usage:\tresetusr [-v] [user-name]\n"
  49. "\tresetusr [-v] -default\n"
  50. "\tresetusr -?\n",
  51. E_INVALIDARG);
  52. }
  53. return (int)hr;
  54. }
  55. /**********************************************************************
  56. * ParseCmdLine *
  57. *--------------*
  58. *
  59. * Description:
  60. *
  61. * Parse the command line. Argument can be a name, or the string
  62. * -default.
  63. *
  64. * Return:
  65. *
  66. * TRUE -- delete the user specified,
  67. * FALSE -- show usage info
  68. *
  69. ************************************************************* cthrash */
  70. BOOL
  71. ParseCmdLine(
  72. char * pszCmdLine, // [in] Command line arguments
  73. char ** ppszUserName) // [out]
  74. {
  75. BOOL fReset = FALSE;
  76. while (*pszCmdLine)
  77. {
  78. if (0 == strnicmp(pszCmdLine, "-v", 2))
  79. {
  80. g_fVerbose = TRUE;
  81. }
  82. else
  83. {
  84. if (0 == strnicmp(pszCmdLine, "-default", 8))
  85. {
  86. *ppszUserName = NULL;
  87. fReset = TRUE;
  88. }
  89. else if (0 != strnicmp(pszCmdLine, "-?", 2))
  90. {
  91. *ppszUserName = pszCmdLine;
  92. fReset = TRUE;
  93. }
  94. else
  95. {
  96. fReset = FALSE;
  97. }
  98. break;
  99. }
  100. for (pszCmdLine += 2;isspace((unsigned)(unsigned char)*pszCmdLine); pszCmdLine++);
  101. }
  102. return fReset;
  103. }
  104. /*****************************************************************************
  105. * ResetUser *
  106. *-----------*
  107. *
  108. * Description: Reset a user's AM state.
  109. *
  110. * Return: HRESULT
  111. *
  112. ***************************************************************** cthrash ***/
  113. HRESULT
  114. ResetUser(
  115. char * pszName) // [in] Name; NULL implies the default user
  116. {
  117. HRESULT hr, hrReturn;
  118. CComPtr<ISpObjectToken> cpEngineToken;
  119. CComPtr<ISpObjectToken> cpUserToken;
  120. CComPtr<ISpDataKey> cpDataKey;
  121. CComPtr<ISpDataKey> cpSubDataKey;
  122. CSpDynamicString dstrEngineGUID;
  123. CSpDynamicString dstrReport;
  124. // Should we provide a mechanism to pick engine? Currently we pick the default.
  125. hr = SpGetDefaultTokenFromCategoryId(SPCAT_RECOGNIZERS, &cpEngineToken);
  126. if (SUCCEEDED(hr))
  127. {
  128. hr = cpEngineToken->GetId(&dstrEngineGUID);
  129. }
  130. if (SUCCEEDED(hr))
  131. {
  132. const WCHAR * pch = wcsrchr(dstrEngineGUID, L'\\');
  133. if (pch)
  134. {
  135. pch++;
  136. memmove((WCHAR *)dstrEngineGUID, pch, sizeof(WCHAR) * (1 + wcslen(pch)));
  137. }
  138. }
  139. // Get the user token;
  140. if (!pszName)
  141. {
  142. if (SUCCEEDED(hr))
  143. {
  144. hr = SpGetDefaultTokenFromCategoryId(SPCAT_SPEECHUSER, &cpUserToken);
  145. }
  146. }
  147. else
  148. {
  149. BOOL fFoundMatch = FALSE;
  150. CComPtr<IEnumSpObjectTokens> cpEnum;
  151. ULONG celtFetched;
  152. CSpDynamicString dstrName = pszName;
  153. if (SUCCEEDED(hr))
  154. {
  155. hr = SpEnumTokens(SPCAT_SPEECHUSER, NULL, NULL, &cpEnum);
  156. }
  157. if(hr == S_FALSE)
  158. {
  159. hr = SPERR_NOT_FOUND;
  160. }
  161. if (SUCCEEDED(hr))
  162. {
  163. hr = cpEnum->GetCount(&celtFetched);
  164. }
  165. while (!fFoundMatch && SUCCEEDED(hr))
  166. {
  167. ISpRegistryObjectToken *pRegToken = 0;
  168. hr = cpEnum->Next(1, (ISpObjectToken**)&pRegToken, &celtFetched);
  169. if (hr != S_OK)
  170. {
  171. break;
  172. }
  173. if (SUCCEEDED(hr))
  174. {
  175. CSpDynamicString dstrNameT;
  176. hr = SpGetDescription(pRegToken, &dstrNameT);
  177. fFoundMatch = 0 == wcsicmp(dstrName, dstrNameT);
  178. }
  179. if (fFoundMatch)
  180. {
  181. cpUserToken = pRegToken;
  182. }
  183. if (pRegToken)
  184. {
  185. pRegToken->Release();
  186. }
  187. }
  188. }
  189. hrReturn = hr;
  190. if (SUCCEEDED(hr))
  191. {
  192. hr = cpUserToken->OpenKey(dstrEngineGUID, &cpDataKey);
  193. hrReturn = (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) ? S_OK : hr;
  194. }
  195. if (SUCCEEDED(hr))
  196. {
  197. hr = cpDataKey->OpenKey(L"files", &cpSubDataKey);
  198. hrReturn = (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) ? S_OK : hr;
  199. }
  200. // Nuke all the files first.
  201. if (SUCCEEDED(hr))
  202. {
  203. ULONG iKey;
  204. for (iKey = 0; hr == S_OK; iKey++)
  205. {
  206. CSpDynamicString dstrFileType;
  207. CSpDynamicString dstrFilePath;
  208. hr = cpSubDataKey->EnumValues(iKey, &dstrFileType);
  209. if (SUCCEEDED(hr))
  210. {
  211. hr = cpSubDataKey->GetStringValue(dstrFileType, &dstrFilePath);
  212. }
  213. if (SUCCEEDED(hr))
  214. {
  215. USES_CONVERSION;
  216. hr = DeleteFile(W2T(dstrFilePath)) ? S_OK : HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  217. if (g_fVerbose)
  218. {
  219. dstrReport.Append(L"Deleting ");
  220. dstrReport.Append2(dstrFilePath, SUCCEEDED(hr) ? L" -- Success\n" : L" -- Fail\n");
  221. }
  222. }
  223. }
  224. hrReturn = hr = (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr) ? S_OK : hr;
  225. }
  226. // Nuke the files key
  227. if (SUCCEEDED(hr))
  228. {
  229. cpSubDataKey.Release();
  230. hr = cpDataKey->DeleteKey(L"files");
  231. if (g_fVerbose)
  232. {
  233. CSpDynamicString dstrID;
  234. cpUserToken->GetID(&dstrID);
  235. dstrReport.Append2(L"Deleting Key ", dstrID);
  236. dstrReport.Append2(L"\\", dstrEngineGUID);
  237. dstrReport.Append2(L"\\Files", SUCCEEDED(hr) ? L" -- Success\n" : L" -- Fail\n");
  238. }
  239. hrReturn = hr;
  240. }
  241. if (FAILED(hrReturn))
  242. {
  243. //Report("DataCouldn't find an appropriate user", E_INVALIDARG);
  244. }
  245. else if (g_fVerbose && dstrReport)
  246. {
  247. USES_CONVERSION;
  248. Report(W2A(dstrReport), hr);
  249. }
  250. return hrReturn;
  251. }
  252. /**********************************************************************
  253. * Report *
  254. *--------*
  255. *
  256. * Description:
  257. *
  258. * Show a message box, possibly indicating an error.
  259. *
  260. * Return:
  261. *
  262. * The HRESULT passed in is returned, for the convenience of
  263. * the caller.
  264. *
  265. ************************************************************* cthrash */
  266. HRESULT Report(char * lpMsg, HRESULT hr)
  267. {
  268. if (hr != S_OK || g_fVerbose)
  269. {
  270. const UINT uType = MB_OK | (FAILED(hr) ? MB_ICONERROR : MB_ICONINFORMATION);
  271. MessageBox(HWND_DESKTOP, lpMsg, "resetusr.exe", uType);
  272. }
  273. return hr;
  274. }