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.

1251 lines
42 KiB

  1. //*************************************************************
  2. //
  3. // General.cpp - General property sheet page
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1996-2000
  7. // All rights reserved
  8. //
  9. //*************************************************************
  10. // NT base apis
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <ntdddisk.h>
  15. #include <sysdm.h>
  16. #include <regstr.h>
  17. #include <help.h>
  18. #include <shellapi.h>
  19. #include <shlapip.h>
  20. #include <shlobjp.h>
  21. #include <regapix.h>
  22. #include <wininet.h>
  23. #include <wbemcli.h> // Contains the WMI APIs: IWbemLocator, etc.
  24. #include <ccstock.h> // Contains IID_PPV_ARG()
  25. #include <debug.h> // For TraceMsg()
  26. #include <stdio.h>
  27. #include <math.h>
  28. #include <tchar.h>
  29. #include <winbrand.h> // For added branding resources
  30. #define CP_ENGLISH 1252 // This is the English code page.
  31. #ifdef DEBUG
  32. #undef TraceMsg
  33. #define TraceMsg(nTFFlags, str, n1) DbgPrintf(TEXT(str) TEXT("\n"), n1)
  34. #else // DEBUG
  35. #endif // DEBUG
  36. #define SYSCPL_ASYNC_COMPUTER_INFO (WM_APP + 1)
  37. #define SZ_REGKEY_MYCOMP_OEMLINKS TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\OEMLinks")
  38. #define SZ_REGKEY_MYCOMP_OEMENGLISH TEXT("1252")
  39. #define SZ_ATCOMPATIBLE TEXT("AT/AT COMPATIBLE")
  40. #define SZ_WMI_WIN32PROCESSOR_ATTRIB_NAME L"Name" // Example, "Intel Pentium III Xeon processor"
  41. #define SZ_WMI_WIN32PROCESSOR_ATTRIB_SPEED L"CurrentClockSpeed" // Example, "550".
  42. #define SZ_WMI_WIN32PROCESSOR_ATTRIB_MAXSPEED L"MaxClockSpeed" // Example, "550".
  43. #define SZ_WMI_WQL_QUERY_STRING L"select Name,CurrentClockSpeed,MaxClockSpeed from Win32_Processor"
  44. #define MHZ_TO_GHZ_THRESHHOLD 1000
  45. // if cpu speed comes back slower than WMI_WIN32PROCESSOR_SPEEDSTEP_CUTOFF,
  46. // assume we're in power-save mode, display max speed instead.
  47. #define WMI_WIN32PROCESSOR_SPEEDSTEP_CUTOFF 50
  48. #define FEATURE_IGNORE_ATCOMPAT
  49. #define FEATURE_LINKS
  50. #define MAX_URL_STRING (INTERNET_MAX_SCHEME_LENGTH \
  51. + sizeof("://") \
  52. + INTERNET_MAX_PATH_LENGTH)
  53. #define MAX_PROCESSOR_DESCRIPTION MAX_URL_STRING
  54. // Globals for this page
  55. static BOOL g_fWin9xUpgrade = FALSE;
  56. static const TCHAR c_szEmpty[] = TEXT("");
  57. static const TCHAR c_szCRLF[] = TEXT("\r\n");
  58. static const TCHAR c_szAboutKey[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion");
  59. static const TCHAR c_szAboutRegisteredOwner[] = REGSTR_VAL_REGOWNER;
  60. static const TCHAR c_szAboutRegisteredOrganization[] = REGSTR_VAL_REGORGANIZATION;
  61. static const TCHAR c_szAboutProductId[] = REGSTR_VAL_PRODUCTID;
  62. static const TCHAR c_szAboutAnotherSerialNumber[] = TEXT("Plus! VersionNumber");
  63. static const TCHAR c_szAboutAnotherProductId[] = TEXT("Plus! ProductId");
  64. // oeminfo stuff
  65. static const TCHAR c_szSystemDir[] = TEXT("System\\");
  66. static const TCHAR c_szOemFile[] = TEXT("OemInfo.Ini");
  67. static const TCHAR c_szOemImageFile[] = TEXT("OemLogo.Bmp");
  68. static const TCHAR c_szOemGenSection[] = TEXT("General");
  69. static const TCHAR c_szOemSupportSection[] = TEXT("Support Information");
  70. static const TCHAR c_szOemName[] = TEXT("Manufacturer");
  71. static const TCHAR c_szOemModel[] = TEXT("Model");
  72. static const TCHAR c_szOemSupportLinePrefix[] = TEXT("line");
  73. static const TCHAR c_szDefSupportLineText[] = TEXT("@");
  74. static const TCHAR SZ_REGKEY_HARDWARE_CPU[] = TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
  75. static const TCHAR c_szMemoryManagement[] = TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
  76. static const TCHAR c_szPhysicalAddressExtension[] = TEXT("PhysicalAddressExtension");
  77. static const TCHAR c_szIndentifier[] = TEXT("Identifier");
  78. static const TCHAR SZ_REGVALUE_PROCESSORNAMESTRING[] = TEXT("ProcessorNameString");
  79. #define SZ_REGKEY_HARDWARE TEXT("HARDWARE\\DESCRIPTION\\System")
  80. #define SZ_REGKEY_USE_WMI TEXT("UseWMI")
  81. // Help ID's
  82. int g_nStartOfOEMLinks = 0;
  83. DWORD aGeneralHelpIds[] = {
  84. IDC_GEN_WINDOWS_IMAGE, NO_HELP,
  85. IDC_TEXT_1, (IDH_GENERAL + 0),
  86. IDC_GEN_VERSION_0, (IDH_GENERAL + 1),
  87. IDC_GEN_VERSION_1, (IDH_GENERAL + 1),
  88. IDC_GEN_VERSION_2, (IDH_GENERAL + 1),
  89. IDC_GEN_SERVICE_PACK, (IDH_GENERAL + 1),
  90. IDC_TEXT_3, (IDH_GENERAL + 3),
  91. IDC_GEN_REGISTERED_0, (IDH_GENERAL + 3),
  92. IDC_GEN_REGISTERED_1, (IDH_GENERAL + 3),
  93. IDC_GEN_REGISTERED_2, (IDH_GENERAL + 3),
  94. IDC_GEN_REGISTERED_3, (IDH_GENERAL + 3),
  95. IDC_GEN_OEM_IMAGE, NO_HELP,
  96. IDC_TEXT_4, (IDH_GENERAL + 6),
  97. IDC_GEN_MACHINE_0, (IDH_GENERAL + 7),
  98. IDC_GEN_MACHINE_1, (IDH_GENERAL + 8),
  99. IDC_GEN_MACHINE_2, (IDH_GENERAL + 9),
  100. IDC_GEN_MACHINE_3, (IDH_GENERAL + 10),
  101. IDC_GEN_MACHINE_4, (IDH_GENERAL + 11),
  102. IDC_GEN_MACHINE_5, NO_HELP,
  103. IDC_GEN_MACHINE_6, NO_HELP,
  104. IDC_GEN_MACHINE_7, NO_HELP,
  105. IDC_GEN_MACHINE_8, NO_HELP,
  106. IDC_GEN_OEM_SUPPORT, (IDH_GENERAL + 12),
  107. IDC_GEN_REGISTERED_2, (IDH_GENERAL + 14),
  108. IDC_GEN_REGISTERED_3, (IDH_GENERAL + 15),
  109. IDC_GEN_MACHINE, (IDH_GENERAL + 7),
  110. IDC_GEN_OEM_NUDGE, NO_HELP,
  111. 0, 0
  112. };
  113. //
  114. // Macros
  115. //
  116. #define BytesToK(pDW) (*(pDW) = (*(pDW) + 512) / 1024) // round up
  117. //
  118. // Function proto-types
  119. //
  120. INT_PTR APIENTRY PhoneSupportProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  121. DWORD WINAPI InitGeneralDlgThread(LPVOID lpParam);
  122. typedef struct {
  123. TCHAR szProcessorDesc[MAX_PROCESSOR_DESCRIPTION];
  124. TCHAR szProcessorClockSpeed[MAX_PROCESSOR_DESCRIPTION];
  125. } PROCESSOR_INFO;
  126. typedef struct {
  127. LONGLONG llMem;
  128. PROCESSOR_INFO pi;
  129. BOOL fShowProcName;
  130. BOOL fShowProcSpeed;
  131. } INITDLGSTRUCT;
  132. HRESULT _SetMachineInfoLine(HWND hDlg, int idControl, LPCTSTR pszText, BOOL fSetTabStop)
  133. {
  134. HRESULT hr = S_OK;
  135. #ifdef FEATURE_LINKS
  136. HWND hwndItem = GetDlgItem(hDlg, idControl);
  137. SetDlgItemText(hDlg, idControl, pszText);
  138. if (fSetTabStop)
  139. {
  140. // We also want to add the WS_TABSTOP attribute for accessibility.
  141. SetWindowLong(hwndItem, GWL_STYLE, (WS_TABSTOP | GetWindowLong(hwndItem, GWL_STYLE)));
  142. }
  143. else
  144. {
  145. // We want to remove the tab stop behavior and we do that by removing
  146. // the LWIS_ENABLED attribute
  147. LWITEM item = {0};
  148. item.mask = (LWIF_ITEMINDEX | LWIF_STATE);
  149. item.stateMask = LWIS_ENABLED;
  150. item.state = 0; // 0 if we want it disabled.
  151. item.iLink = 0;
  152. hr = (SendMessage(hwndItem, LWM_SETITEM, 0, (LPARAM)&item) ? S_OK : E_FAIL);
  153. }
  154. #else // FEATURE_LINKS
  155. SetDlgItemText(hDlg, idControl, pszText);
  156. #endif // FEATURE_LINKS
  157. return hr;
  158. }
  159. //*************************************************************
  160. // Purpose: Sets or clears an image in a static control.
  161. //
  162. // Parameters: control - handle of static control
  163. // resource - resource / filename of bitmap
  164. // fl - SCB_ flags:
  165. // SCB_FROMFILE 'resource' specifies a filename instead of a resource
  166. // SCB_REPLACEONLY only put the new image up if there was an old one
  167. //
  168. // Return: (BOOL) TRUE if successful
  169. // FALSE if an error occurs
  170. //
  171. // Comments:
  172. //
  173. // History: Date Author Comment
  174. // 5/24/95 ericflo Ported
  175. //*************************************************************
  176. #define SCB_FROMFILE (0x1)
  177. #define SCB_REPLACEONLY (0x2)
  178. BOOL SetClearBitmap( HWND control, LPCTSTR resource, UINT fl )
  179. {
  180. HBITMAP hbm = (HBITMAP)SendMessage(control, STM_GETIMAGE, IMAGE_BITMAP, 0);
  181. if( hbm )
  182. {
  183. DeleteObject( hbm );
  184. }
  185. else if( fl & SCB_REPLACEONLY )
  186. {
  187. return FALSE;
  188. }
  189. if( resource )
  190. {
  191. SendMessage(control, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)
  192. LoadImage( hInstance, resource, IMAGE_BITMAP, 0, 0,
  193. LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS |
  194. ( ( fl & SCB_FROMFILE )? LR_LOADFROMFILE : 0 ) ) );
  195. }
  196. return
  197. ((HBITMAP)SendMessage(control, STM_GETIMAGE, IMAGE_BITMAP, 0) != NULL);
  198. }
  199. BOOL IsLowColor (HWND hDlg)
  200. {
  201. BOOL fLowColor = FALSE;
  202. HDC hdc = GetDC(hDlg);
  203. if (hdc)
  204. {
  205. INT iColors = GetDeviceCaps( hdc, NUMCOLORS );
  206. fLowColor = ((iColors != -1) && (iColors <= 256));
  207. ReleaseDC(hDlg, hdc);
  208. }
  209. return fLowColor;
  210. }
  211. HRESULT _GetLinkInfo(HKEY hkey, LPCTSTR pszLanguageKey, int nIndex, LPTSTR pszLink, SIZE_T cchNameSize)
  212. {
  213. DWORD cbSize = (DWORD)(cchNameSize * sizeof(pszLink[0]));
  214. TCHAR szIndex[10];
  215. DWORD dwError;
  216. wnsprintf(szIndex, ARRAYSIZE(szIndex), TEXT("%03d"), nIndex);
  217. dwError = SHGetValue(hkey, pszLanguageKey, szIndex, NULL, (void *) pszLink, &cbSize);
  218. return HRESULT_FROM_WIN32(dwError);
  219. }
  220. // GSierra is worried that if we allow admins to put an arbirary
  221. // number of OEM links that they will abuse the privalage.
  222. // So we use this arbitrary limit. PMs may want to change it in
  223. // the future.
  224. #define ARTIFICIAL_MAX_SLOTS 3
  225. HRESULT AddOEMHyperLinks(HWND hDlg, int * pControlID)
  226. {
  227. HKEY hkey;
  228. DWORD dwError;
  229. HRESULT hr;
  230. g_nStartOfOEMLinks = *pControlID;
  231. dwError = RegOpenKey(HKEY_LOCAL_MACHINE, SZ_REGKEY_MYCOMP_OEMLINKS, &hkey);
  232. hr = HRESULT_FROM_WIN32(dwError);
  233. if (hkey)
  234. {
  235. int nIndex;
  236. // While we have room and haven't hit the limit.
  237. for (nIndex = 0; ((nIndex <= ARTIFICIAL_MAX_SLOTS) &&
  238. (*pControlID <= LAST_GEN_MACHINES_SLOT)); nIndex++)
  239. {
  240. TCHAR szLink[2 * MAX_URL_STRING];
  241. TCHAR szLanguageKey[10];
  242. wnsprintf(szLanguageKey, ARRAYSIZE(szLanguageKey), TEXT("%u"), GetACP());
  243. hr = _GetLinkInfo(hkey, szLanguageKey, nIndex, szLink, ARRAYSIZE(szLink));
  244. if (FAILED(hr) && (CP_ENGLISH != GetACP()))
  245. {
  246. // We failed to find it in the natural language, so try English.
  247. hr = _GetLinkInfo(hkey, SZ_REGKEY_MYCOMP_OEMENGLISH, nIndex, szLink, ARRAYSIZE(szLink));
  248. }
  249. if (SUCCEEDED(hr))
  250. {
  251. // TODO: Find out how to turn on the link control and set the URL.
  252. _SetMachineInfoLine(hDlg, *pControlID, szLink, TRUE);
  253. }
  254. (*pControlID)++;
  255. }
  256. RegCloseKey(hkey);
  257. }
  258. return hr;
  259. }
  260. HRESULT HrSysAllocStringW(IN const OLECHAR * pwzSource, OUT BSTR * pbstrDest)
  261. {
  262. HRESULT hr = S_OK;
  263. if (pbstrDest)
  264. {
  265. *pbstrDest = SysAllocString(pwzSource);
  266. if (pwzSource)
  267. {
  268. if (*pbstrDest)
  269. hr = S_OK;
  270. else
  271. hr = E_OUTOFMEMORY;
  272. }
  273. }
  274. return hr;
  275. }
  276. HRESULT SetWMISecurityBlanket(IN IUnknown * punk, IUnknown * punkToPass)
  277. {
  278. IClientSecurity * pClientSecurity;
  279. HRESULT hr = punk->QueryInterface(IID_PPV_ARG(IClientSecurity, &pClientSecurity));
  280. TraceMsg(TF_ALWAYS, "IEnumWbemClassObject::QueryInterface(IClientSecurity) called and hr=%#08lx", hr);
  281. if (SUCCEEDED(hr))
  282. {
  283. // Nuke after we get this working. RPC_C_AUTHN_NONE , RPC_C_AUTHZ_NAME
  284. hr = pClientSecurity->SetBlanket(punk, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
  285. RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
  286. TraceMsg(TF_ALWAYS, "IClientSecurity::SetBlanket() called and hr=%#08lx", hr);
  287. pClientSecurity->Release();
  288. }
  289. return hr;
  290. }
  291. // DESCRIPTION:
  292. // WMI's Win32_Processor object will return a lot of rich information.
  293. // We use this because we want rich information even if the processor doesn't
  294. // provide it (like intel pre-Willette). Millennium uses cpuid.asm as a
  295. // hack and we want to prevent from copying that because there is a political
  296. // pressure from the NT team to intel to have the processors provide this
  297. // information. That way the OS doesn't need to rev to include new processor
  298. // names when they are released. WMI does something to generate good results
  299. // (\admin\wmi\WBEM\Providers\Win32Provider\Providers\processor.cpp) which
  300. // includes asm. I don't know if it's the exact same logic as Millennium and
  301. // I don't care. The important fact is that they are the only ones to maintain
  302. // any hard coded list. Therefore we are willing to use their poorly written
  303. // API so we can re-use code and get out of the maintaince problems.
  304. HRESULT GetWMI_Win32_Processor(OUT IEnumWbemClassObject ** ppEnumProcessors)
  305. {
  306. HRESULT hr = E_NOTIMPL;
  307. *ppEnumProcessors = NULL;
  308. // Our second try is to use the WMI automation object. It has a Win32_Processor object
  309. // that can give us a good Description, even when SZ_REGVALUE_PROCESSORNAMESTRING
  310. // isn't set.
  311. IWbemLocator * pLocator;
  312. hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IWbemLocator, &pLocator));
  313. if (SUCCEEDED(hr))
  314. {
  315. hr = E_OUTOFMEMORY;
  316. BSTR bstrLocalMachine = SysAllocString(L"root\\cimv2");
  317. if (bstrLocalMachine)
  318. {
  319. IWbemServices * pIWbemServices;
  320. hr = pLocator->ConnectServer(bstrLocalMachine, NULL, NULL, 0L, 0L, NULL, NULL, &pIWbemServices);
  321. TraceMsg(TF_ALWAYS, "IWbemLocator::ConnectServer() called and hr=%#08lx", hr);
  322. if (SUCCEEDED(hr))
  323. {
  324. hr = E_OUTOFMEMORY;
  325. BSTR bstrQueryLang = SysAllocString(L"WQL");
  326. BSTR bstrQuery = SysAllocString(SZ_WMI_WQL_QUERY_STRING);
  327. if (bstrQueryLang && bstrQuery)
  328. {
  329. IEnumWbemClassObject * pEnum = NULL;
  330. hr = pIWbemServices->ExecQuery(bstrQueryLang, bstrQuery, (WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY), NULL , &pEnum);
  331. TraceMsg(TF_ALWAYS, "IWbemServices::CreateInstanceEnum() called and hr=%#08lx", hr);
  332. if (SUCCEEDED(hr))
  333. {
  334. hr = SetWMISecurityBlanket(pEnum, pIWbemServices);
  335. TraceMsg(TF_ALWAYS, "SetWMISecurityBlanket() called and hr=%#08lx", hr);
  336. if (SUCCEEDED(hr))
  337. {
  338. hr = pEnum->QueryInterface(IID_PPV_ARG(IEnumWbemClassObject, ppEnumProcessors));
  339. }
  340. pEnum->Release();
  341. }
  342. }
  343. SysFreeString(bstrQuery); // SysFreeString is happy to take NULL
  344. SysFreeString(bstrQueryLang);
  345. pIWbemServices->Release();
  346. }
  347. SysFreeString(bstrLocalMachine);
  348. }
  349. pLocator->Release();
  350. }
  351. return hr;
  352. }
  353. HRESULT GetProcessorDescFromWMI(PROCESSOR_INFO *ppi)
  354. {
  355. IEnumWbemClassObject * pEnumProcessors;
  356. HRESULT hr = GetWMI_Win32_Processor(&pEnumProcessors);
  357. if (SUCCEEDED(hr))
  358. {
  359. IWbemClassObject * pProcessor;
  360. ULONG ulRet;
  361. // Currently we only care about the first processor.
  362. hr = pEnumProcessors->Next(WBEM_INFINITE, 1, &pProcessor, &ulRet);
  363. TraceMsg(TF_ALWAYS, "IEnumWbemClassObject::Next() called and hr=%#08lx", hr);
  364. if (SUCCEEDED(hr))
  365. {
  366. VARIANT varProcessorName = {0};
  367. hr = pProcessor->Get(SZ_WMI_WIN32PROCESSOR_ATTRIB_NAME, 0, &varProcessorName, NULL, NULL);
  368. if (SUCCEEDED(hr))
  369. {
  370. VARIANT varProcessorSpeed = {0};
  371. hr = pProcessor->Get(SZ_WMI_WIN32PROCESSOR_ATTRIB_SPEED, 0, &varProcessorSpeed, NULL, NULL);
  372. if (SUCCEEDED(hr) &&
  373. VT_I4 == varProcessorSpeed.vt &&
  374. varProcessorSpeed.lVal < WMI_WIN32PROCESSOR_SPEEDSTEP_CUTOFF) // we're in speed step power-saving mode
  375. {
  376. hr = pProcessor->Get(SZ_WMI_WIN32PROCESSOR_ATTRIB_MAXSPEED, 0, &varProcessorSpeed, NULL, NULL);
  377. }
  378. if (SUCCEEDED(hr))
  379. {
  380. if ((VT_BSTR == varProcessorName.vt) && (VT_I4 == varProcessorSpeed.vt))
  381. {
  382. StrCpyN(ppi->szProcessorDesc, varProcessorName.bstrVal, ARRAYSIZE(ppi->szProcessorDesc));
  383. TCHAR szTemplate[MAX_PATH];
  384. UINT idStringTemplate = IDS_PROCESSOR_SPEED;
  385. szTemplate[0] = 0;
  386. if (MHZ_TO_GHZ_THRESHHOLD <= varProcessorSpeed.lVal)
  387. {
  388. TCHAR szSpeed[20];
  389. double dGHz = (varProcessorSpeed.lVal / (double)1000.0);
  390. // Someone released a "1.13 GHz" chip, so let's display that correctly...
  391. _snwprintf(szSpeed, ARRAYSIZE(szSpeed), TEXT("%1.2f"), dGHz);
  392. LoadString(hInstance, IDS_PROCESSOR_SPEEDGHZ, szTemplate, ARRAYSIZE(szTemplate));
  393. wnsprintf(ppi->szProcessorClockSpeed, ARRAYSIZE(ppi->szProcessorClockSpeed), szTemplate, szSpeed);
  394. }
  395. else
  396. {
  397. LoadString(hInstance, IDS_PROCESSOR_SPEED, szTemplate, ARRAYSIZE(szTemplate));
  398. wnsprintf(ppi->szProcessorClockSpeed, ARRAYSIZE(ppi->szProcessorClockSpeed), szTemplate, varProcessorSpeed.lVal);
  399. }
  400. }
  401. else
  402. {
  403. hr = E_FAIL;
  404. }
  405. }
  406. VariantClear(&varProcessorSpeed);
  407. }
  408. VariantClear(&varProcessorName);
  409. pProcessor->Release();
  410. }
  411. pEnumProcessors->Release();
  412. }
  413. return hr;
  414. }
  415. HRESULT GetProcessorInfoFromRegistry(HKEY hkey, PROCESSOR_INFO *ppi)
  416. {
  417. HRESULT hr = E_FAIL;
  418. TCHAR szTemp[MAX_PROCESSOR_DESCRIPTION];
  419. *szTemp = NULL;
  420. DWORD cbData = sizeof(szTemp);
  421. //To avoid copying blank string.
  422. if ((RegQueryValueEx(hkey, SZ_REGVALUE_PROCESSORNAMESTRING, 0, 0, (LPBYTE)szTemp, &cbData) == ERROR_SUCCESS) &&
  423. (*szTemp != NULL) && (cbData > 1))
  424. {
  425. //ISSUE - How do I get the processor clock speed.
  426. StrCpyN(ppi->szProcessorDesc, szTemp, MAX_PROCESSOR_DESCRIPTION);
  427. hr = S_OK;
  428. }
  429. return hr;
  430. }
  431. // This is the number of chars that will fit on one line in our dialog
  432. // with the current layout.
  433. #define SIZE_CHARSINLINE 30
  434. BOOL _GetProcessorDescription(PROCESSOR_INFO* ppi, BOOL* pbShowClockSpeed)
  435. {
  436. BOOL bShowProcessorInfo = FALSE;
  437. *pbShowClockSpeed = TRUE;
  438. HKEY hkey;
  439. // In general, WMI is a lowse API. However, they provide the processor description on
  440. // downlevel so we need them. They implement this in a hacky way so we want them to
  441. // maintain the hack and all the problems associated with it. We need to turn this feature
  442. // off until they fix their bugs. Currently, they call JET which recently regressed and
  443. // causes their API to take 10-20 seconds. -BryanSt
  444. if (SHRegGetBoolUSValue(SZ_REGKEY_HARDWARE, SZ_REGKEY_USE_WMI, FALSE, TRUE))
  445. {
  446. if (SUCCEEDED(GetProcessorDescFromWMI(ppi)))
  447. {
  448. bShowProcessorInfo = TRUE;
  449. }
  450. }
  451. if (RegOpenKey(HKEY_LOCAL_MACHINE, SZ_REGKEY_HARDWARE_CPU, &hkey) == ERROR_SUCCESS)
  452. {
  453. // Try for ProcessorNameString if present.
  454. // This registry entry will contain the most correct description of the processor
  455. // because it came directly from the CPU. AMD and Cyrix support this but
  456. // intel won't until Willette.
  457. if (FAILED(GetProcessorInfoFromRegistry(hkey, ppi)))
  458. {
  459. if (!bShowProcessorInfo)
  460. {
  461. // Our last try is to use the generic Identifier. This is normally formatted like,
  462. // "x86 Family 6 Model 7 Stepping 3" but it's better than nothing.
  463. DWORD cbData = sizeof(ppi->szProcessorDesc);
  464. if (RegQueryValueEx(hkey, c_szIndentifier, 0, 0, (LPBYTE)ppi->szProcessorDesc, &cbData) == ERROR_SUCCESS)
  465. {
  466. bShowProcessorInfo = TRUE;
  467. *pbShowClockSpeed = FALSE;
  468. }
  469. }
  470. }
  471. RegCloseKey(hkey);
  472. }
  473. return bShowProcessorInfo;
  474. }
  475. void _SetProcessorDescription(HWND hDlg, PROCESSOR_INFO* ppi, BOOL bShowClockSpeed, BOOL bShowProcessorInfo, int * pnControlID)
  476. {
  477. if (bShowProcessorInfo)
  478. {
  479. TCHAR szProcessorLine1[MAX_PATH];
  480. TCHAR szProcessorLine2[MAX_PATH];
  481. // We need to get the CPU name from the CPU itself so we don't
  482. // need to rev our OS's INF files every time they ship a new processor. So we guaranteed
  483. // them that we would display whatever string they provide in whatever way they provide it
  484. // up to 49 chars. The layout on the dlg doesn't allow 49 chars on one line so we need to wrap
  485. // in that case. Whistler #159510.
  486. // Don't change this without talking to me (BryanSt) or JVert.
  487. //
  488. // Note: there is often talk of stripping leading spaces. Intel even asks software to do this.
  489. // (http://developer.intel.com/design/processor/future/manuals/CPUID_Supplement.htm)
  490. // However, we SHOULD NOT do this. This call was defined and standardized by AMD long ago.
  491. // The rule we make is they must be compatible with AMD�s existing implementation.
  492. // (http://www.amd.com/products/cpg/athlon/techdocs/pdf/20734.pdf)
  493. // Contact JVert for questions on stripping leading spaces.
  494. StrCpyN(szProcessorLine1, ppi->szProcessorDesc, ARRAYSIZE(szProcessorLine1));
  495. szProcessorLine2[0] = 0;
  496. if (SIZE_CHARSINLINE < lstrlen(szProcessorLine1))
  497. {
  498. // Now word wrap
  499. TCHAR* pszWrapPoint = StrRChr(szProcessorLine1, szProcessorLine1 + SIZE_CHARSINLINE, TEXT(' '));
  500. if (pszWrapPoint)
  501. {
  502. StrCpyN(szProcessorLine2, pszWrapPoint + 1, ARRAYSIZE(szProcessorLine2));
  503. *pszWrapPoint = 0;
  504. }
  505. else // if no space found, just wrap at SIZE_CHARSINLINE
  506. {
  507. StrCpyN(szProcessorLine2, &szProcessorLine1[SIZE_CHARSINLINE], ARRAYSIZE(szProcessorLine2));
  508. szProcessorLine1[SIZE_CHARSINLINE] = 0;
  509. }
  510. }
  511. _SetMachineInfoLine(hDlg, (*pnControlID)++, szProcessorLine1, FALSE);
  512. if (szProcessorLine2[0])
  513. {
  514. _SetMachineInfoLine(hDlg, (*pnControlID)++, szProcessorLine2, FALSE);
  515. }
  516. if (bShowClockSpeed)
  517. {
  518. _SetMachineInfoLine(hDlg, (*pnControlID)++, ppi->szProcessorClockSpeed, FALSE);
  519. }
  520. }
  521. }
  522. typedef struct _OSNAMEIDPAIR {
  523. UINT iOSType;
  524. UINT iOSName;
  525. } OSNAMEIDPAIR;
  526. //*************************************************************
  527. // Purpose: Initalize the general page
  528. //
  529. // Parameters: hDlg - Handle to the dialog box
  530. //
  531. // Return: void
  532. //
  533. // Comments:
  534. //
  535. // History: Date Author Comment
  536. // 11/20/95 ericflo Ported
  537. //*************************************************************
  538. VOID InitGeneralDlg(HWND hDlg)
  539. {
  540. OSVERSIONINFO ver;
  541. TCHAR szScratch1[64];
  542. TCHAR szScratch2[64];
  543. DWORD cbData;
  544. HKEY hkey;
  545. int ctlid;
  546. UINT uXpSpLevel = 0;
  547. HMODULE hResourceDll = hInstance;
  548. // Set the default bitmap
  549. SetClearBitmap(GetDlgItem(hDlg, IDC_GEN_WINDOWS_IMAGE),
  550. IsLowColor(hDlg) ? MAKEINTRESOURCE(IDB_WINDOWS_256) : MAKEINTRESOURCE(IDB_WINDOWS), 0);
  551. // Query for the build number information
  552. ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  553. if (!GetVersionEx(&ver)) {
  554. return;
  555. }
  556. // IDC_GEN_VERSION_0: Major Branding ("Windows XP")
  557. // todo: for now, everything is "Windows XP". must change for blackcomb
  558. UINT id = IDS_WINVER_WINDOWSXP;
  559. LoadString(hInstance, id, szScratch1, ARRAYSIZE(szScratch1));
  560. SetDlgItemText(hDlg, IDC_GEN_VERSION_0, szScratch1);
  561. // IDC_GEN_VERSION_1: Minor Branding ("Personal", "Professional", etc)
  562. szScratch1[0] = TEXT('\0');
  563. id = 0;
  564. // note: OS_EMBEDDED must be before any options that may co-occur with OS_EMBEDDED
  565. #ifndef _WIN64
  566. OSNAMEIDPAIR rgID[] = {{OS_EMBEDDED, IDS_WINVER_EMBEDDED},
  567. {OS_TABLETPC, IDS_WINVER_TABLETPC_SYSDM_CPL},
  568. {OS_MEDIACENTER, IDS_WINVER_MEDIACENTER_SYSDM_CPL},
  569. {OS_PERSONAL, IDS_WINVER_PERSONAL},
  570. {OS_PROFESSIONAL, IDS_WINVER_PROFESSIONAL},
  571. {OS_SERVER, IDS_WINVER_SERVER},
  572. {OS_ADVSERVER, IDS_WINVER_ADVANCEDSERVER},
  573. {OS_DATACENTER, IDS_WINVER_DATACENTER}};
  574. #else
  575. OSNAMEIDPAIR rgID[] = {{OS_PROFESSIONAL, IDS_WINVER_PROFESSIONAL_WIN64},
  576. {OS_SERVER, IDS_WINVER_SERVER},
  577. {OS_ADVSERVER, IDS_WINVER_ADVANCEDSERVER},
  578. {OS_DATACENTER, IDS_WINVER_DATACENTER}};
  579. #endif
  580. for (int i = 0; i < ARRAYSIZE(rgID); i++)
  581. {
  582. if (IsOS(rgID[i].iOSType))
  583. {
  584. // Do a special test now to determine if this resource was added
  585. // for a Windows XP service pack.
  586. switch (rgID[i].iOSType)
  587. {
  588. case OS_TABLETPC:
  589. case OS_MEDIACENTER:
  590. uXpSpLevel = 1;
  591. break;
  592. }
  593. id = (rgID[i].iOSName);
  594. break;
  595. }
  596. };
  597. // If this string resource was added for a Windows XP service pack, and
  598. // lives in a special resource DLL, attempt to load it now. If this
  599. // fails, revert to the Professional string resource.
  600. if (uXpSpLevel > 0)
  601. {
  602. hResourceDll = LoadLibraryEx(TEXT("winbrand.dll"),
  603. NULL,
  604. LOAD_LIBRARY_AS_DATAFILE);
  605. if (hResourceDll == NULL)
  606. {
  607. hResourceDll = hInstance;
  608. id = IDS_WINVER_PROFESSIONAL;
  609. }
  610. }
  611. LoadString(hResourceDll, id, szScratch1, ARRAYSIZE(szScratch1));
  612. if (hResourceDll != hInstance)
  613. {
  614. FreeLibrary(hResourceDll);
  615. }
  616. SetDlgItemText(hDlg, IDC_GEN_VERSION_1, szScratch1);
  617. // IDC_GEN_VERSION_2: Version Year ("Version 2002", etc)
  618. // set szScratch2 to "Debug" if the debugging version of USER.EXE is installed
  619. if (GetSystemMetrics(SM_DEBUG))
  620. {
  621. szScratch2[0] = TEXT(' ');
  622. LoadString(hInstance, IDS_DEBUG, &szScratch2[1], ARRAYSIZE(szScratch2));
  623. }
  624. else
  625. {
  626. szScratch2[0] = TEXT('\0');
  627. }
  628. // todo: for now, everything is 2002. For Blackcomb we'll need to update this.
  629. LoadString(hInstance, IDS_WINVER_2002, szScratch1, ARRAYSIZE(szScratch1));
  630. StrCatBuff(szScratch1, szScratch2, ARRAYSIZE(szScratch1));
  631. SetDlgItemText(hDlg, IDC_GEN_VERSION_2, szScratch1);
  632. // IDC_GEN_SERVICE_PACK: Service Pack (if any)
  633. SetDlgItemText(hDlg, IDC_GEN_SERVICE_PACK, ver.szCSDVersion);
  634. if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szAboutKey, &hkey) == ERROR_SUCCESS)
  635. {
  636. // Do registered user info
  637. ctlid = IDC_GEN_REGISTERED_0; // start here and use more as needed
  638. cbData = ARRAYSIZE( szScratch2 ) * sizeof (TCHAR);
  639. if( (RegQueryValueEx(hkey, c_szAboutRegisteredOwner,
  640. NULL, NULL, (LPBYTE)szScratch2, &cbData) == ERROR_SUCCESS) &&
  641. ( cbData > 1 ) )
  642. {
  643. SetDlgItemText(hDlg, ctlid++, szScratch2);
  644. }
  645. cbData = ARRAYSIZE( szScratch2 ) * sizeof (TCHAR);
  646. if( (RegQueryValueEx(hkey, c_szAboutRegisteredOrganization,
  647. NULL, NULL, (LPBYTE)szScratch2, &cbData) == ERROR_SUCCESS) &&
  648. ( cbData > 1 ) )
  649. {
  650. SetDlgItemText(hDlg, ctlid++, szScratch2);
  651. }
  652. cbData = ARRAYSIZE( szScratch2 ) * sizeof (TCHAR);
  653. if( (RegQueryValueEx(hkey, c_szAboutProductId,
  654. NULL, NULL, (LPBYTE)szScratch2, &cbData) == ERROR_SUCCESS) &&
  655. ( cbData > 1 ) )
  656. {
  657. SetDlgItemText(hDlg, ctlid++, szScratch2);
  658. }
  659. cbData = ARRAYSIZE( szScratch2 ) * sizeof (TCHAR);
  660. if( (RegQueryValueEx(hkey, c_szAboutAnotherProductId,
  661. NULL, NULL, (LPBYTE)szScratch2, &cbData) == ERROR_SUCCESS) &&
  662. ( cbData > 1 ) )
  663. {
  664. SetDlgItemText(hDlg, ctlid++, szScratch2);
  665. }
  666. RegCloseKey(hkey);
  667. }
  668. SHCreateThread(InitGeneralDlgThread, hDlg, CTF_COINIT | CTF_FREELIBANDEXIT, NULL);
  669. }
  670. DWORD WINAPI InitGeneralDlgThread(LPVOID lpParam)
  671. {
  672. SYSTEM_BASIC_INFORMATION BasicInfo;
  673. NTSTATUS Status;
  674. if (!lpParam)
  675. return -1;
  676. INITDLGSTRUCT* pids = (INITDLGSTRUCT*)LocalAlloc(LPTR, sizeof(INITDLGSTRUCT));
  677. if (pids)
  678. {
  679. // Memory
  680. Status = NtQuerySystemInformation(
  681. SystemBasicInformation,
  682. &BasicInfo,
  683. sizeof(BasicInfo),
  684. NULL
  685. );
  686. if (NT_SUCCESS(Status))
  687. {
  688. LONGLONG nTotalBytes = BasicInfo.NumberOfPhysicalPages;
  689. nTotalBytes *= BasicInfo.PageSize;
  690. // WORKAROUND - NtQuerySystemInformation doesn't really return the total available physical
  691. // memory, it instead just reports the total memory seen by the Operating System. Since
  692. // some amount of memory is reserved by BIOS, the total available memory is reported
  693. // incorrectly. To work around this limitation, we convert the total bytes to
  694. // the nearest 4MB value
  695. #define ONEMB 1048576 //1MB = 1048576 bytes.
  696. double nTotalMB = (double)(nTotalBytes / ONEMB);
  697. pids->llMem = (LONGLONG)((ceil(ceil(nTotalMB) / 4.0) * 4.0) * ONEMB);
  698. }
  699. pids->fShowProcName = _GetProcessorDescription(&pids->pi, &pids->fShowProcSpeed);
  700. PostMessage((HWND)lpParam, SYSCPL_ASYNC_COMPUTER_INFO, (WPARAM)pids, 0);
  701. }
  702. return 0;
  703. }
  704. VOID CompleteGeneralDlgInitialization(HWND hDlg, INITDLGSTRUCT* pids)
  705. {
  706. TCHAR oemfile[MAX_PATH];
  707. int ctlid;
  708. NTSTATUS Status;
  709. HKEY hkey;
  710. TCHAR szScratch1[64];
  711. TCHAR szScratch2[64];
  712. TCHAR szScratch3[64];
  713. DWORD cbData;
  714. // Do machine info
  715. ctlid = IDC_GEN_MACHINE_0; // start here and use controls as needed
  716. // if OEM name is present, show logo and check for phone support info
  717. if (!GetSystemDirectory(oemfile, ARRAYSIZE(oemfile)))
  718. {
  719. oemfile[0] = 0;
  720. }
  721. if( oemfile[ lstrlen( oemfile ) - 1 ] != TEXT('\\') )
  722. lstrcat( oemfile, TEXT("\\"));
  723. lstrcat( oemfile, c_szOemFile );
  724. if (!PathFileExists(oemfile))
  725. {
  726. // On Win9x, the oeminfo files went in %windir%\system,
  727. // so we need to look in there, as well.
  728. if (GetWindowsDirectory(oemfile, ARRAYSIZE(oemfile)))
  729. {
  730. if (oemfile[lstrlen(oemfile)-1] != TEXT('\\'))
  731. lstrcat(oemfile, TEXT("\\"));
  732. }
  733. lstrcat(oemfile, c_szSystemDir);
  734. lstrcat(oemfile, c_szOemFile);
  735. if (PathFileExists(oemfile)) {
  736. g_fWin9xUpgrade = TRUE;
  737. }
  738. }
  739. if( GetPrivateProfileString( c_szOemGenSection, c_szOemName, c_szEmpty,
  740. szScratch1, ARRAYSIZE( szScratch1 ), oemfile ) )
  741. {
  742. _SetMachineInfoLine(hDlg, ctlid++, szScratch1, FALSE);
  743. if( GetPrivateProfileString( c_szOemGenSection, c_szOemModel,
  744. c_szEmpty, szScratch1, ARRAYSIZE( szScratch1 ), oemfile ) )
  745. {
  746. _SetMachineInfoLine(hDlg, ctlid++, szScratch1, FALSE);
  747. }
  748. lstrcpy( szScratch2, c_szOemSupportLinePrefix );
  749. lstrcat( szScratch2, TEXT("1") );
  750. if( GetPrivateProfileString( c_szOemSupportSection,
  751. szScratch2, c_szEmpty, szScratch1, ARRAYSIZE( szScratch1 ), oemfile ) )
  752. {
  753. HWND wnd = GetDlgItem( hDlg, IDC_GEN_OEM_SUPPORT );
  754. EnableWindow( wnd, TRUE );
  755. ShowWindow( wnd, SW_SHOW );
  756. }
  757. if (g_fWin9xUpgrade)
  758. {
  759. if (GetWindowsDirectory( oemfile, ARRAYSIZE( oemfile ) ))
  760. {
  761. if( oemfile[ lstrlen( oemfile ) - 1 ] != TEXT('\\') )
  762. lstrcat( oemfile, TEXT("\\") );
  763. }
  764. else
  765. {
  766. oemfile[0] = 0;
  767. }
  768. lstrcat(oemfile, c_szSystemDir);
  769. lstrcat( oemfile, c_szOemImageFile );
  770. }
  771. else {
  772. if (!GetSystemDirectory( oemfile, ARRAYSIZE( oemfile ) ))
  773. {
  774. oemfile[0] = 0;
  775. }
  776. if( oemfile[ lstrlen( oemfile ) - 1 ] != TEXT('\\') )
  777. lstrcat( oemfile, TEXT("\\") );
  778. lstrcat( oemfile, c_szOemImageFile );
  779. }
  780. if( SetClearBitmap( GetDlgItem( hDlg, IDC_GEN_OEM_IMAGE ), oemfile,
  781. SCB_FROMFILE ) )
  782. {
  783. ShowWindow( GetDlgItem( hDlg, IDC_GEN_OEM_NUDGE ), SW_SHOWNA );
  784. ShowWindow( GetDlgItem( hDlg, IDC_GEN_MACHINE ), SW_HIDE );
  785. }
  786. }
  787. // Get Processor Description
  788. _SetProcessorDescription(hDlg, &pids->pi, pids->fShowProcSpeed, pids->fShowProcName, &ctlid);
  789. // System identifier
  790. if (RegOpenKey(HKEY_LOCAL_MACHINE, SZ_REGKEY_HARDWARE, &hkey) == ERROR_SUCCESS)
  791. {
  792. cbData = ARRAYSIZE( szScratch2 ) * sizeof (TCHAR);
  793. if (RegQueryValueEx(hkey, c_szIndentifier, 0, 0, (LPBYTE)szScratch2, &cbData) == ERROR_SUCCESS)
  794. {
  795. // Some OEMs put "AT/AT Compatible" as the System Identifier. Since this
  796. // is completely obsolete, we may want to have a feature that simply ignores
  797. // it.
  798. #ifdef FEATURE_IGNORE_ATCOMPAT
  799. if (StrCmpI(szScratch2, SZ_ATCOMPATIBLE))
  800. #endif // FEATURE_IGNORE_ATCOMPAT
  801. {
  802. _SetMachineInfoLine(hDlg, ctlid++, szScratch2, FALSE);
  803. }
  804. }
  805. RegCloseKey(hkey);
  806. }
  807. StrFormatByteSize(pids->llMem, szScratch1, ARRAYSIZE(szScratch1));
  808. LoadString(hInstance, IDS_XDOTX_MB, szScratch3, ARRAYSIZE(szScratch3));
  809. wnsprintf(szScratch2, ARRAYSIZE(szScratch2), szScratch3, szScratch1);
  810. _SetMachineInfoLine(hDlg, ctlid++, szScratch2, FALSE);
  811. // Physical address extension
  812. Status = RegOpenKey(
  813. HKEY_LOCAL_MACHINE,
  814. c_szMemoryManagement,
  815. &hkey
  816. );
  817. if (ERROR_SUCCESS == Status)
  818. {
  819. DWORD paeEnabled;
  820. Status = RegQueryValueEx(
  821. hkey,
  822. c_szPhysicalAddressExtension,
  823. NULL,
  824. NULL,
  825. (LPBYTE)&paeEnabled,
  826. &cbData
  827. );
  828. if (ERROR_SUCCESS == Status &&
  829. sizeof(paeEnabled) == cbData &&
  830. 0 != paeEnabled) {
  831. LoadString(hInstance, IDS_PAE, szScratch1, ARRAYSIZE(szScratch1));
  832. _SetMachineInfoLine(hDlg, ctlid++, szScratch1, FALSE);
  833. }
  834. RegCloseKey(hkey);
  835. }
  836. AddOEMHyperLinks(hDlg, &ctlid);
  837. }
  838. HRESULT _DisplayHelp(LPHELPINFO lpHelpInfo)
  839. {
  840. // We will call WinHelp() unless it's an OEM link
  841. // because in that case, we don't know what to show.
  842. if ((g_nStartOfOEMLinks <= lpHelpInfo->iCtrlId) && // Is it outside of the IDC_GEN_MACHINE_* range used by OEM Links?
  843. (LAST_GEN_MACHINES_SLOT >= lpHelpInfo->iCtrlId) && // Is it outside of the IDC_GEN_MACHINE_* range used by OEM Links?
  844. (IDC_GEN_OEM_SUPPORT != lpHelpInfo->iCtrlId)) // Is it outside of the IDC_GEN_MACHINE_* range used by OEM Links?
  845. {
  846. int nIndex;
  847. // This item is an OEM link, so let's mark it as "No Help".
  848. for (nIndex = 0; nIndex < ARRAYSIZE(aGeneralHelpIds); nIndex++)
  849. {
  850. if ((DWORD)lpHelpInfo->iCtrlId == aGeneralHelpIds[nIndex])
  851. {
  852. aGeneralHelpIds[nIndex + 1] = NO_HELP;
  853. break;
  854. }
  855. nIndex++; // We need to skip every other entry because it's a list.
  856. }
  857. }
  858. WinHelp((HWND)lpHelpInfo->hItemHandle, HELP_FILE, HELP_WM_HELP, (DWORD_PTR) (LPSTR) aGeneralHelpIds);
  859. return S_OK;
  860. }
  861. //*************************************************************
  862. // Purpose: Dialog box procedure for general tab
  863. //
  864. // Parameters: hDlg - handle to the dialog box
  865. // uMsg - window message
  866. // wParam - wParam
  867. // lParam - lParam
  868. //
  869. // Return: TRUE if message was processed
  870. // FALSE if not
  871. //
  872. // Comments:
  873. //
  874. // History: Date Author Comment
  875. // 11/17/95 ericflo Created
  876. //*************************************************************
  877. INT_PTR APIENTRY GeneralDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  878. {
  879. switch (uMsg)
  880. {
  881. case WM_INITDIALOG:
  882. InitGeneralDlg(hDlg);
  883. break;
  884. case WM_NOTIFY:
  885. switch (((NMHDR FAR*)lParam)->code)
  886. {
  887. case PSN_APPLY:
  888. SetWindowLongPtr (hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  889. return TRUE;
  890. default:
  891. return FALSE;
  892. }
  893. break;
  894. case WM_COMMAND:
  895. if (wParam == IDC_GEN_OEM_SUPPORT) {
  896. DialogBox(hInstance, MAKEINTRESOURCE(IDD_PHONESUP),
  897. GetParent(hDlg), PhoneSupportProc);
  898. }
  899. break;
  900. case WM_SYSCOLORCHANGE:
  901. {
  902. TCHAR oemfile[MAX_PATH];
  903. if (g_fWin9xUpgrade)
  904. {
  905. if (GetWindowsDirectory( oemfile, ARRAYSIZE( oemfile ) ))
  906. {
  907. if( oemfile[ lstrlen( oemfile ) - 1 ] != TEXT('\\') )
  908. lstrcat( oemfile, TEXT("\\") );
  909. }
  910. else
  911. {
  912. *oemfile = TEXT('\0');
  913. }
  914. lstrcat(oemfile, c_szSystemDir);
  915. lstrcat( oemfile, c_szOemImageFile );
  916. }
  917. else {
  918. if (!GetSystemDirectory( oemfile, ARRAYSIZE( oemfile ) ))
  919. {
  920. oemfile[0] = 0;
  921. }
  922. if( oemfile[ lstrlen( oemfile ) - 1 ] != TEXT('\\') )
  923. lstrcat( oemfile, TEXT("\\") );
  924. lstrcat( oemfile, c_szOemImageFile );
  925. }
  926. SetClearBitmap(GetDlgItem(hDlg, IDC_GEN_OEM_IMAGE), oemfile, SCB_FROMFILE | SCB_REPLACEONLY);
  927. SetClearBitmap(GetDlgItem(hDlg, IDC_GEN_WINDOWS_IMAGE),
  928. IsLowColor(hDlg) ? MAKEINTRESOURCE(IDB_WINDOWS_256) : MAKEINTRESOURCE(IDB_WINDOWS), 0);
  929. }
  930. break;
  931. case SYSCPL_ASYNC_COMPUTER_INFO:
  932. {
  933. if (wParam)
  934. {
  935. CompleteGeneralDlgInitialization(hDlg, (INITDLGSTRUCT*)wParam);
  936. LocalFree((HLOCAL)wParam);
  937. }
  938. }
  939. break;
  940. case WM_DESTROY:
  941. SetClearBitmap( GetDlgItem( hDlg, IDC_GEN_OEM_IMAGE ), NULL, 0 );
  942. SetClearBitmap( GetDlgItem( hDlg, IDC_GEN_WINDOWS_IMAGE ), NULL, 0 );
  943. break;
  944. case WM_HELP: // F1
  945. _DisplayHelp((LPHELPINFO) lParam);
  946. break;
  947. case WM_CONTEXTMENU: // right mouse click
  948. WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
  949. (DWORD_PTR) (LPSTR) aGeneralHelpIds);
  950. break;
  951. default:
  952. return FALSE;
  953. }
  954. return TRUE;
  955. }
  956. //*************************************************************
  957. //
  958. // PhoneSupportProc()
  959. //
  960. // Purpose: Dialog box procedure for OEM phone support dialog
  961. //
  962. // Parameters: hDlg - handle to the dialog box
  963. // uMsg - window message
  964. // wParam - wParam
  965. // lParam - lParam
  966. //
  967. // Return: TRUE if message was processed
  968. // FALSE if not
  969. //
  970. // Comments:
  971. //
  972. // History: Date Author Comment
  973. // 11/17/95 ericflo Created
  974. //
  975. //*************************************************************
  976. INT_PTR APIENTRY PhoneSupportProc(HWND hDlg, UINT uMsg,
  977. WPARAM wParam, LPARAM lParam )
  978. {
  979. switch( uMsg ) {
  980. case WM_INITDIALOG:
  981. {
  982. HWND edit = GetDlgItem(hDlg, IDC_SUPPORT_TEXT);
  983. UINT i = 1; // 1-based by design
  984. TCHAR oemfile[MAX_PATH];
  985. TCHAR text[ 256 ];
  986. TCHAR line[ 12 ];
  987. LPTSTR endline = line + lstrlen( c_szOemSupportLinePrefix );
  988. if (g_fWin9xUpgrade)
  989. {
  990. if (GetWindowsDirectory( oemfile, ARRAYSIZE( oemfile ) ))
  991. {
  992. if( oemfile[ lstrlen( oemfile ) - 1 ] != TEXT('\\') )
  993. lstrcat( oemfile, TEXT("\\") );
  994. }
  995. else
  996. {
  997. *oemfile = TEXT('\0');
  998. }
  999. lstrcat(oemfile, c_szSystemDir);
  1000. lstrcat( oemfile, c_szOemFile );
  1001. }
  1002. else
  1003. {
  1004. if (!GetSystemDirectory( oemfile, ARRAYSIZE( oemfile ) ))
  1005. {
  1006. oemfile[0] = 0;
  1007. }
  1008. if( oemfile[ lstrlen( oemfile ) - 1 ] != TEXT('\\') )
  1009. lstrcat( oemfile, TEXT("\\") );
  1010. lstrcat( oemfile, c_szOemFile );
  1011. }
  1012. GetPrivateProfileString( c_szOemGenSection, c_szOemName, c_szEmpty,
  1013. text, ARRAYSIZE( text ), oemfile );
  1014. SetWindowText( hDlg, text );
  1015. lstrcpy( line, c_szOemSupportLinePrefix );
  1016. SendMessage (edit, WM_SETREDRAW, FALSE, 0);
  1017. for( ;; i++ )
  1018. {
  1019. wsprintf( endline, TEXT("%u"), i );
  1020. GetPrivateProfileString( c_szOemSupportSection,
  1021. line, c_szDefSupportLineText, text, ARRAYSIZE( text ) - 2,
  1022. oemfile );
  1023. if( !lstrcmpi( text, c_szDefSupportLineText ) )
  1024. break;
  1025. lstrcat( text, c_szCRLF );
  1026. SendMessage( edit, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
  1027. SendMessage( edit, EM_REPLACESEL, 0, (LPARAM)text );
  1028. }
  1029. SendMessage (edit, WM_SETREDRAW, TRUE, 0);
  1030. break;
  1031. }
  1032. case WM_COMMAND:
  1033. switch (LOWORD(wParam)) {
  1034. case IDOK:
  1035. case IDCANCEL:
  1036. EndDialog( hDlg, 0 );
  1037. break;
  1038. default:
  1039. return FALSE;
  1040. }
  1041. break;
  1042. default:
  1043. return FALSE;
  1044. }
  1045. return TRUE;
  1046. }