Leaked source code of windows server 2003
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.

741 lines
20 KiB

  1. // cutil.cpp
  2. //
  3. // file to put misc utility classes implementation
  4. //
  5. #include "private.h"
  6. #include "sapilayr.h"
  7. #include "sphelper.h"
  8. #include "xstring.h"
  9. #include "cregkey.h"
  10. #include "ctflbui.h"
  11. #include "nui.h"
  12. const GUID c_guidProfileBogus = { /* 09ea4e4b-46ce-4469-b450-0de76a435bbb */
  13. 0x09ea4e4b,
  14. 0x46ce,
  15. 0x4469,
  16. {0xb4, 0x50, 0x0d, 0xe7, 0x6a, 0x43, 0x5b, 0xbb}
  17. };
  18. /* a5239e24-2bcf-4915-9c5c-fd50c0f69db2 */
  19. const CLSID CLSID_MSLBUI = {
  20. 0xa5239e24,
  21. 0x2bcf,
  22. 0x4915,
  23. {0x9c, 0x5c, 0xfd, 0x50, 0xc0, 0xf6, 0x9d, 0xb2}
  24. };
  25. // const GUID c_guidProfile0 = { /* 55122b58-15bb-11d4-bd48-00105a2799b5 */
  26. // 0x55122b58,
  27. // 0x15bb,
  28. // 0x11d4,
  29. // {0xbd, 0x48, 0x00, 0x10, 0x5a, 0x27, 0x99, 0xb5}
  30. // };
  31. // const GUID c_guidProfile1 = { /* 55122b59-15bb-11d4-bd48-00105a2799b5 */
  32. // 0x55122b59,
  33. // 0x15bb,
  34. // 0x11d4,
  35. // {0xbd, 0x48, 0x00, 0x10, 0x5a, 0x27, 0x99, 0xb5}
  36. // };
  37. // const GUID c_guidProfile2 = { /* 55122b5a-15bb-11d4-bd48-00105a2799b5 */
  38. // 0x55122b5a,
  39. // 0x15bb,
  40. // 0x11d4,
  41. // {0xbd, 0x48, 0x00, 0x10, 0x5a, 0x27, 0x99, 0xb5}
  42. // };
  43. #ifndef USE_SAPI_FOR_LANGDETECTION
  44. static const char c_szSpeechRecognizersKey[] = "Software\\Microsoft\\Speech\\Recognizers";
  45. static const char c_szSpeechRecognizersTokensKey[] = "Software\\Microsoft\\Speech\\Recognizers\\Tokens";
  46. static const char c_szDefault[] = "DefaultTokenId";
  47. static const char c_szAttribute[] = "Attributes";
  48. static const char c_szLanguage[] = "Language";
  49. static const char c_szUseSAPIForLang[] = "UseSAPIForLang";
  50. #endif
  51. static const char c_szProfileRemoved[] = "ProfileRemoved";
  52. static const char c_szProfileInitialized[] = "ProfileInitialized";
  53. _inline BOOL _IsCompatibleLangid(LANGID langidReq, LANGID langidCmp)
  54. {
  55. if (PRIMARYLANGID(langidReq) == LANG_CHINESE)
  56. {
  57. return langidReq == langidCmp;
  58. }
  59. else
  60. {
  61. return PRIMARYLANGID(langidReq) == PRIMARYLANGID(langidCmp);
  62. }
  63. }
  64. void _RegisterOrUnRegisterMslbui(BOOL fRegister)
  65. {
  66. // we just assume the dll is copied to system32
  67. TCHAR szMslbui[MAX_PATH];
  68. int cch = GetSystemDirectory(szMslbui, ARRAYSIZE(szMslbui));
  69. if (!cch)
  70. {
  71. return;
  72. }
  73. // GetSystemDirectory appends no '\' unless the system
  74. // directory is the root, such like "c:\"
  75. if (cch != 3)
  76. {
  77. StringCchCat(szMslbui, ARRAYSIZE(szMslbui), TEXT("\\"));
  78. }
  79. StringCchCat(szMslbui, ARRAYSIZE(szMslbui), TEXT("mslbui.dll"));
  80. if (fRegister)
  81. {
  82. // load mslbui.dll and register it
  83. TF_RegisterLangBarAddIn(CLSID_MSLBUI, AtoW(szMslbui), TF_RLBAI_CURRENTUSER | TF_RLBAI_ENABLE);
  84. }
  85. else
  86. {
  87. TF_UnregisterLangBarAddIn(CLSID_MSLBUI, TF_RLBAI_CURRENTUSER);
  88. }
  89. }
  90. //+---------------------------------------------------------------------------
  91. //
  92. // dtor
  93. //
  94. //
  95. //---------------------------------------------------------------------------+
  96. CLangProfileUtil::~CLangProfileUtil()
  97. {
  98. if (m_langidRecognizers.Count() > 0)
  99. m_langidRecognizers.Clear();
  100. }
  101. //+---------------------------------------------------------------------------
  102. //
  103. // _RegisterProfiles
  104. //
  105. // synopsis: a rough equivalent of RegisterTIP lib function, only different in
  106. // trying to cache the profile manager & the category manager
  107. //
  108. //---------------------------------------------------------------------------+
  109. HRESULT CLangProfileUtil::_RegisterAProfile(HINSTANCE hInst, REFCLSID rclsid, const REGTIPLANGPROFILE *plp)
  110. {
  111. Assert(plp);
  112. HRESULT hr = S_OK;
  113. // ensure profile manager
  114. if (!m_cpProfileMgr)
  115. {
  116. hr = TF_CreateInputProcessorProfiles(&m_cpProfileMgr);
  117. }
  118. // register the clsid
  119. if (S_OK == hr)
  120. {
  121. hr = m_cpProfileMgr->Register(rclsid);
  122. }
  123. if (S_OK == hr)
  124. {
  125. WCHAR wszFilePath[MAX_PATH];
  126. WCHAR *pv = &wszFilePath[0];
  127. wszFilePath[0] = L'\0';
  128. if (wcslen(plp->szIconFile))
  129. {
  130. char szFilePath[MAX_PATH];
  131. WCHAR *pvCur;
  132. ::GetModuleFileName(hInst, szFilePath, ARRAYSIZE(szFilePath));
  133. StringCchCopyW(wszFilePath, ARRAYSIZE(wszFilePath), AtoW(szFilePath));
  134. pv = pvCur = &wszFilePath[0];
  135. while (*pvCur)
  136. {
  137. if (*pvCur == L'\\')
  138. pv = pvCur + 1;
  139. pvCur++;
  140. }
  141. *pv = L'\0';
  142. }
  143. StringCchCatW(wszFilePath, ARRAYSIZE(wszFilePath), plp->szIconFile);
  144. hr = m_cpProfileMgr->AddLanguageProfile(rclsid,
  145. plp->langid, *plp->pguidProfile, plp->szProfile,
  146. wcslen(plp->szProfile), wszFilePath, wcslen(wszFilePath),
  147. plp->uIconIndex);
  148. }
  149. return hr;
  150. }
  151. //+---------------------------------------------------------------------------
  152. //
  153. // RegisterActiveProfiles(void)
  154. //
  155. // synopsis
  156. //
  157. //
  158. //
  159. //---------------------------------------------------------------------------+
  160. HRESULT CLangProfileUtil::RegisterActiveProfiles(void)
  161. {
  162. if (_fUserRemovedProfile())
  163. {
  164. // remove mslbui when not one speech profile is enabled
  165. if (!_IsAnyProfileEnabled())
  166. _RegisterOrUnRegisterMslbui(FALSE);
  167. return S_FALSE;
  168. }
  169. _SetUserInitializedProfile();
  170. BOOL fEnabled;
  171. HRESULT hr = _EnsureProfiles(TRUE, &fEnabled);
  172. // if the speech TIP profile is correctly registered,
  173. // then we're OK to register the persist UI (mslbui.dll)
  174. //
  175. if (S_OK == hr && fEnabled)
  176. _RegisterOrUnRegisterMslbui(TRUE);
  177. return hr;
  178. }
  179. //+---------------------------------------------------------------------------
  180. //
  181. // IsProfileAvailableForLang(LANGID langid, BOOL *pfAvailable)
  182. //
  183. // synopsis
  184. //
  185. //
  186. //
  187. //---------------------------------------------------------------------------+
  188. HRESULT CLangProfileUtil::IsProfileAvailableForLang(LANGID langid, BOOL *pfAvailable)
  189. {
  190. if (pfAvailable)
  191. {
  192. *pfAvailable = _IsDictationEnabledForLang(langid);
  193. return S_OK;
  194. }
  195. else
  196. return E_INVALIDARG;
  197. }
  198. //+---------------------------------------------------------------------------
  199. //
  200. // GetDisplayName(BSTR *pbstrName)
  201. //
  202. // synopsis
  203. //
  204. //
  205. //---------------------------------------------------------------------------+
  206. HRESULT CLangProfileUtil::GetDisplayName(BSTR *pbstrName)
  207. {
  208. HRESULT hr = E_INVALIDARG;
  209. if (pbstrName)
  210. {
  211. *pbstrName = SysAllocString(L"Register Active profiles for SPTIP");
  212. if (!*pbstrName)
  213. hr = E_OUTOFMEMORY;
  214. else
  215. hr = S_OK;
  216. }
  217. return hr;
  218. }
  219. HRESULT CLangProfileUtil::_EnsureProfiles(BOOL fRegister, BOOL *pfEnabled)
  220. {
  221. HRESULT hr = S_OK;
  222. if (pfEnabled)
  223. *pfEnabled = FALSE;
  224. if (fRegister)
  225. {
  226. m_langidRecognizers.Clear();
  227. }
  228. if (!m_cpProfileMgr || fRegister)
  229. {
  230. if (!m_cpProfileMgr)
  231. {
  232. hr = TF_CreateInputProcessorProfiles(&m_cpProfileMgr);
  233. }
  234. if (fRegister)
  235. {
  236. // if this is a first time initialization,
  237. // obtain the list of all languages
  238. //
  239. if (S_OK == hr)
  240. {
  241. LANGID *pLangIds;
  242. ULONG ulCount;
  243. // plangid will be assigned cotaskmemalloc'd memory
  244. //
  245. hr = m_cpProfileMgr->GetLanguageList(&pLangIds, &ulCount);
  246. if (S_OK == hr)
  247. {
  248. for (UINT i = 0; i < ulCount; i++)
  249. {
  250. // here we register profiles
  251. // if SR engines are available
  252. //
  253. BOOL fEnable = FALSE;
  254. if (_IsDictationEnabledForLang(pLangIds[i]))
  255. {
  256. fEnable = TRUE;
  257. if (pfEnabled)
  258. *pfEnabled = TRUE;
  259. }
  260. hr = m_cpProfileMgr->EnableLanguageProfile(
  261. CLSID_SapiLayr,
  262. pLangIds[i],
  263. c_guidProfileBogus,
  264. fEnable);
  265. } // for
  266. CoTaskMemFree(pLangIds);
  267. }
  268. }
  269. } // fRegister
  270. }
  271. return hr;
  272. }
  273. BOOL CLangProfileUtil::_IsAnyProfileEnabled()
  274. {
  275. HRESULT hr = S_OK;
  276. if (!m_cpProfileMgr)
  277. {
  278. hr = TF_CreateInputProcessorProfiles(&m_cpProfileMgr);
  279. }
  280. LANGID *pLangIds;
  281. ULONG ulCount;
  282. BOOL fEnable = FALSE;
  283. if (S_OK == hr)
  284. {
  285. //
  286. // plangid will be assigned cotaskmemalloc'd memory
  287. //
  288. hr = m_cpProfileMgr->GetLanguageList(&pLangIds, &ulCount);
  289. }
  290. if (S_OK == hr)
  291. {
  292. for (UINT i = 0; i < ulCount; i++)
  293. {
  294. hr = m_cpProfileMgr->IsEnabledLanguageProfile(CLSID_SapiLayr,
  295. pLangIds[i],
  296. c_guidProfileBogus,
  297. &fEnable);
  298. if (S_OK == hr && fEnable)
  299. break;
  300. }
  301. CoTaskMemFree(pLangIds);
  302. }
  303. return fEnable;
  304. }
  305. //+---------------------------------------------------------------------------
  306. //
  307. // _GetProfileLangID
  308. //
  309. // synopsis: handle language profiles
  310. //
  311. //---------------------------------------------------------------------------+
  312. HRESULT CLangProfileUtil::_GetProfileLangID(LANGID *plangid)
  313. {
  314. HRESULT hr = S_OK;
  315. Assert(plangid);
  316. hr = _EnsureProfiles(FALSE);
  317. if (hr == S_OK)
  318. {
  319. hr = m_cpProfileMgr->GetCurrentLanguage(plangid);
  320. }
  321. return hr;
  322. }
  323. //+---------------------------------------------------------------------------
  324. //
  325. // _DictationEnabled
  326. //
  327. // synopsis:
  328. //
  329. //---------------------------------------------------------------------------+
  330. BOOL CLangProfileUtil::_DictationEnabled(LANGID *plangidRequested)
  331. {
  332. BOOL fret = FALSE;
  333. LANGID langidReq = (LANGID)-1;
  334. HRESULT hr = _GetProfileLangID(&langidReq);
  335. if (S_OK == hr)
  336. {
  337. if (plangidRequested)
  338. *plangidRequested = langidReq;
  339. fret = _IsDictationActiveForLang(langidReq);
  340. }
  341. return fret;
  342. }
  343. //
  344. // _IsDictationActiveForLang
  345. //
  346. // synopsis: see if the default SR engine is capable for
  347. // the specified language
  348. //
  349. BOOL CLangProfileUtil::_IsDictationActiveForLang(LANGID langidReq)
  350. {
  351. return _IsDictationEnabledForLang(langidReq, TRUE);
  352. }
  353. BOOL CLangProfileUtil::_IsDictationEnabledForLang(LANGID langidReq, BOOL fUseDefault)
  354. {
  355. //
  356. // try reg first and if it's not compatible try SAPI
  357. //
  358. BOOL fEnabled = FALSE;
  359. if (_fUseSAPIForLanguageDetection() == FALSE
  360. && ERROR_SUCCESS ==
  361. _IsDictationEnabledForLangInReg(langidReq, fUseDefault, &fEnabled))
  362. {
  363. return fEnabled;
  364. }
  365. return _IsDictationEnabledForLangSAPI(langidReq, fUseDefault);
  366. }
  367. BOOL CLangProfileUtil::_IsDictationEnabledForLangSAPI(LANGID langidReq, BOOL fUseDefault)
  368. {
  369. BOOL fEnabled = FALSE;
  370. WCHAR * pszDefaultTokenId = NULL;
  371. HRESULT hr = S_OK;
  372. if (fUseDefault)
  373. {
  374. if (langidReq == m_langidDefault)
  375. return TRUE;
  376. SpGetDefaultTokenIdFromCategoryId(SPCAT_RECOGNIZERS, &pszDefaultTokenId);
  377. }
  378. CComPtr<IEnumSpObjectTokens> cpEnum;
  379. if (S_OK == hr)
  380. {
  381. char szLang[MAX_PATH];
  382. WCHAR wsz[MAX_PATH];
  383. StringCchPrintfA(szLang, ARRAYSIZE(szLang), "Language=%x", langidReq);
  384. MultiByteToWideChar(CP_ACP, NULL, szLang, -1, wsz, ARRAYSIZE(wsz));
  385. hr = SpEnumTokens(SPCAT_RECOGNIZERS, wsz, NULL, &cpEnum);
  386. }
  387. while (!fEnabled && S_OK == hr)
  388. {
  389. CComPtr<ISpObjectToken> cpToken;
  390. WCHAR * pszTokenId = NULL;
  391. hr = cpEnum->Next(1, &cpToken, NULL);
  392. if (S_OK == hr)
  393. {
  394. hr = cpToken->GetId(&pszTokenId);
  395. }
  396. if (S_OK == hr)
  397. {
  398. Assert(!fUseDefault || pszDefaultTokenId);
  399. if (!fUseDefault || wcscmp(pszDefaultTokenId, pszTokenId) == 0)
  400. fEnabled = TRUE;
  401. }
  402. if (pszTokenId)
  403. {
  404. CoTaskMemFree(pszTokenId);
  405. }
  406. }
  407. if (pszDefaultTokenId)
  408. {
  409. CoTaskMemFree(pszDefaultTokenId);
  410. }
  411. if (fUseDefault && fEnabled)
  412. {
  413. m_langidDefault = langidReq;
  414. }
  415. return fEnabled;
  416. }
  417. const TCHAR c_szDefaultDefaultToken[] = TEXT("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Recognizers\\Tokens\\MSASREnglish");
  418. const TCHAR c_szDefaultDefaultTokenJpn[] = TEXT("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Recognizers\\Tokens\\MSASRJapanese");
  419. const TCHAR c_szDefaultDefaultTokenChs[] = TEXT("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Recognizers\\Tokens\\MSASRChinese");
  420. LONG CLangProfileUtil::_IsDictationEnabledForLangInReg(LANGID langidReq, BOOL fUseDefault, BOOL *pfEnabled)
  421. {
  422. LONG lret = ERROR_SUCCESS;
  423. //
  424. // fUseDefault == TRUE, just see if the current default recognizer
  425. // matches with the requested langid
  426. //
  427. if (fUseDefault)
  428. {
  429. if( m_langidDefault == 0xFFFF)
  430. {
  431. char szRegkeyDefaultToken[MAX_PATH];
  432. CMyRegKey regkey;
  433. lret = regkey.Open(HKEY_CURRENT_USER,
  434. c_szSpeechRecognizersKey,
  435. KEY_READ);
  436. if (ERROR_SUCCESS == lret)
  437. {
  438. // first obtain the regkey to look at for default token
  439. lret = regkey.QueryValueCch(szRegkeyDefaultToken, c_szDefault, ARRAYSIZE(szRegkeyDefaultToken));
  440. regkey.Close();
  441. }
  442. else
  443. {
  444. if (PRIMARYLANGID(langidReq) == LANG_JAPANESE)
  445. {
  446. StringCchCopy(szRegkeyDefaultToken, ARRAYSIZE(szRegkeyDefaultToken), c_szDefaultDefaultTokenJpn);
  447. }
  448. else if (langidReq == 0x804) // CHS
  449. {
  450. StringCchCopy(szRegkeyDefaultToken, ARRAYSIZE(szRegkeyDefaultToken), c_szDefaultDefaultTokenChs);
  451. }
  452. else
  453. {
  454. StringCchCopy(szRegkeyDefaultToken, ARRAYSIZE(szRegkeyDefaultToken), c_szDefaultDefaultToken);
  455. }
  456. lret = ERROR_SUCCESS;
  457. }
  458. // then get the attribute / language
  459. if (ERROR_SUCCESS == lret)
  460. {
  461. char *psz = szRegkeyDefaultToken;
  462. //
  463. // eliminate "KKEY_LOCAL_MACHINE"
  464. //
  465. while(*psz && *psz != '\\')
  466. psz++;
  467. if (*psz == '\\')
  468. {
  469. psz++;
  470. //
  471. // open speech/recognizers/tokens key
  472. //
  473. lret = regkey.Open(HKEY_LOCAL_MACHINE, psz, KEY_READ);
  474. }
  475. else
  476. m_langidDefault = 0x0000;
  477. }
  478. if (ERROR_SUCCESS == lret)
  479. {
  480. m_langidDefault = _GetLangIdFromRecognizerToken(regkey.m_hKey);
  481. }
  482. }
  483. *pfEnabled = _IsCompatibleLangid(langidReq, m_langidDefault);
  484. return lret;
  485. }
  486. //
  487. // this is fUseDefault == FALSE case. We want to see
  488. // if any installed recognizer can satisfy the langid requested.
  489. //
  490. if (m_langidRecognizers.Count() == 0)
  491. {
  492. CMyRegKey regkey;
  493. char szRecognizerName[MAX_PATH];
  494. lret = regkey.Open(HKEY_LOCAL_MACHINE,
  495. c_szSpeechRecognizersTokensKey,
  496. KEY_READ);
  497. if(ERROR_SUCCESS == lret)
  498. {
  499. CMyRegKey regkeyReco;
  500. DWORD dwIndex = 0;
  501. while (ERROR_SUCCESS ==
  502. regkey.EnumKey(dwIndex, szRecognizerName, ARRAYSIZE(szRecognizerName)))
  503. {
  504. lret = regkeyReco.Open(regkey.m_hKey, szRecognizerName, KEY_READ);
  505. if (ERROR_SUCCESS == lret)
  506. {
  507. LANGID langid=_GetLangIdFromRecognizerToken(regkeyReco.m_hKey);
  508. if (langid)
  509. {
  510. LANGID *pl = m_langidRecognizers.Append(1);
  511. if (pl)
  512. *pl = langid;
  513. }
  514. regkeyReco.Close();
  515. }
  516. dwIndex++;
  517. }
  518. }
  519. }
  520. BOOL fEnabled = FALSE;
  521. for (int i = 0 ; i < m_langidRecognizers.Count(); i++)
  522. {
  523. LANGID *p= m_langidRecognizers.GetPtr(i);
  524. if (p)
  525. {
  526. if (_IsCompatibleLangid(langidReq, *p))
  527. {
  528. fEnabled = TRUE;
  529. break;
  530. }
  531. }
  532. }
  533. *pfEnabled = fEnabled;
  534. return lret;
  535. }
  536. LANGID CLangProfileUtil::_GetLangIdFromRecognizerToken(HKEY hkeyToken)
  537. {
  538. LANGID langid = 0;
  539. char szLang[MAX_PATH];
  540. CMyRegKey regkeyAttr;
  541. LONG lret = regkeyAttr.Open(hkeyToken, c_szAttribute, KEY_READ);
  542. if (ERROR_SUCCESS == lret)
  543. {
  544. lret = regkeyAttr.QueryValueCch(szLang, c_szLanguage, ARRAYSIZE(szLang));
  545. }
  546. if (ERROR_SUCCESS == lret)
  547. {
  548. char *psz = szLang;
  549. while(*psz && *psz != ';')
  550. {
  551. langid = langid << 4;
  552. if (*psz >= 'a' && *psz <= 'f')
  553. {
  554. *psz -= ('a' - 'A');
  555. }
  556. if (*psz >= 'A' && *psz <= 'F')
  557. {
  558. langid += *psz - 'A' + 10;
  559. }
  560. else if (*psz >= '0' && *psz <= '9')
  561. {
  562. langid += *psz - '0';
  563. }
  564. psz++;
  565. }
  566. }
  567. return langid;
  568. }
  569. BOOL CLangProfileUtil::_fUseSAPIForLanguageDetection(void)
  570. {
  571. if (m_uiUseSAPIForLangDetection == 0)
  572. {
  573. CMyRegKey regkey;
  574. if (ERROR_SUCCESS == regkey.Open(HKEY_LOCAL_MACHINE, c_szSapilayrKey, KEY_READ))
  575. {
  576. DWORD dw;
  577. if (ERROR_SUCCESS==regkey.QueryValue(dw, c_szUseSAPIForLang))
  578. {
  579. m_uiUseSAPIForLangDetection = dw;
  580. }
  581. }
  582. if (m_uiUseSAPIForLangDetection == 0)
  583. {
  584. m_uiUseSAPIForLangDetection = 1;
  585. }
  586. }
  587. return m_uiUseSAPIForLangDetection == 2 ? TRUE : FALSE;
  588. }
  589. BOOL CLangProfileUtil::_fUserRemovedProfile(void)
  590. {
  591. BOOL bret = FALSE;
  592. CMyRegKey regkey;
  593. if (ERROR_SUCCESS == regkey.Open(HKEY_CURRENT_USER, c_szSapilayrKey, KEY_READ))
  594. {
  595. DWORD dw;
  596. if (ERROR_SUCCESS==regkey.QueryValue(dw, c_szProfileRemoved))
  597. {
  598. bret = dw > 0 ? TRUE : FALSE;
  599. }
  600. }
  601. return bret;
  602. }
  603. BOOL CLangProfileUtil::_fUserInitializedProfile(void)
  604. {
  605. BOOL bret = FALSE;
  606. CMyRegKey regkey;
  607. if (ERROR_SUCCESS == regkey.Open(HKEY_CURRENT_USER, c_szSapilayrKey, KEY_READ))
  608. {
  609. DWORD dw;
  610. if (ERROR_SUCCESS==regkey.QueryValue(dw, c_szProfileInitialized))
  611. {
  612. bret = dw > 0 ? TRUE : FALSE;
  613. }
  614. }
  615. return bret;
  616. }
  617. BOOL CLangProfileUtil::_SetUserInitializedProfile(void)
  618. {
  619. CMyRegKey regkey;
  620. if (ERROR_SUCCESS == regkey.Create(HKEY_CURRENT_USER, c_szSapilayrKey))
  621. {
  622. DWORD dw = 0x0001;
  623. if (ERROR_SUCCESS==regkey.SetValue(dw, c_szProfileInitialized))
  624. {
  625. return TRUE;
  626. }
  627. }
  628. return FALSE;
  629. }