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.

693 lines
20 KiB

  1. //*********************************************************************
  2. //* Microsoft Windows **
  3. //* Copyright(c) Microsoft Corp., 1994 **
  4. //*********************************************************************
  5. //
  6. // UTIL.C - common utility functions
  7. //
  8. // HISTORY:
  9. //
  10. // 12/21/94 jeremys Created.
  11. // 96/03/24 markdu Replaced memset with ZeroMemory for consistency.
  12. // 96/04/06 markdu NASH BUG 15653 Use exported autodial API.
  13. // Need to keep a modified SetInternetConnectoid to set the
  14. // MSN backup connectoid.
  15. // 96/05/14 markdu NASH BUG 21706 Removed BigFont functions.
  16. //
  17. #include "pre.h"
  18. // function prototypes
  19. VOID _cdecl FormatErrorMessage(LPTSTR pszMsg,DWORD cbMsg,LPTSTR pszFmt,LPTSTR szArg);
  20. VOID Win95JMoveDlgItem( HWND hwndParent, HWND hwndItem, int iUp );
  21. // Static data
  22. static const TCHAR szRegValICWCompleted[] = TEXT("Completed");
  23. #define MAX_STRINGS 5
  24. #define OEM_CONFIG_INS_FILENAME TEXT("icw\\OEMCNFG.INS")
  25. #define OEM_CONFIG_REGKEY TEXT("SOFTWARE\\Microsoft\\Internet Connection Wizard\\INS processing")
  26. #define OEM_CONFIG_REGVAL_FAILED TEXT("Process failed")
  27. #define OEM_CONFIG_REGVAL_ISPNAME TEXT("ISP name")
  28. #define OEM_CONFIG_REGVAL_SUPPORTNUM TEXT("Support number")
  29. #define OEM_CONFIG_INS_SECTION TEXT("Entry")
  30. #define OEM_CONFIG_INS_ISPNAME TEXT("Entry_Name")
  31. #define OEM_CONFIG_INS_SUPPORTNUM TEXT("Support_Number")
  32. int iSzTable=0;
  33. TCHAR szStrTable[MAX_STRINGS][512];
  34. //+----------------------------------------------------------------------------
  35. // NAME: GetSz
  36. //
  37. // Load strings from resources
  38. //
  39. // Created 1/28/96, Chris Kauffman
  40. //+----------------------------------------------------------------------------
  41. LPTSTR GetSz(WORD wszID)
  42. {
  43. LPTSTR psz = szStrTable[iSzTable];
  44. iSzTable++;
  45. if (iSzTable >= MAX_STRINGS)
  46. iSzTable = 0;
  47. if (!LoadString(g_hInstance, wszID, psz, 512))
  48. {
  49. *psz = 0;
  50. }
  51. return (psz);
  52. }
  53. /*******************************************************************
  54. NAME: MsgBox
  55. SYNOPSIS: Displays a message box with the specified string ID
  56. ********************************************************************/
  57. int MsgBox(HWND hWnd,UINT nMsgID,UINT uIcon,UINT uButtons)
  58. {
  59. return (MessageBox(hWnd,
  60. GetSz((USHORT)nMsgID),
  61. GetSz(IDS_APPNAME),
  62. uIcon | uButtons));
  63. }
  64. /*******************************************************************
  65. NAME: MsgBoxSz
  66. SYNOPSIS: Displays a message box with the specified text
  67. ********************************************************************/
  68. int MsgBoxSz(HWND hWnd,LPTSTR szText,UINT uIcon,UINT uButtons)
  69. {
  70. return (MessageBox(hWnd,szText,GetSz(IDS_APPNAME),uIcon | uButtons));
  71. }
  72. void OlsFinish()
  73. {
  74. QuickCompleteSignup();
  75. g_bRunDefaultHtm = FALSE;
  76. g_szShellNext[0] = '\0';
  77. }
  78. void SetICWComplete(void)
  79. {
  80. // Set the completed bit
  81. HKEY hkey = NULL;
  82. DWORD dwValue = 1;
  83. DWORD dwDisposition = 0;
  84. if(ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER,
  85. ICWSETTINGSPATH,
  86. 0,
  87. NULL,
  88. REG_OPTION_NON_VOLATILE,
  89. KEY_ALL_ACCESS,
  90. NULL,
  91. &hkey,
  92. &dwDisposition))
  93. {
  94. RegSetValueEx(hkey,
  95. szRegValICWCompleted,
  96. 0,
  97. REG_BINARY,
  98. (LPBYTE) &dwValue,
  99. sizeof(DWORD));
  100. RegCloseKey(hkey);
  101. }
  102. }
  103. LPWSTR WINAPI A2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars)
  104. {
  105. ASSERT(lpa != NULL);
  106. ASSERT(lpw != NULL);\
  107. // verify that no illegal character present
  108. // since lpw was allocated based on the size of lpa
  109. // don't worry about the number of chars
  110. lpw[0] = '\0';
  111. MultiByteToWideChar(CP_ACP, 0, lpa, -1, lpw, nChars);
  112. return lpw;
  113. }
  114. LPSTR WINAPI W2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars)
  115. {
  116. ASSERT(lpw != NULL);
  117. ASSERT(lpa != NULL);
  118. // verify that no illegal character present
  119. // since lpa was allocated based on the size of lpw
  120. // don't worry about the number of chars
  121. lpa[0] = '\0';
  122. WideCharToMultiByte(CP_ACP, 0, lpw, -1, lpa, nChars, NULL, NULL);
  123. return lpa;
  124. }
  125. HRESULT ConnectToICWConnectionPoint
  126. (
  127. IUnknown *punkThis,
  128. REFIID riidEvent,
  129. BOOL fConnect,
  130. IUnknown *punkTarget,
  131. DWORD *pdwCookie,
  132. IConnectionPoint **ppcpOut
  133. )
  134. {
  135. // We always need punkTarget, we only need punkThis on connect
  136. if (!punkTarget || (fConnect && !punkThis))
  137. {
  138. return E_FAIL;
  139. }
  140. if (ppcpOut)
  141. *ppcpOut = NULL;
  142. HRESULT hr;
  143. IConnectionPointContainer *pcpContainer;
  144. if (SUCCEEDED(hr = punkTarget->QueryInterface(IID_IConnectionPointContainer, (void **)&pcpContainer)))
  145. {
  146. IConnectionPoint *pcp;
  147. if(SUCCEEDED(hr = pcpContainer->FindConnectionPoint(riidEvent, &pcp)))
  148. {
  149. if(fConnect)
  150. {
  151. // Add us to the list of people interested...
  152. hr = pcp->Advise(punkThis, pdwCookie);
  153. if (FAILED(hr))
  154. *pdwCookie = 0;
  155. }
  156. else
  157. {
  158. // Remove us from the list of people interested...
  159. hr = pcp->Unadvise(*pdwCookie);
  160. *pdwCookie = 0;
  161. }
  162. if (ppcpOut && SUCCEEDED(hr))
  163. *ppcpOut = pcp;
  164. else
  165. pcp->Release();
  166. pcp = NULL;
  167. }
  168. pcpContainer->Release();
  169. pcpContainer = NULL;
  170. }
  171. return hr;
  172. }
  173. BOOL ConfirmCancel(HWND hWnd)
  174. {
  175. TCHAR szTitle[MAX_TITLE];
  176. TCHAR szMessage[MAX_MESSAGE];
  177. LoadString(g_hInstance, IDS_APPNAME, szTitle, sizeof(szTitle));
  178. LoadString(g_hInstance, IDS_WANTTOEXIT, szMessage, sizeof(szMessage));
  179. if (IDYES == MessageBox(hWnd,
  180. szMessage,
  181. szTitle,
  182. MB_APPLMODAL | MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2))
  183. {
  184. return TRUE;
  185. }
  186. else
  187. {
  188. return FALSE;
  189. }
  190. }
  191. BOOL Restart(HWND hWnd)
  192. {
  193. TCHAR szLongString[1024];
  194. LPTSTR pszSmallString1, pszSmallString2;
  195. pszSmallString1 = GetSz(IDS_NEEDRESTART1);
  196. pszSmallString2 = GetSz(IDS_NEEDRESTART2);
  197. lstrcpy(szLongString,pszSmallString1);
  198. lstrcat(szLongString,pszSmallString2);
  199. if (IDYES == MessageBox(hWnd,
  200. szLongString,
  201. GetSz(IDS_APPNAME),
  202. MB_APPLMODAL | MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2))
  203. {
  204. SetupForReboot(1);
  205. return TRUE;
  206. }
  207. else
  208. {
  209. return FALSE;
  210. }
  211. }
  212. void Reboot(HWND hWnd)
  213. {
  214. TCHAR szLongString[1024];
  215. LPTSTR pszSmallString1, pszSmallString2;
  216. // 4/28/97 ChrisK
  217. // Fix build break, because string was too long for compiler.
  218. pszSmallString1 = GetSz(IDS_NEEDREBOOT1);
  219. pszSmallString2 = GetSz(IDS_NEEDREBOOT2);
  220. lstrcpy(szLongString,pszSmallString1);
  221. lstrcat(szLongString,pszSmallString2);
  222. //
  223. // ChrisK Olympus 419
  224. // We changed our mind again and decided to no give the user a chance to avoid rebooting.
  225. //
  226. MessageBox( hWnd,
  227. szLongString,
  228. GetSz(IDS_APPNAME),
  229. MB_APPLMODAL |
  230. MB_ICONINFORMATION |
  231. MB_SETFOREGROUND |
  232. MB_OK);
  233. SetupForReboot(0);
  234. }
  235. BOOL WINAPI ConfigureSystem(HWND hDlg)
  236. {
  237. BOOL bReboot = FALSE;
  238. BOOL bRestart = FALSE;
  239. BOOL bQuitWizard = FALSE;
  240. BOOL bNoPWCaching = FALSE;
  241. PropSheet_SetWizButtons(GetParent(hDlg),0);
  242. gpWizardState->cmnStateData.pICWSystemConfig->ConfigSystem(&gpWizardState->cmnStateData.bSystemChecked);
  243. PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_NEXT);
  244. if (!gpWizardState->cmnStateData.bSystemChecked)
  245. {
  246. gpWizardState->cmnStateData.pICWSystemConfig->get_NeedsReboot(&bReboot);
  247. if (bReboot)
  248. {
  249. Reboot(hDlg);
  250. gfQuitWizard = TRUE;
  251. return FALSE;
  252. }
  253. gpWizardState->cmnStateData.pICWSystemConfig->get_NeedsRestart(&bRestart);
  254. if (bRestart)
  255. {
  256. if (Restart(hDlg))
  257. {
  258. gfQuitWizard = TRUE;
  259. return FALSE;
  260. }
  261. else
  262. {
  263. if (ConfirmCancel(hDlg))
  264. {
  265. gfQuitWizard = TRUE;
  266. }
  267. return FALSE;
  268. }
  269. }
  270. gpWizardState->cmnStateData.pICWSystemConfig->get_QuitWizard(&bQuitWizard);
  271. if(bQuitWizard)
  272. {
  273. gfQuitWizard = TRUE;
  274. return FALSE;
  275. }
  276. else
  277. {
  278. if (ConfirmCancel(hDlg))
  279. gfQuitWizard = TRUE;
  280. return FALSE;
  281. }
  282. }
  283. // Make sure there is not a policy against password caching
  284. gpWizardState->cmnStateData.pICWSystemConfig->CheckPasswordCachingPolicy(&bNoPWCaching);
  285. if (bNoPWCaching)
  286. {
  287. // too bad, no password caching, no ICW
  288. gfQuitWizard = TRUE;
  289. return FALSE;
  290. }
  291. return true;
  292. }
  293. BOOL IsNT5()
  294. {
  295. OSVERSIONINFO OsVersionInfo;
  296. ZeroMemory(&OsVersionInfo, sizeof(OSVERSIONINFO));
  297. OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  298. GetVersionEx(&OsVersionInfo);
  299. return ((VER_PLATFORM_WIN32_NT == OsVersionInfo.dwPlatformId) && (OsVersionInfo.dwMajorVersion >= 5));
  300. }
  301. BOOL IsNT()
  302. {
  303. OSVERSIONINFO OsVersionInfo;
  304. ZeroMemory(&OsVersionInfo, sizeof(OSVERSIONINFO));
  305. OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  306. GetVersionEx(&OsVersionInfo);
  307. return (VER_PLATFORM_WIN32_NT == OsVersionInfo.dwPlatformId);
  308. }
  309. BOOL IsWhistler()
  310. {
  311. BOOL bRet = FALSE;
  312. OSVERSIONINFO OsVersionInfo;
  313. ZeroMemory(&OsVersionInfo, sizeof(OSVERSIONINFO));
  314. OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  315. if (GetVersionEx(&OsVersionInfo))
  316. {
  317. if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  318. OsVersionInfo.dwMajorVersion >= 5 &&
  319. OsVersionInfo.dwMinorVersion >= 1)
  320. {
  321. bRet = TRUE;
  322. }
  323. }
  324. return bRet;
  325. }
  326. BOOL DoesUserHaveAdminPrivleges(HINSTANCE hInstance)
  327. {
  328. HKEY hKey = NULL;
  329. BOOL bRet = FALSE;
  330. if (!IsNT())
  331. return TRUE;
  332. // BUGBUG: We should allow NT5 to run in all user groups
  333. // except normal users.
  334. if (IsNT5())
  335. return TRUE;
  336. //
  337. // Ensure caller is an administrator on this machine.
  338. //
  339. if(RegOpenKeyEx(HKEY_USERS, TEXT(".DEFAULT"), 0, KEY_WRITE, &hKey) == 0)
  340. {
  341. RegCloseKey(hKey);
  342. bRet = TRUE;
  343. }
  344. return bRet;
  345. }
  346. void WINAPI FillWindowWithAppBackground
  347. (
  348. HWND hWndToFill,
  349. HDC hdc
  350. )
  351. {
  352. RECT rcUpdate;
  353. RECT rcBmp;
  354. HDC hdcWnd;
  355. HDC hSourceDC;
  356. HGDIOBJ hgdiOldBitmap;
  357. // If we are passed in the DC to use then use it, otherwise get
  358. // the DC from the window handle
  359. if (hdc)
  360. hdcWnd = hdc;
  361. else
  362. hdcWnd = GetDC(hWndToFill);
  363. hSourceDC = CreateCompatibleDC( hdcWnd );
  364. // Compute the client area of the main window that needs to be
  365. // erased, so that we can extract that chunk of the background
  366. // bitmap
  367. GetUpdateRect(hWndToFill, &rcUpdate, FALSE);
  368. // Make sure the rectangle is not empty
  369. if (IsRectEmpty(&rcUpdate))
  370. {
  371. InvalidateRect(hWndToFill, NULL, FALSE);
  372. GetUpdateRect(hWndToFill, &rcUpdate, FALSE);
  373. }
  374. rcBmp = rcUpdate;
  375. if (hWndToFill != gpWizardState->cmnStateData.hWndApp)
  376. MapWindowPoints(hWndToFill, gpWizardState->cmnStateData.hWndApp, (LPPOINT)&rcBmp, 2);
  377. // paint the background bitmap
  378. hgdiOldBitmap = SelectObject( hSourceDC, (HGDIOBJ) gpWizardState->cmnStateData.hbmBkgrnd);
  379. BitBlt( hdcWnd,
  380. rcUpdate.left,
  381. rcUpdate.top,
  382. RECTWIDTH(rcUpdate),
  383. RECTHEIGHT(rcUpdate),
  384. hSourceDC,
  385. rcBmp.left,
  386. rcBmp.top,
  387. SRCCOPY );
  388. // Cleanup GDI Objects
  389. SelectObject( hSourceDC, hgdiOldBitmap );
  390. DeleteDC(hSourceDC);
  391. // If we were not passed the DC, then release the one that we
  392. // got from the window handle
  393. if (!hdc)
  394. ReleaseDC(hWndToFill, hdcWnd);
  395. }
  396. // Fill in a rectangle within the specificed DC with the app's bkgrnd.
  397. // lpRectDC is a rectangle in the DC's coordinate space, and lpRectApp
  398. // is a rectangle in the Apps coordinate space
  399. void FillDCRectWithAppBackground
  400. (
  401. LPRECT lpRectDC,
  402. LPRECT lpRectApp,
  403. HDC hdc
  404. )
  405. {
  406. HDC hSourceDC = CreateCompatibleDC( hdc );
  407. HGDIOBJ hgdiOldBitmap;
  408. // paint the background bitmap
  409. hgdiOldBitmap = SelectObject( hSourceDC, (HGDIOBJ) gpWizardState->cmnStateData.hbmBkgrnd);
  410. BitBlt( hdc,
  411. lpRectDC->left,
  412. lpRectDC->top,
  413. RECTWIDTH(*lpRectDC),
  414. RECTHEIGHT(*lpRectDC),
  415. hSourceDC,
  416. lpRectApp->left,
  417. lpRectApp->top,
  418. SRCCOPY );
  419. // Cleanup GDI Objects
  420. SelectObject( hSourceDC, hgdiOldBitmap );
  421. DeleteDC(hSourceDC);
  422. }
  423. BOOL CheckForOemConfigFailure(HINSTANCE hInstance)
  424. {
  425. HKEY hKey = NULL;
  426. DWORD dwFailed = 0;
  427. DWORD dwSize = sizeof(dwFailed);
  428. TCHAR szIspName [MAX_PATH+1] = TEXT("\0");
  429. TCHAR szSupportNum [MAX_PATH+1] = TEXT("\0");
  430. TCHAR szErrMsg1 [MAX_RES_LEN] = TEXT("\0");
  431. TCHAR szErrMsg2 [MAX_RES_LEN] = TEXT("\0");
  432. TCHAR szErrMsgTmp1 [MAX_RES_LEN] = TEXT("\0");
  433. TCHAR szErrMsgTmp2 [MAX_RES_LEN] = TEXT("\0");
  434. TCHAR szCaption [MAX_RES_LEN] = TEXT("\0");
  435. TCHAR szErrDlgMsg [MAX_PATH*2 + MAX_RES_LEN + 2] = TEXT("\0");
  436. RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  437. OEM_CONFIG_REGKEY,
  438. 0,
  439. KEY_ALL_ACCESS,
  440. &hKey);
  441. if(hKey)
  442. {
  443. RegQueryValueEx(hKey,
  444. OEM_CONFIG_REGVAL_FAILED,
  445. 0,
  446. NULL,
  447. (LPBYTE)&dwFailed,
  448. &dwSize);
  449. if(dwFailed)
  450. {
  451. dwSize = sizeof(szIspName);
  452. RegQueryValueEx(hKey,
  453. OEM_CONFIG_REGVAL_ISPNAME,
  454. 0,
  455. NULL,
  456. (LPBYTE)&szIspName,
  457. &dwSize);
  458. dwSize = sizeof(szSupportNum);
  459. RegQueryValueEx(hKey,
  460. OEM_CONFIG_REGVAL_SUPPORTNUM,
  461. 0,
  462. NULL,
  463. (LPBYTE)&szSupportNum,
  464. &dwSize);
  465. if(*szIspName)
  466. {
  467. LoadString(hInstance, IDS_PRECONFIG_ERROR_1, szErrMsg1, sizeof(szErrMsg1));
  468. wsprintf(szErrMsgTmp1, szErrMsg1, szIspName);
  469. lstrcpy(szErrDlgMsg,szErrMsgTmp1);
  470. }
  471. else
  472. {
  473. LoadString(hInstance, IDS_PRECONFIG_ERROR_1_NOINFO, szErrMsg1, sizeof(szErrMsg1));
  474. lstrcpy(szErrDlgMsg, szErrMsg1);
  475. }
  476. if(*szSupportNum)
  477. {
  478. LoadString(hInstance, IDS_PRECONFIG_ERROR_2, szErrMsg2, sizeof(szErrMsg2));
  479. wsprintf(szErrMsgTmp2, szErrMsg2, szSupportNum);
  480. lstrcat(szErrDlgMsg, szErrMsgTmp2);
  481. }
  482. else
  483. {
  484. LoadString(hInstance, IDS_PRECONFIG_ERROR_2_NOINFO, szErrMsg2, sizeof(szErrMsg2));
  485. lstrcat(szErrDlgMsg, szErrMsg2);
  486. }
  487. LoadString(hInstance, IDS_APPNAME, szCaption, sizeof(szCaption));
  488. MessageBox(NULL, szErrDlgMsg, szCaption, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
  489. dwFailed = 0;
  490. RegSetValueEx(hKey,
  491. OEM_CONFIG_REGVAL_FAILED,
  492. 0,
  493. REG_DWORD,
  494. (LPBYTE)&dwFailed,
  495. sizeof(dwFailed));
  496. CloseHandle(hKey);
  497. return TRUE;
  498. }
  499. }
  500. return FALSE;
  501. }
  502. //returns TRUE if it could successfully find locate the file
  503. //and attempt to configure the system, this does not mean however that the process was successful
  504. BOOL RunOemconfigIns()
  505. {
  506. TCHAR szInsPath [MAX_PATH+1] = TEXT("\0");
  507. TCHAR szIspName [MAX_PATH+1] = TEXT("\0");
  508. TCHAR szSupportNum [MAX_PATH+1] = TEXT("\0");
  509. BOOL bRet = FALSE;
  510. GetWindowsDirectory(szInsPath, MAX_PATH+1);
  511. if(!szInsPath)
  512. return FALSE;
  513. if(*CharPrev(szInsPath, szInsPath + lstrlen(szInsPath)) != TEXT('\\'))
  514. lstrcat(szInsPath, TEXT("\\"));
  515. lstrcat(szInsPath, OEM_CONFIG_INS_FILENAME);
  516. //if we can't find the file return false
  517. if(0xFFFFFFFF == GetFileAttributes(szInsPath))
  518. return FALSE;
  519. //ProcessINS will nuke the file so if we want this info we should get it now
  520. GetPrivateProfileString(OEM_CONFIG_INS_SECTION,
  521. OEM_CONFIG_INS_ISPNAME,
  522. TEXT(""),
  523. szIspName,
  524. sizeof(szIspName),
  525. szInsPath);
  526. GetPrivateProfileString(OEM_CONFIG_INS_SECTION,
  527. OEM_CONFIG_INS_SUPPORTNUM,
  528. TEXT(""),
  529. szSupportNum,
  530. sizeof(szSupportNum),
  531. szInsPath);
  532. //set silent mode to disallow UI
  533. gpWizardState->pINSHandler->put_SilentMode(TRUE);
  534. // Process the inf file.
  535. gpWizardState->pINSHandler->ProcessINS(A2W(szInsPath), &bRet);
  536. if(bRet)
  537. QuickCompleteSignup();
  538. else
  539. {
  540. HKEY hKey = NULL;
  541. DWORD dwDisposition = 0;
  542. DWORD dwFailed = 1;
  543. //Let's make double sure we nuke the file.
  544. if(0xFFFFFFFF != GetFileAttributes(szInsPath))
  545. {
  546. DeleteFile(szInsPath);
  547. }
  548. RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  549. OEM_CONFIG_REGKEY,
  550. 0,
  551. NULL,
  552. REG_OPTION_NON_VOLATILE,
  553. KEY_ALL_ACCESS,
  554. NULL,
  555. &hKey,
  556. &dwDisposition);
  557. if(hKey)
  558. {
  559. RegSetValueEx(hKey,
  560. OEM_CONFIG_REGVAL_FAILED,
  561. 0,
  562. REG_DWORD,
  563. (LPBYTE)&dwFailed,
  564. sizeof(dwFailed));
  565. RegSetValueEx(hKey,
  566. OEM_CONFIG_REGVAL_ISPNAME,
  567. 0,
  568. REG_SZ,
  569. (LPBYTE)szIspName,
  570. sizeof(TCHAR)*lstrlen(szIspName));
  571. RegSetValueEx(hKey,
  572. OEM_CONFIG_REGVAL_SUPPORTNUM,
  573. 0,
  574. REG_SZ,
  575. (LPBYTE)szSupportNum,
  576. sizeof(TCHAR)*lstrlen(szSupportNum));
  577. CloseHandle(hKey);
  578. }
  579. }
  580. return TRUE;
  581. }