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.

2102 lines
64 KiB

  1. //--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999 - 2000.
  5. //
  6. // File: scansys
  7. //
  8. // Contents: Scan system settings.
  9. //
  10. //---------------------------------------------------------------
  11. #include <scanhead.cxx>
  12. #pragma hdrstop
  13. #include <common.hxx>
  14. #include <stdio.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <errno.h>
  18. #include <io.h>
  19. #include <objerror.h>
  20. #include <scanstate.hxx>
  21. #include <winuser.h>
  22. #include <winnetwk.h>
  23. #include <winspool.h>
  24. #include <lmerr.h>
  25. #include <lmaccess.h>
  26. // We need to define WINVER to a pre-2000 definition in order to
  27. // pull in the right structure definitions and sizes for correct
  28. // operation on 9x and NT.
  29. #undef WINVER
  30. #define WINVER 0x400
  31. #include <ras.h>
  32. #include <raserror.h>
  33. #include "bothchar.hxx"
  34. #include "scansys.hxx"
  35. //---------------------------------------------------------------
  36. const CHAR SHARES[] = "[NetShares]\r\n";
  37. const CHAR PRINTERS[] = "[Printers]\r\n";
  38. const CHAR RAS[] = "[RAS]\r\n";
  39. #define LINEBUFSIZE 1024
  40. // longest ip address is: XXX.XXX.XXX.XXX\0
  41. #define MAX_IP_ADDRESS 16
  42. const CHAR REGKEY_TIMEZONE[] = "System\\CurrentControlSet\\Control\\TimeZoneInformation";
  43. const CHAR REGVAL_TIMEZONE[] = "StandardName";
  44. const CHAR REGKEY_VERSION[] = "Software\\Microsoft\\Windows NT\\CurrentVersion";
  45. const CHAR REGKEY_VERSION_9x[] = "Software\\Microsoft\\Windows\\CurrentVersion";
  46. const CHAR REGVAL_FULLNAME[] = "RegisteredOwner";
  47. const CHAR REGVAL_ORGNAME[] = "RegisteredOrganization";
  48. const CHAR REGKEY_RAS[] = "System\\CurrentControlSet\\Services\\RemoteAccess";
  49. const CHAR SCRNSAVE[] = "SCRNSAVE.EXE";
  50. const CHAR REGKEY_NT4_PBK[] = "Software\\Microsoft\\RAS Phonebook";
  51. const CHAR REGVAL_NT4_PRS_PBK_LOC[] = "PersonalPhonebookFile";
  52. const CHAR REGVAL_NT4_ALT_PBK_LOC[] = "AlternatePhonebookPath";
  53. const CHAR RAS_NT4_RAS_PATH[] = "system32\\ras";
  54. const CHAR RAS_NT4_SYSTEM_PHONEBOOK[] = "rasphone.pbk";
  55. #define ChkErr(s) if ((dwErr = (s)) != ERROR_SUCCESS) goto Err;
  56. //+---------------------------------------------------------------------------
  57. // Types
  58. // RAS api functions
  59. typedef DWORD
  60. (*MRasEnumEntries)(
  61. IN LPCSTR reserved,
  62. IN LPCSTR lpszPhonebook,
  63. OUT LPRASENTRYNAMEA lprasentryname,
  64. OUT LPDWORD lpcb,
  65. OUT LPDWORD lpcEntries);
  66. typedef DWORD
  67. (*MRasGetEntryProperties)(
  68. IN LPCSTR lpszPhonebook,
  69. IN LPCSTR lpszEntry,
  70. OUT LPRASENTRYA lpRasEntry,
  71. OUT LPDWORD lpdwEntryInfoSize,
  72. OUT LPBYTE lpbDeviceInfo,
  73. OUT LPDWORD lpdwDeviceInfoSize);
  74. typedef DWORD
  75. (*MRasGetEntryDialParams)(
  76. IN LPCSTR lpszPhonebook,
  77. OUT LPRASDIALPARAMSA lprasdialparams,
  78. OUT LPBOOL lpfPassword);
  79. //+---------------------------------------------------------------------------
  80. // Statics
  81. static MRasEnumEntries GRasEnumEntries = NULL;
  82. static MRasGetEntryProperties GRasGetEntryProperties = NULL;
  83. static MRasGetEntryDialParams GRasGetEntryDialParams = NULL;
  84. //+---------------------------------------------------------------------------
  85. //
  86. // Function: InitializeRasApi
  87. //
  88. // Synopsis: Loads rasapi32.dll if it exists
  89. //
  90. // Arguments: none
  91. //
  92. // Returns: Appropriate status code
  93. //
  94. // History: 24-Feb-00 Jay Thaler Created
  95. DWORD InitializeRasApi()
  96. {
  97. DWORD result = ERROR_SUCCESS;
  98. HINSTANCE rasdll;
  99. // Load rasapi32.dll
  100. rasdll = LoadLibraryA( "rasapi32.dll" );
  101. if (rasdll == NULL)
  102. {
  103. result = GetLastError();
  104. if (DebugOutput)
  105. {
  106. Win32Printf(STDERR, "Warning: rasapi32.dll not loaded: %d\r\n", result);
  107. }
  108. goto cleanup;
  109. }
  110. GRasEnumEntries = (MRasEnumEntries)GetProcAddress(rasdll, "RasEnumEntriesA");
  111. if (GRasEnumEntries == NULL)
  112. {
  113. result = GetLastError();
  114. goto cleanup;
  115. }
  116. GRasGetEntryProperties = (MRasGetEntryProperties)GetProcAddress(rasdll, "RasGetEntryPropertiesA");
  117. if (GRasGetEntryProperties == NULL)
  118. {
  119. result = GetLastError();
  120. goto cleanup;
  121. }
  122. GRasGetEntryDialParams = (MRasGetEntryDialParams)GetProcAddress(rasdll, "RasGetEntryDialParamsA");
  123. if (GRasGetEntryDialParams == NULL)
  124. {
  125. result = GetLastError();
  126. goto cleanup;
  127. }
  128. cleanup:
  129. if (result != ERROR_SUCCESS)
  130. {
  131. GRasEnumEntries = NULL;
  132. GRasGetEntryProperties = NULL;
  133. GRasGetEntryDialParams = NULL;
  134. }
  135. return result;
  136. }
  137. //+---------------------------------------------------------------------------
  138. //
  139. // Function: GetInfField
  140. //
  141. // Synopsis: returns an allocated string for current line field #N
  142. //
  143. // Arguments: [ppBuffer] -- output buffer
  144. // [pContext] -- INF file context
  145. // [nArg] -- argument field number
  146. //
  147. // Returns: Appropriate status code
  148. //
  149. // History: 20-Sep-99 HenryLee Created
  150. //
  151. //----------------------------------------------------------------------------
  152. DWORD GetInfField (TCHAR **ppBuffer, INFCONTEXT *pContext, DWORD nArg)
  153. {
  154. ULONG len = 0;
  155. DWORD dwErr = ERROR_SUCCESS;
  156. TCHAR *buffer;
  157. *ppBuffer = NULL;
  158. if (!SetupGetStringField ( pContext, nArg, NULL, 0, &len ))
  159. return ERROR_BAD_FORMAT;
  160. // Allocate a buffer.
  161. buffer = (TCHAR *) malloc( len*sizeof(TCHAR) );
  162. if (buffer == NULL)
  163. {
  164. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  165. }
  166. else
  167. {
  168. if (!SetupGetStringField ( pContext, nArg, buffer, len, &len ))
  169. {
  170. free( buffer );
  171. dwErr = ERROR_BAD_FORMAT;
  172. }
  173. else *ppBuffer = buffer;
  174. }
  175. return dwErr;
  176. }
  177. //+---------------------------------------------------------------------------
  178. //
  179. // Function: LogFormatError
  180. //
  181. // Synopsis: logs error message in current locale
  182. //
  183. // Arguments:
  184. //
  185. // Returns: Appropriate status code
  186. //
  187. // History: 20-Sep-99 HenryLee Created
  188. //
  189. //----------------------------------------------------------------------------
  190. DWORD LogFormatError (DWORD dwErr)
  191. {
  192. DWORD dwRet = ERROR_SUCCESS;
  193. TCHAR *pcs = NULL;
  194. if (0 != FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
  195. FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL,
  196. dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  197. (TCHAR*) &pcs, 0, NULL))
  198. {
  199. dwRet = Win32Printf (LogFile, "%s\r\n", pcs);
  200. LocalFree (pcs);
  201. }
  202. else dwRet = GetLastError();
  203. return dwRet;
  204. }
  205. //+---------------------------------------------------------------------------
  206. //
  207. // Function: ScanGenerateEncryptKey
  208. //
  209. // Synopsis: decode the RAS address BLOB
  210. //
  211. // Arguments:
  212. //
  213. // Returns: Appropriate status code
  214. //
  215. // History: 20-Sep-99 HenryLee Created
  216. //
  217. //----------------------------------------------------------------------------
  218. BYTE ScanGenerateEncryptKey (CHAR *szKey)
  219. {
  220. BYTE bKey;
  221. BYTE* pKey;
  222. for (bKey = 0, pKey = (BYTE*)szKey; *pKey != 0; pKey++)
  223. {
  224. bKey += *pKey;
  225. };
  226. return bKey;
  227. }
  228. //+---------------------------------------------------------------------------
  229. //
  230. // Function: ScanDecryptEntry
  231. //
  232. // Synopsis: decode the RAS address BLOB
  233. //
  234. // Arguments:
  235. //
  236. // Returns: Appropriate status code
  237. //
  238. // History: 20-Sep-99 HenryLee Created
  239. //
  240. //----------------------------------------------------------------------------
  241. void ScanDecryptEntry (CHAR * szEntry, BYTE * pEnt, DWORD cb)
  242. {
  243. // Generate the encryption key from the entry name
  244. BYTE bKey = ScanGenerateEncryptKey(szEntry);
  245. // Encrypt the address entry one byte at a time
  246. for (;cb > 0; cb--, pEnt++)
  247. {
  248. *pEnt ^= bKey;
  249. };
  250. return;
  251. }
  252. //+---------------------------------------------------------------------------
  253. //
  254. // Function: IsRasInstalled
  255. //
  256. // Synopsis: determines if RAS is installed
  257. //
  258. // Arguments:
  259. //
  260. // Returns: Appropriate status code
  261. //
  262. // History: 20-Sep-99 HenryLee Created
  263. //
  264. //----------------------------------------------------------------------------
  265. BOOL IsRasInstalled ()
  266. {
  267. HKEY hKey = NULL;
  268. if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_LOCAL_MACHINE,
  269. REGKEY_RAS,
  270. NULL,
  271. KEY_READ,
  272. &hKey))
  273. {
  274. RegCloseKey (hKey);
  275. return TRUE;
  276. }
  277. return FALSE;
  278. }
  279. //----------------------------------------------------------------------------
  280. DWORD RasReadIpAddress(HINF h,
  281. const TCHAR *pszEntryName,
  282. const TCHAR *pszKeyName,
  283. RASIPADDR *lpIpAddr)
  284. {
  285. BOOL fSuccess;
  286. INFCONTEXT IpAddrLine;
  287. TCHAR szIpAddr[MAX_IP_ADDRESS];
  288. DWORD dwAddr1, dwAddr2, dwAddr3, dwAddr4;
  289. DWORD dwErr = ERROR_SUCCESS;
  290. fSuccess = SetupFindFirstLine(h,
  291. pszEntryName,
  292. pszKeyName,
  293. &IpAddrLine);
  294. if (fSuccess == FALSE)
  295. {
  296. dwErr = GetLastError();
  297. Win32PrintfResource(LogFile, IDS_RAS_ENTRY_NOT_MIGRATED, pszEntryName);
  298. if (DebugOutput)
  299. {
  300. Win32Printf(LogFile,
  301. "SetupFindFirstLine: Error %d looking for %s[%s]\r\n",
  302. dwErr, pszEntryName, pszKeyName);
  303. }
  304. goto cleanup;
  305. }
  306. fSuccess = SetupGetStringField(&IpAddrLine, 1, szIpAddr, MAX_IP_ADDRESS, 0);
  307. if (fSuccess == FALSE)
  308. {
  309. dwErr = GetLastError();
  310. Win32PrintfResource(LogFile, IDS_RAS_ENTRY_NOT_MIGRATED, pszEntryName);
  311. if (DebugOutput)
  312. {
  313. Win32Printf(LogFile,
  314. "SetupGetStringField: Error %d reading %s[%s]\r\n",
  315. dwErr, pszEntryName, pszKeyName);
  316. }
  317. goto cleanup;
  318. }
  319. if (_stscanf(szIpAddr, "%d.%d.%d.%d",
  320. &dwAddr1, &dwAddr2, &dwAddr3, &dwAddr4) != 4)
  321. {
  322. if (DebugOutput)
  323. {
  324. Win32Printf(LogFile,
  325. "szIpAddr for %s[%s] is not an address: %s\r\n",
  326. pszEntryName, pszKeyName, szIpAddr);
  327. }
  328. dwErr = ERROR_BAD_FORMAT;
  329. goto cleanup;
  330. }
  331. lpIpAddr->a = (BYTE)dwAddr1;
  332. lpIpAddr->b = (BYTE)dwAddr2;
  333. lpIpAddr->c = (BYTE)dwAddr3;
  334. lpIpAddr->d = (BYTE)dwAddr4;
  335. cleanup:
  336. return dwErr;
  337. }
  338. //----------------------------------------------------------------------------
  339. DWORD ScanRasPhonebook( HANDLE h, LPCTSTR lpPbkFileName )
  340. {
  341. DWORD dwErr = ERROR_SUCCESS;
  342. LPRASENTRYNAMEA lpRasEntryName;
  343. DWORD i = 0;
  344. DWORD dwRasEntrySize = 0;
  345. DWORD dwRasEntryNameSize = 0;
  346. DWORD dwBufferSize = 0;
  347. DWORD cEntries = 0;
  348. LPRASENTRYA lpRasEntry = NULL;
  349. RASDIALPARAMSA RasDialParams;
  350. BOOL bPasswordRead = FALSE;
  351. HINF hPbkFile = INVALID_HANDLE_VALUE;
  352. // Make sure the file exists
  353. if(GetFileAttributes(lpPbkFileName) == -1)
  354. {
  355. ChkErr( GetLastError() );
  356. }
  357. lpRasEntryName = (LPRASENTRYNAMEA)GlobalAlloc(GPTR, sizeof(RASENTRYNAMEA));
  358. lpRasEntryName->dwSize = sizeof(RASENTRYNAMEA); // Should be 264 when WINVER < 0x500
  359. dwErr = GRasEnumEntries(NULL,
  360. lpPbkFileName,
  361. lpRasEntryName,
  362. &dwRasEntryNameSize,
  363. &cEntries);
  364. if (dwErr == ERROR_INVALID_SIZE || dwErr == ERROR_BUFFER_TOO_SMALL )
  365. {
  366. lpRasEntryName = (LPRASENTRYNAMEA)GlobalAlloc(GPTR, dwRasEntryNameSize);
  367. if ( cEntries > 1 )
  368. {
  369. lpRasEntryName->dwSize = dwRasEntryNameSize / cEntries;
  370. }
  371. else
  372. {
  373. lpRasEntryName->dwSize = dwRasEntryNameSize;
  374. }
  375. dwErr = GRasEnumEntries(NULL,
  376. lpPbkFileName,
  377. lpRasEntryName,
  378. &dwRasEntryNameSize,
  379. &cEntries);
  380. }
  381. if (dwErr != ERROR_SUCCESS)
  382. {
  383. // The resource file specifies %1!d! which requires an int argument in this case
  384. Win32PrintfResource (LogFile, IDS_RAS_CANNOT_ENUM, dwErr);
  385. goto Err;
  386. }
  387. for(i=0; i < cEntries; i++)
  388. {
  389. // Read size needed
  390. GRasGetEntryProperties(lpPbkFileName,
  391. lpRasEntryName->szEntryName,
  392. NULL,
  393. &dwRasEntrySize,
  394. NULL,
  395. 0);
  396. if (lpRasEntry == NULL)
  397. {
  398. lpRasEntry = (LPRASENTRYA)malloc(dwRasEntrySize);
  399. }
  400. else if (dwRasEntrySize > dwBufferSize)
  401. {
  402. lpRasEntry = (LPRASENTRYA)realloc(lpRasEntry, dwRasEntrySize);
  403. dwBufferSize = dwRasEntrySize;
  404. }
  405. ZeroMemory( lpRasEntry, dwBufferSize );
  406. lpRasEntry->dwSize = sizeof(RASENTRYA);
  407. dwErr = GRasGetEntryProperties( lpPbkFileName,
  408. lpRasEntryName->szEntryName,
  409. lpRasEntry,
  410. &dwRasEntrySize,
  411. NULL,
  412. 0 );
  413. if (dwErr != ERROR_SUCCESS)
  414. {
  415. // Log Error
  416. Win32PrintfResource (LogFile, IDS_RAS_ENTRY_NOT_MIGRATED, lpRasEntryName->szEntryName);
  417. if (DebugOutput)
  418. {
  419. Win32Printf(LogFile, "RasGetEntryProperties: Error %d\r\n", dwErr );
  420. }
  421. goto Err;
  422. }
  423. if ((lpPbkFileName != NULL) &&
  424. (lpRasEntry->dwFramingProtocol == RASFP_Slip))
  425. {
  426. // We read from a PBK file (not Win9x) and we're using SLIP.
  427. // This means the ipAddress, DNS addresses, and WINS addresses
  428. // were probably lost. Those bastards!
  429. UINT dwErrorLine;
  430. hPbkFile = SetupOpenInfFile(lpPbkFileName,
  431. NULL,
  432. INF_STYLE_OLDNT | INF_STYLE_WIN4,
  433. &dwErrorLine);
  434. if (hPbkFile == INVALID_HANDLE_VALUE)
  435. {
  436. dwErr = GetLastError();
  437. Win32PrintfResource(LogFile, IDS_RAS_ENTRY_NOT_MIGRATED,
  438. lpRasEntryName->szEntryName);
  439. if (DebugOutput)
  440. {
  441. Win32Printf(LogFile,
  442. "SetupOpenInfFile: Error 0x%X opening %s, line %d\r\n",
  443. dwErr, lpPbkFileName, dwErrorLine );
  444. }
  445. goto Err;
  446. }
  447. // Check IpAddress
  448. if ((*(DWORD*)&lpRasEntry->ipaddr) == 0 )
  449. {
  450. ChkErr( RasReadIpAddress(hPbkFile,
  451. lpRasEntryName->szEntryName,
  452. TEXT("IpAddress"),
  453. &(lpRasEntry->ipaddr)) );
  454. }
  455. if ((*(DWORD*)&lpRasEntry->ipaddr) != 0 )
  456. {
  457. lpRasEntry->dwfOptions |= RASEO_SpecificIpAddr;
  458. }
  459. // Check ipaddrDns
  460. if ((*(DWORD*)&lpRasEntry->ipaddrDns) == 0 )
  461. {
  462. ChkErr( RasReadIpAddress(hPbkFile,
  463. lpRasEntryName->szEntryName,
  464. TEXT("IpDnsAddress"),
  465. &(lpRasEntry->ipaddrDns)) );
  466. }
  467. if ((*(DWORD*)&lpRasEntry->ipaddrDns) != 0 )
  468. {
  469. lpRasEntry->dwfOptions |= RASEO_SpecificNameServers;
  470. }
  471. // Check ipaddrDnsAlt
  472. if ((*(DWORD*)&lpRasEntry->ipaddrDnsAlt) == 0 )
  473. {
  474. ChkErr( RasReadIpAddress(hPbkFile,
  475. lpRasEntryName->szEntryName,
  476. TEXT("IpDns2Address"),
  477. &(lpRasEntry->ipaddrDnsAlt)) );
  478. }
  479. if ((*(DWORD*)&lpRasEntry->ipaddrDnsAlt) != 0 )
  480. {
  481. lpRasEntry->dwfOptions |= RASEO_SpecificNameServers;
  482. }
  483. // Check ipaddrWins
  484. if ((*(DWORD*)&lpRasEntry->ipaddrWins) == 0 )
  485. {
  486. ChkErr( RasReadIpAddress(hPbkFile,
  487. lpRasEntryName->szEntryName,
  488. TEXT("IpWinsAddress"),
  489. &(lpRasEntry->ipaddrWins)) );
  490. }
  491. if ((*(DWORD*)&lpRasEntry->ipaddrWins) != 0 )
  492. {
  493. lpRasEntry->dwfOptions |= RASEO_SpecificNameServers;
  494. }
  495. // Check ipaddrWinsAlt
  496. if ((*(DWORD*)&lpRasEntry->ipaddrWinsAlt) == 0 )
  497. {
  498. ChkErr( RasReadIpAddress(hPbkFile,
  499. lpRasEntryName->szEntryName,
  500. TEXT("IpWins2Address"),
  501. &(lpRasEntry->ipaddrWinsAlt)) );
  502. }
  503. if ((*(DWORD*)&lpRasEntry->ipaddrWinsAlt) != 0 )
  504. {
  505. lpRasEntry->dwfOptions |= RASEO_SpecificNameServers;
  506. }
  507. }
  508. ChkErr (Win32Printf(h, "\"%s\",", lpRasEntryName->szEntryName) );
  509. ChkErr (Win32Printf(h, "0x%0X,", lpRasEntry->dwfOptions ) );
  510. ChkErr (Win32Printf(h, "%d,", lpRasEntry->dwCountryID ) );
  511. ChkErr (Win32Printf(h, "%d,", lpRasEntry->dwCountryCode ) );
  512. ChkErr (Win32Printf(h, "\"%s\",", lpRasEntry->szAreaCode ) );
  513. ChkErr (Win32Printf(h, "\"%s\",", lpRasEntry->szLocalPhoneNumber) );
  514. ChkErr (Win32Printf(h, "%d,", 0) ); // lpRasEntry->dwAlternateOffset
  515. ChkErr (Win32Printf(h, "0x%08X,", lpRasEntry->ipaddr ) );
  516. ChkErr (Win32Printf(h, "0x%08X,", lpRasEntry->ipaddrDns ) );
  517. ChkErr (Win32Printf(h, "0x%08X,", lpRasEntry->ipaddrDnsAlt) );
  518. ChkErr (Win32Printf(h, "0x%08X,", lpRasEntry->ipaddrWins ) );
  519. ChkErr (Win32Printf(h, "0x%08X,", lpRasEntry->ipaddrWinsAlt) );
  520. ChkErr (Win32Printf(h, "%d,", lpRasEntry->dwFrameSize ) );
  521. ChkErr (Win32Printf(h, "%d,", lpRasEntry->dwfNetProtocols ) );
  522. ChkErr (Win32Printf(h, "%d,", lpRasEntry->dwFramingProtocol) );
  523. ChkErr (Win32Printf(h, "\"%s\",", lpRasEntry->szScript ) );
  524. ChkErr (Win32Printf(h, "\"%s\",", lpRasEntry->szAutodialDll ) );
  525. ChkErr (Win32Printf(h, "\"%s\",", lpRasEntry->szAutodialFunc ) );
  526. ChkErr (Win32Printf(h, "\"%s\",", lpRasEntry->szDeviceType ) );
  527. ChkErr (Win32Printf(h, "\"%s\",", lpRasEntry->szDeviceName ) );
  528. ChkErr (Win32Printf(h, "\"%s\",", lpRasEntry->szX25PadType ) );
  529. ChkErr (Win32Printf(h, "\"%s\",", lpRasEntry->szX25Address ) );
  530. ChkErr (Win32Printf(h, "\"%s\",", lpRasEntry->szX25Facilities ) );
  531. ChkErr (Win32Printf(h, "\"%s\",", lpRasEntry->szX25UserData ) );
  532. ChkErr (Win32Printf(h, "%d,", lpRasEntry->dwChannels ) );
  533. ZeroMemory( &RasDialParams, sizeof(RASDIALPARAMSA) );
  534. lstrcpyA( RasDialParams.szEntryName, lpRasEntryName->szEntryName);
  535. RasDialParams.dwSize = sizeof(RASDIALPARAMSA);
  536. dwErr = GRasGetEntryDialParams( lpPbkFileName,
  537. &RasDialParams,
  538. &bPasswordRead );
  539. if ( dwErr != ERROR_SUCCESS )
  540. {
  541. Win32PrintfResource (LogFile, IDS_RAS_ENTRY_NOT_MIGRATED, lpRasEntryName->szEntryName);
  542. if (DebugOutput)
  543. {
  544. Win32Printf(LogFile, "RasGetDialParams: Error %d\n", dwErr );
  545. }
  546. goto Err;
  547. }
  548. ChkErr (Win32Printf(h, "%s,", RasDialParams.szPhoneNumber ) );
  549. ChkErr (Win32Printf(h, "%s,", RasDialParams.szCallbackNumber ) );
  550. ChkErr (Win32Printf(h, "%s,", RasDialParams.szUserName ) );
  551. ChkErr (Win32Printf(h, "%s,", RasDialParams.szPassword ) );
  552. ChkErr (Win32Printf(h, "%s\r\n", RasDialParams.szDomain) );
  553. lpRasEntryName++;
  554. }
  555. Err:
  556. if (hPbkFile != INVALID_HANDLE_VALUE)
  557. SetupCloseInfFile(hPbkFile);
  558. Win32Printf(h, "\r\n" );
  559. if (lpRasEntry != NULL)
  560. free (lpRasEntry);
  561. if (lpRasEntryName != NULL)
  562. GlobalFree (lpRasEntryName);
  563. return dwErr;
  564. }
  565. DWORD ScanRasPerPhonebook (HANDLE h)
  566. {
  567. DWORD dwErr = ERROR_SUCCESS;
  568. CHAR szValue[LINEBUFSIZE];
  569. CHAR szPbkFileName[MAX_PATH];
  570. TCHAR szWinDir[MAX_PATH];
  571. if (Win9x)
  572. {
  573. // System phonebook
  574. dwErr = ScanRasPhonebook( h, NULL );
  575. if (ERROR_CANNOT_OPEN_PHONEBOOK == dwErr)
  576. {
  577. // 9x stores Ras in the registry. If it can't find the registry,
  578. // assume there are no Ras connections that need migrating.
  579. dwErr = ERROR_SUCCESS;
  580. }
  581. }
  582. else
  583. {
  584. // Scan system pbk
  585. dwErr = GetWindowsDirectory(szWinDir, MAX_PATH );
  586. if (dwErr <= 0 || dwErr > MAX_PATH)
  587. {
  588. if (Verbose)
  589. {
  590. Win32Printf(LogFile,
  591. "Error: Could not retrieve Windows directory: %d\r\n",
  592. dwErr);
  593. }
  594. goto Err;
  595. }
  596. if ( (_tcslen(szWinDir) +
  597. _tcslen(RAS_NT4_RAS_PATH) +
  598. _tcslen(RAS_NT4_SYSTEM_PHONEBOOK) + 3) > MAX_PATH )
  599. {
  600. Win32PrintfResource(LogFile,
  601. IDS_FILENAME_TOOLONG,
  602. RAS_NT4_SYSTEM_PHONEBOOK);
  603. if (Verbose)
  604. {
  605. Win32Printf(STDERR,
  606. "Error: Too Long Phonebook Filename: %s\\%s\\%s\r\n",
  607. szWinDir,
  608. RAS_NT4_RAS_PATH,
  609. RAS_NT4_SYSTEM_PHONEBOOK);
  610. }
  611. dwErr = ERROR_FILENAME_EXCED_RANGE;
  612. goto Err;
  613. }
  614. sprintf( szPbkFileName, "%s\\%s\\%s",
  615. szWinDir, RAS_NT4_RAS_PATH, RAS_NT4_SYSTEM_PHONEBOOK );
  616. // Make sure the file exists
  617. dwErr = GetFileAttributes(szPbkFileName);
  618. if (-1 == dwErr)
  619. {
  620. dwErr = GetLastError();
  621. if (dwErr == ERROR_FILE_NOT_FOUND ||
  622. dwErr == ERROR_PATH_NOT_FOUND)
  623. {
  624. // This phonebook file doesn't exist, which is fine. Just skip it.
  625. dwErr = ERROR_SUCCESS;
  626. }
  627. else
  628. {
  629. goto Err;
  630. }
  631. }
  632. else
  633. {
  634. ChkErr( ScanRasPhonebook( h, szPbkFileName ) );
  635. }
  636. // Scan personal pbk
  637. dwErr = ScanReadKey (HKEY_CURRENT_USER,
  638. (CHAR*) REGKEY_NT4_PBK,
  639. (CHAR*) REGVAL_NT4_PRS_PBK_LOC,
  640. (CHAR*) szValue, sizeof(szValue));
  641. if ( dwErr == ERROR_SUCCESS && szValue[0] != '\0')
  642. {
  643. if ( (_tcslen(szWinDir) +
  644. _tcslen(RAS_NT4_RAS_PATH) +
  645. _tcslen(szValue) + 3) > MAX_PATH )
  646. {
  647. Win32PrintfResource(LogFile,
  648. IDS_FILENAME_TOOLONG,
  649. szValue);
  650. if (Verbose)
  651. {
  652. Win32Printf(STDERR,
  653. "Error: Too Long Phonebook Filename: %s\\%s\\%s\r\n",
  654. szWinDir,
  655. RAS_NT4_RAS_PATH,
  656. szValue);
  657. }
  658. dwErr = ERROR_FILENAME_EXCED_RANGE;
  659. goto Err;
  660. }
  661. sprintf( szPbkFileName, "%s\\%s\\%s", szWinDir, RAS_NT4_RAS_PATH, szValue );
  662. // Make sure the file exists
  663. dwErr = GetFileAttributes(szPbkFileName);
  664. if (-1 == dwErr)
  665. {
  666. dwErr = GetLastError();
  667. if (dwErr == ERROR_FILE_NOT_FOUND ||
  668. dwErr == ERROR_PATH_NOT_FOUND)
  669. {
  670. // This phonebook file doesn't exist. Just skip it
  671. dwErr = ERROR_SUCCESS;
  672. }
  673. else
  674. {
  675. goto Err;
  676. }
  677. }
  678. else
  679. {
  680. ChkErr( ScanRasPhonebook( h, szPbkFileName ) );
  681. }
  682. }
  683. else if (dwErr == ERROR_FILE_NOT_FOUND)
  684. {
  685. // Just because there is no personal pbk defined in the registry doesn't
  686. // mean there was a fatal error. Just skip it and move on with life.
  687. dwErr = ERROR_SUCCESS;
  688. }
  689. else if (dwErr != ERROR_SUCCESS)
  690. {
  691. if (DebugOutput)
  692. {
  693. Win32Printf(LogFile, "ScanReadKey for personal PBK returned %d\r\n", dwErr);
  694. }
  695. goto Err;
  696. }
  697. // Scan alternate pbk
  698. dwErr = ScanReadKey (HKEY_CURRENT_USER,
  699. (CHAR*) REGKEY_NT4_PBK,
  700. (CHAR*) REGVAL_NT4_ALT_PBK_LOC,
  701. (CHAR*) szValue, sizeof(szValue));
  702. if ( dwErr == ERROR_SUCCESS && szValue[0] != '\0')
  703. {
  704. // Make sure the file exists
  705. dwErr = GetFileAttributes(szValue);
  706. if (-1 == dwErr)
  707. {
  708. dwErr = GetLastError();
  709. if (dwErr == ERROR_FILE_NOT_FOUND ||
  710. dwErr == ERROR_PATH_NOT_FOUND)
  711. {
  712. // This phonebook file doesn't exist. Just skip it.
  713. dwErr = ERROR_SUCCESS;
  714. }
  715. else
  716. {
  717. return dwErr;
  718. }
  719. }
  720. else
  721. {
  722. ChkErr( ScanRasPhonebook( h, szValue ) );
  723. }
  724. }
  725. else if (dwErr == ERROR_FILE_NOT_FOUND)
  726. {
  727. // Just because there is no alternate pbk defined in the registry doesn't
  728. // mean there was a fatal error. Just skip it and move on with life.
  729. dwErr = ERROR_SUCCESS;
  730. }
  731. else if ( dwErr != ERROR_SUCCESS )
  732. {
  733. if (DebugOutput)
  734. {
  735. Win32Printf(LogFile, "ScanReadKey for alternate pbk returned: %d\r\n", dwErr);
  736. }
  737. goto Err;
  738. }
  739. }
  740. Err:
  741. return dwErr;
  742. }
  743. //+---------------------------------------------------------------------------
  744. //
  745. // Function: ScanRasSettings
  746. //
  747. // Synopsis: scans RAS settings for current user
  748. //
  749. // Arguments:
  750. //
  751. // Returns: Appropriate status code
  752. //
  753. // History: 20-Sep-99 HenryLee Created
  754. //
  755. //----------------------------------------------------------------------------
  756. DWORD ScanRasSettings (HANDLE h)
  757. {
  758. DWORD dwErr = ERROR_SUCCESS;
  759. if (IsRasInstalled())
  760. {
  761. ChkErr (Win32Printf (h, (CHAR *) RAS));
  762. ChkErr (ScanRasPerPhonebook (h));
  763. }
  764. Err:
  765. return dwErr;
  766. }
  767. //+---------------------------------------------------------------------------
  768. //
  769. // Function: ScanEnumerateShares
  770. //
  771. // Synopsis: lists public (non-system) network shares
  772. //
  773. // Arguments:
  774. //
  775. // Returns: Appropriate status code
  776. //
  777. // History: 20-Sep-99 HenryLee Created
  778. //
  779. //----------------------------------------------------------------------------
  780. DWORD ScanEnumerateShares (HANDLE h)
  781. {
  782. short nLevel = (short) (Win9x ? 50 : 502);
  783. DWORD dwErr = ERROR_SUCCESS;
  784. const int MAX_ENTRIES = 64;
  785. ScanNetShareEnumNT pNetShareEnum = NULL;
  786. ScanNetShareEnum9x pNetShareEnum9x = NULL;
  787. ScanNetAccessEnum9x pNetAccessEnum9x = NULL;
  788. HINSTANCE hInst = LoadLibraryA (Win9x ? "svrapi.dll" : "netapi32.dll");
  789. if (hInst == 0)
  790. {
  791. ChkErr (ERROR_INVALID_DLL);
  792. }
  793. ChkErr (Win32Printf (h, (CHAR *) SHARES));
  794. if (Win9x)
  795. {
  796. USHORT cbBuffer;
  797. USHORT nEntriesRead = 0;
  798. USHORT nTotalEntries = 0;
  799. USHORT i;
  800. static _share_info_50 pBuf[MAX_ENTRIES];
  801. _share_info_50* pTmpBuf = NULL;
  802. cbBuffer = MAX_ENTRIES * sizeof(_share_info_50);
  803. pNetShareEnum9x = (ScanNetShareEnum9x) GetProcAddress (hInst,
  804. "NetShareEnum");
  805. if (pNetShareEnum9x == NULL)
  806. {
  807. ChkErr (ERROR_INVALID_DLL);
  808. }
  809. pNetAccessEnum9x = (ScanNetAccessEnum9x) GetProcAddress (hInst,
  810. "NetAccessEnum");
  811. if (pNetAccessEnum9x == NULL)
  812. {
  813. ChkErr (ERROR_INVALID_DLL);
  814. }
  815. //
  816. // Call the NetShareEnum function to list the
  817. // shares, specifying information level 50.
  818. //
  819. dwErr = (*pNetShareEnum9x)(NULL,
  820. (short) nLevel,
  821. (char *) pBuf,
  822. cbBuffer,
  823. &nEntriesRead,
  824. &nTotalEntries);
  825. if (dwErr == ERROR_SUCCESS)
  826. {
  827. if (nTotalEntries > 0 && nEntriesRead != nTotalEntries)
  828. ChkErr (ERROR_MORE_DATA);
  829. for (i = 0; i < nEntriesRead; i++)
  830. {
  831. DWORD dwPerms = 0;
  832. pTmpBuf = &pBuf[i];
  833. // Require share to be a user-defined, persistent disk share
  834. if ((pTmpBuf->shi50_flags & SHI50F_SYSTEM) ||
  835. !(pTmpBuf->shi50_flags & SHI50F_PERSIST) ||
  836. pTmpBuf->shi50_type != STYPE_DISKTREE )
  837. {
  838. continue;
  839. }
  840. if (pTmpBuf->shi50_flags & SHI50F_RDONLY)
  841. dwPerms = ACCESS_READ;
  842. else if (pTmpBuf->shi50_flags & SHI50F_FULL)
  843. dwPerms = ACCESS_ALL;
  844. //
  845. // Display the information for each entry retrieved.
  846. //
  847. ChkErr (Win32Printf (h, "%s, %s, %d, %s\r\n",
  848. pTmpBuf->shi50_netname, pTmpBuf->shi50_path,
  849. dwPerms, pTmpBuf->shi50_remark));
  850. //
  851. // Process custom access permissions
  852. //
  853. if ((pTmpBuf->shi50_flags & SHI50F_ACCESSMASK) ==
  854. SHI50F_ACCESSMASK)
  855. {
  856. static CHAR AccessInfoBuf[16384];
  857. WORD wItemsAvail, wItemsRead;
  858. access_info_2 *pai;
  859. access_list_2 *pal;
  860. dwErr = (*pNetAccessEnum9x) (NULL,
  861. pTmpBuf->shi50_path,
  862. 0,
  863. 2,
  864. AccessInfoBuf,
  865. sizeof (AccessInfoBuf),
  866. &wItemsRead,
  867. &wItemsAvail
  868. );
  869. if (dwErr != NERR_ACFNotLoaded)
  870. {
  871. BOOL LostCustomAccess = FALSE;
  872. if (dwErr == ERROR_SUCCESS)
  873. {
  874. pai = (access_info_2 *) AccessInfoBuf;
  875. pal = (access_list_2 *) (&pai[1]);
  876. for (int i = 0 ; i < pai->acc2_count ; i++)
  877. {
  878. #if 0
  879. // turn off custom access support
  880. // implementation is incomplete
  881. if (pal->acl2_access & READ_ACCESS_FLAGS)
  882. Win32Printf (h, " %s, read\r\n",
  883. pal->acl2_ugname);
  884. else if(pal->acl2_access & FULL_ACCESS_FLAGS)
  885. Win32Printf (h, " %s, full\r\n",
  886. pal->acl2_ugname);
  887. else
  888. #endif
  889. LostCustomAccess = TRUE;
  890. pal++;
  891. }
  892. if (LostCustomAccess)
  893. Win32Printf (LogFile, "Warning custom access"
  894. " not migrated %s\r\n",
  895. pTmpBuf->shi50_netname);
  896. pTmpBuf->shi50_flags |= SHI50F_ACLS;
  897. }
  898. else ChkErr (dwErr);
  899. }
  900. }
  901. if (!(pTmpBuf->shi50_flags & SHI50F_ACLS) &&
  902. (pTmpBuf->shi50_rw_password[0] ||
  903. pTmpBuf->shi50_ro_password[0]))
  904. {
  905. Win32PrintfResource (LogFile,
  906. IDS_SHARE_PASSWORD_NOT_MIGRATED,
  907. pTmpBuf->shi50_netname);
  908. }
  909. }
  910. }
  911. else if (dwErr == NERR_ServerNotStarted)
  912. {
  913. dwErr = ERROR_SUCCESS;
  914. }
  915. }
  916. else
  917. {
  918. ULONG cbBuffer = MAX_ENTRIES * sizeof(SHARE_INFO_502);
  919. ULONG nEntriesRead = 0;
  920. ULONG nTotalEntries = 0;
  921. ULONG i;
  922. SHARE_INFO_502* pBuf = NULL;
  923. SHARE_INFO_502* pTmpBuf = NULL;
  924. pNetShareEnum = (ScanNetShareEnumNT) GetProcAddress(hInst,
  925. "NetShareEnum");
  926. if (pNetShareEnum == NULL)
  927. {
  928. ChkErr (ERROR_INVALID_DLL);
  929. }
  930. //
  931. // Call the NetShareEnum function to list the
  932. // shares, specifying information level 502.
  933. //
  934. dwErr = (*pNetShareEnum)(NULL,
  935. nLevel,
  936. (BYTE **) &pBuf,
  937. cbBuffer,
  938. &nEntriesRead,
  939. &nTotalEntries,
  940. NULL);
  941. //
  942. // Loop through the entries; process errors.
  943. //
  944. if (dwErr == ERROR_SUCCESS)
  945. {
  946. if ((pTmpBuf = pBuf) != NULL)
  947. {
  948. for (i = 0; (i < nEntriesRead); i++)
  949. {
  950. //
  951. // Display the information for each entry retrieved.
  952. //
  953. ChkErr (Win32Printf (h, "%ws, %ws, %d, %ws\r\n",
  954. pTmpBuf->shi502_netname, pTmpBuf->shi502_path,
  955. pTmpBuf->shi502_permissions, pTmpBuf->shi502_remark));
  956. pTmpBuf++;
  957. }
  958. }
  959. }
  960. else
  961. {
  962. Win32PrintfResource (LogFile, IDS_CANNOT_ENUM_NETSHARES);
  963. LogFormatError (dwErr);
  964. dwErr = ERROR_SUCCESS; // continue with other settings
  965. }
  966. if (pBuf != NULL)
  967. {
  968. ScanNetApiBufferFreeNT pNetApiBufferFree = NULL;
  969. pNetApiBufferFree = (ScanNetApiBufferFreeNT) GetProcAddress (hInst,
  970. "NetApiBufferFree");
  971. if (pNetApiBufferFree != NULL)
  972. (*pNetApiBufferFree) (pBuf);
  973. }
  974. }
  975. Err:
  976. if (Verbose && dwErr != ERROR_SUCCESS)
  977. Win32Printf (LogFile, "Out ScanEnumerateShares => 0x%x\r\n", dwErr);
  978. return dwErr;
  979. }
  980. //+---------------------------------------------------------------------------
  981. //
  982. // Function: ScanEnumeratePrinters
  983. //
  984. // Synopsis: list connected printers
  985. //
  986. // Arguments:
  987. //
  988. // Returns: Appropriate status code
  989. //
  990. // History: 20-Sep-99 HenryLee Created
  991. //
  992. //----------------------------------------------------------------------------
  993. DWORD ScanEnumeratePrinters (HANDLE h)
  994. {
  995. DWORD dwErr;
  996. DWORD cbBuffer = 16384; // 16K is a good size
  997. DWORD cbReceived;
  998. DWORD nPrinters;
  999. DWORD i;
  1000. PRINTER_INFO_2 *pPrinterEnum;
  1001. for(i = 0; i < 2; i++)
  1002. {
  1003. dwErr = ERROR_SUCCESS;
  1004. pPrinterEnum = (PRINTER_INFO_2 *) GlobalAlloc(GPTR, cbBuffer);
  1005. if (pPrinterEnum == NULL)
  1006. ChkErr (ERROR_NOT_ENOUGH_MEMORY);
  1007. if (FALSE == EnumPrintersA (Win9x ? PRINTER_ENUM_LOCAL :
  1008. PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS,
  1009. NULL,
  1010. 2,
  1011. (BYTE *) pPrinterEnum,
  1012. cbBuffer,
  1013. &cbReceived,
  1014. &nPrinters))
  1015. {
  1016. dwErr = GetLastError();
  1017. if (RPC_S_SERVER_UNAVAILABLE == dwErr)
  1018. {
  1019. // If the print spooler is turned off, then
  1020. // assume there are no printers to migrate
  1021. dwErr = ERROR_SUCCESS;
  1022. goto Err;
  1023. }
  1024. if( dwErr == ERROR_INSUFFICIENT_BUFFER || dwErr == ERROR_MORE_DATA )
  1025. {
  1026. GlobalFree(pPrinterEnum);
  1027. cbBuffer = cbReceived;
  1028. // Try again.
  1029. continue;
  1030. }
  1031. }
  1032. // Success, or some other error besides buffer to small.. so bail.
  1033. break;
  1034. }
  1035. ChkErr (dwErr);
  1036. ChkErr (Win32Printf (h, (CHAR *) PRINTERS));
  1037. for (i=0; i < nPrinters; i++)
  1038. {
  1039. if (Win9x)
  1040. {
  1041. ChkErr (Win32Printf(h, "%s\r\n", pPrinterEnum[i].pPortName));
  1042. }
  1043. else
  1044. {
  1045. ChkErr (Win32Printf(h, "%s\r\n", pPrinterEnum[i].pPrinterName));
  1046. }
  1047. }
  1048. Err:
  1049. if (pPrinterEnum != NULL)
  1050. GlobalFree (pPrinterEnum);
  1051. if (Verbose && dwErr != ERROR_SUCCESS)
  1052. Win32Printf (LogFile, "Out ScanEnumeratePrinters => 0x%x\r\n", dwErr);
  1053. return dwErr;
  1054. }
  1055. //+---------------------------------------------------------------------------
  1056. //
  1057. // Function: ScanEnumerateNetResources
  1058. //
  1059. // Synopsis: lists connected remote drives and resources
  1060. //
  1061. // Arguments:
  1062. //
  1063. // Returns: Appropriate status code
  1064. //
  1065. // History: 20-Sep-99 HenryLee Created
  1066. //
  1067. //----------------------------------------------------------------------------
  1068. DWORD ScanEnumerateNetResources (HANDLE h, DWORD dwScope, NETRESOURCEA *lpnr)
  1069. {
  1070. DWORD dwErr, dwResultEnum;
  1071. HANDLE hEnum;
  1072. DWORD cbBuffer = 16384; // 16K is a good size
  1073. DWORD cEntries = 0xFFFFFFFF; // enumerate all possible entries
  1074. LPNETRESOURCEA lpnrLocal; // pointer to enumerated structures
  1075. DWORD i;
  1076. dwErr = WNetOpenEnumA(dwScope,
  1077. RESOURCETYPE_ANY,
  1078. 0, // enumerate all resources
  1079. lpnr, // NULL first time this function is called
  1080. &hEnum); // handle to resource
  1081. if (dwErr != NO_ERROR)
  1082. {
  1083. // An application-defined error handler is demonstrated in the
  1084. // section titled "Retrieving Network Errors."
  1085. return dwErr;
  1086. }
  1087. lpnrLocal = (LPNETRESOURCEA) GlobalAlloc(GPTR, cbBuffer);
  1088. if (lpnrLocal == NULL)
  1089. ChkErr (ERROR_NOT_ENOUGH_MEMORY);
  1090. do
  1091. {
  1092. ZeroMemory(lpnrLocal, cbBuffer);
  1093. dwResultEnum = WNetEnumResourceA (hEnum, // resource handle
  1094. &cEntries, // defined locally as 0xFFFFFFFF
  1095. lpnrLocal, // LPNETRESOURCE
  1096. &cbBuffer); // buffer size
  1097. if (dwResultEnum == NO_ERROR)
  1098. {
  1099. for(i = 0; i < cEntries; i++)
  1100. {
  1101. // Following is an application-defined function for
  1102. // displaying contents of NETRESOURCE structures.
  1103. if (lpnrLocal[i].lpLocalName != NULL)
  1104. {
  1105. ChkErr (Win32Printf (h, "%s, %s, %s\r\n", lpnrLocal[i].lpLocalName,
  1106. lpnrLocal[i].lpRemoteName == NULL ? "" : lpnrLocal[i].lpRemoteName,
  1107. lpnrLocal[i].dwScope == RESOURCE_REMEMBERED ? "persist" : ""));
  1108. }
  1109. #if 0
  1110. // If this NETRESOURCE is a container, call the function
  1111. // recursively.
  1112. // Looking at the docs, it appears that the dwUsage is only applicable for
  1113. // GLOBALNET enumerations, and not for CONNECTED enumerations. We shouldn't
  1114. // have to worry about recursively finding resources, because all we care
  1115. // about is what is currently connected. This was a problem for Netware
  1116. // shares, in which case it recursively found itself until it aborted or AV'd.
  1117. if(RESOURCEUSAGE_CONTAINER == (lpnrLocal[i].dwUsage
  1118. & RESOURCEUSAGE_CONTAINER))
  1119. if((dwErr = ScanEnumerateNetResources (h, dwScope, &lpnrLocal[i])) !=
  1120. ERROR_SUCCESS)
  1121. return dwErr;
  1122. #endif
  1123. }
  1124. }
  1125. }
  1126. while(dwResultEnum != ERROR_NO_MORE_ITEMS);
  1127. if (lpnrLocal != NULL)
  1128. GlobalFree((HGLOBAL)lpnrLocal);
  1129. dwErr = WNetCloseEnum(hEnum);
  1130. Err:
  1131. return dwErr;
  1132. }
  1133. //+---------------------------------------------------------------------------
  1134. //
  1135. // Function: ScanReadKey
  1136. //
  1137. // Synopsis: retrieves a string or blob from the registry
  1138. //
  1139. // Arguments:
  1140. //
  1141. // Returns: Appropriate status code
  1142. //
  1143. // History: 20-Sep-99 HenryLee Created
  1144. //
  1145. //----------------------------------------------------------------------------
  1146. DWORD ScanReadKey (HKEY hKeyStart,
  1147. CHAR *szKey,
  1148. CHAR *szName,
  1149. CHAR *szValue,
  1150. ULONG ulLen)
  1151. {
  1152. HKEY hKey = NULL;
  1153. DWORD dwErr = ERROR_SUCCESS;
  1154. ChkErr (RegOpenKeyExA(hKeyStart, szKey, NULL, KEY_READ, &hKey));
  1155. ChkErr (RegQueryValueExA(hKey, szName, NULL, NULL,(BYTE*)szValue, &ulLen));
  1156. Err:
  1157. if (hKey != NULL)
  1158. RegCloseKey (hKey);
  1159. return dwErr;
  1160. }
  1161. //+---------------------------------------------------------------------------
  1162. //
  1163. // Function: ScanGetTimeZone
  1164. //
  1165. // Synopsis: retrieves the time zone name
  1166. //
  1167. // Arguments:
  1168. //
  1169. // Returns: Appropriate status code
  1170. //
  1171. // History: 20-Sep-99 HenryLee Created
  1172. //
  1173. //----------------------------------------------------------------------------
  1174. DWORD ScanGetTimeZone (HANDLE h)
  1175. {
  1176. CHAR szValue[LINEBUFSIZE];
  1177. DWORD dwErr = ERROR_SUCCESS;
  1178. if (ERROR_SUCCESS == ScanReadKey (HKEY_LOCAL_MACHINE,
  1179. (CHAR*) REGKEY_TIMEZONE,
  1180. (CHAR*) REGVAL_TIMEZONE,
  1181. (CHAR*) szValue, sizeof(szValue)))
  1182. {
  1183. dwErr = Win32Printf (h, "%s=%s\r\n", TIMEZONE, szValue);
  1184. }
  1185. return dwErr;
  1186. }
  1187. //+---------------------------------------------------------------------------
  1188. //
  1189. // Function: ScanGetComputerName
  1190. //
  1191. // Synopsis: retrieves the current NETBIOS machine name
  1192. //
  1193. // Arguments:
  1194. //
  1195. // Returns: Appropriate status code
  1196. //
  1197. // History: 20-Sep-99 HenryLee Created
  1198. //
  1199. //----------------------------------------------------------------------------
  1200. #if 0 // currently not used, but may be needed in the future
  1201. DWORD ScanGetComputerName (CHAR *szValue, ULONG ulLen)
  1202. {
  1203. if (FALSE == GetComputerNameA(szValue, &ulLen))
  1204. return GetLastError();
  1205. return ERROR_SUCCESS;
  1206. }
  1207. #endif
  1208. //+---------------------------------------------------------------------------
  1209. //
  1210. // Function: ScanGetFullName
  1211. //
  1212. // Synopsis: retrieves the registered name
  1213. //
  1214. // Arguments:
  1215. //
  1216. // Returns: Appropriate status code
  1217. //
  1218. // History: 20-Sep-99 HenryLee Created
  1219. //
  1220. //----------------------------------------------------------------------------
  1221. DWORD ScanGetFullName (HANDLE h)
  1222. {
  1223. CHAR szValue[LINEBUFSIZE];
  1224. DWORD dwErr = ERROR_SUCCESS;
  1225. if (ERROR_SUCCESS == ScanReadKey (HKEY_LOCAL_MACHINE,
  1226. Win9x ? (CHAR*)REGKEY_VERSION_9x :(CHAR*)REGKEY_VERSION,
  1227. (CHAR*) REGVAL_FULLNAME, szValue, sizeof(szValue)))
  1228. {
  1229. dwErr = Win32Printf (h, "%s=%s\r\n", FULLNAME, szValue);
  1230. }
  1231. return dwErr;
  1232. }
  1233. //+---------------------------------------------------------------------------
  1234. //
  1235. // Function: ScanGetOrgName
  1236. //
  1237. // Synopsis: retrieves the organization name
  1238. //
  1239. // Arguments:
  1240. //
  1241. // Returns: Appropriate status code
  1242. //
  1243. // History: 20-Sep-99 HenryLee Created
  1244. //
  1245. //----------------------------------------------------------------------------
  1246. DWORD ScanGetOrgName (HANDLE h)
  1247. {
  1248. CHAR szValue[LINEBUFSIZE];
  1249. DWORD dwErr = ERROR_SUCCESS;
  1250. if (ERROR_SUCCESS == ScanReadKey (HKEY_LOCAL_MACHINE,
  1251. Win9x ? (CHAR*)REGKEY_VERSION_9x :(CHAR*)REGKEY_VERSION,
  1252. (CHAR*)REGVAL_ORGNAME, szValue, sizeof(szValue)))
  1253. {
  1254. dwErr = Win32Printf (h, "%s=%s\r\n", ORGNAME, szValue);
  1255. }
  1256. return dwErr;
  1257. }
  1258. //
  1259. // IsLanguageMatched : if source and target language are matched (or compatible)
  1260. //
  1261. // 1. if SourceNativeLangID == TargetNativeLangID
  1262. //
  1263. // 2. if SourceNativeLangID's alternative ID == TargetNative LangID
  1264. //
  1265. typedef struct _tagLANGINFO {
  1266. LANGID LangID;
  1267. INT Count;
  1268. } LANGINFO,*PLANGINFO;
  1269. //+---------------------------------------------------------------------------
  1270. //
  1271. // Function: EnumLangProc
  1272. //
  1273. // Synopsis: callback to pull out the langid while enumerating
  1274. //
  1275. // Arguments:
  1276. //
  1277. // Returns: bool to continue to stop enumeration
  1278. //
  1279. // History: 20-Sep-99 HenryLee Created
  1280. //
  1281. //----------------------------------------------------------------------------
  1282. BOOL CALLBACK EnumLangProc(
  1283. HANDLE hModule, // resource-module handle
  1284. LPCTSTR lpszType, // pointer to resource type
  1285. LPCTSTR lpszName, // pointer to resource name
  1286. WORD wIDLanguage, // resource language identifier
  1287. LONG_PTR lParam // application-defined parameter
  1288. )
  1289. {
  1290. PLANGINFO LangInfo;
  1291. LangInfo = (PLANGINFO) lParam;
  1292. LangInfo->Count++;
  1293. //
  1294. // for localized build contains multiple resource,
  1295. // it usually contains 0409 as backup lang.
  1296. //
  1297. // if LangInfo->LangID != 0 means we already assigned an ID to it
  1298. //
  1299. // so when wIDLanguage == 0x409, we keep the one we got from last time
  1300. //
  1301. if ((wIDLanguage == 0x409) && (LangInfo->LangID != 0)) {
  1302. return TRUE;
  1303. }
  1304. LangInfo->LangID = wIDLanguage;
  1305. return TRUE; // continue enumeration
  1306. }
  1307. //+---------------------------------------------------------------------------
  1308. //
  1309. // Function: GetNTDLLNativeLangID
  1310. //
  1311. // Synopsis: pull the language id from ntdll for NT systems only
  1312. //
  1313. // Arguments:
  1314. //
  1315. // Returns: Native lang ID in ntdll.dll
  1316. //
  1317. // History: 20-Sep-99 HenryLee Created
  1318. //
  1319. //----------------------------------------------------------------------------
  1320. LANGID GetNTDLLNativeLangID()
  1321. {
  1322. LPCTSTR Type = (LPCTSTR) RT_VERSION;
  1323. LPCTSTR Name = (LPCTSTR) 1;
  1324. LANGINFO LangInfo;
  1325. ZeroMemory(&LangInfo,sizeof(LangInfo));
  1326. EnumResourceLanguages(
  1327. GetModuleHandle(TEXT("ntdll.dll")),
  1328. Type,
  1329. Name,
  1330. (ENUMRESLANGPROC) EnumLangProc,
  1331. (LONG_PTR) &LangInfo
  1332. );
  1333. return LangInfo.LangID;
  1334. }
  1335. //+---------------------------------------------------------------------------
  1336. //
  1337. // Function: IsHongKongVersion
  1338. //
  1339. // Synopsis: identifies HongKong NT 4.0 (English UI w/ Chinese locale)
  1340. //
  1341. // Arguments:
  1342. //
  1343. // Returns: TRUE/FALSE
  1344. //
  1345. // History: 20-Sep-99 HenryLee Created
  1346. //
  1347. //----------------------------------------------------------------------------
  1348. BOOL IsHongKongVersion()
  1349. {
  1350. HMODULE hMod;
  1351. BOOL bRet = FALSE;
  1352. typedef BOOL (*IMMRELEASECONTEXT) (HWND,HANDLE);
  1353. IMMRELEASECONTEXT pImmReleaseContext;
  1354. LANGID TmpID = GetNTDLLNativeLangID();
  1355. if (((GetVersion() >> 16) == 1381) && (TmpID == 0x0409))
  1356. {
  1357. hMod = LoadLibrary(TEXT("imm32.dll"));
  1358. if (hMod)
  1359. {
  1360. pImmReleaseContext = (IMMRELEASECONTEXT)
  1361. GetProcAddress(hMod,"ImmReleaseContext");
  1362. if (pImmReleaseContext) {
  1363. bRet = pImmReleaseContext(NULL,NULL);
  1364. }
  1365. FreeLibrary(hMod);
  1366. }
  1367. }
  1368. return (bRet);
  1369. }
  1370. //+---------------------------------------------------------------------------
  1371. //
  1372. // Function: GetDefaultUserLangID
  1373. //
  1374. // Synopsis: retrieves the language of the OS
  1375. //
  1376. // Arguments:
  1377. //
  1378. // Returns: .DEFAULT user's LANGID
  1379. //
  1380. // History: 20-Sep-99 HenryLee Created
  1381. //
  1382. //----------------------------------------------------------------------------
  1383. LANGID GetDefaultUserLangID()
  1384. {
  1385. LONG dwErr;
  1386. HKEY hkey;
  1387. DWORD dwSize;
  1388. CHAR buffer[512];
  1389. LANGID langid = 0;
  1390. dwErr = RegOpenKeyEx( HKEY_USERS,
  1391. TEXT(".DEFAULT\\Control Panel\\International"),
  1392. 0,
  1393. KEY_READ,
  1394. &hkey );
  1395. if( dwErr == ERROR_SUCCESS )
  1396. {
  1397. dwSize = sizeof(buffer);
  1398. dwErr = RegQueryValueExA(hkey,
  1399. "Locale",
  1400. NULL, //reserved
  1401. NULL, //type
  1402. (BYTE *)buffer,
  1403. &dwSize );
  1404. if(dwErr == ERROR_SUCCESS)
  1405. {
  1406. langid = LANGIDFROMLCID(strtoul(buffer,NULL,16));
  1407. }
  1408. RegCloseKey(hkey);
  1409. }
  1410. return langid;
  1411. }
  1412. //+---------------------------------------------------------------------------
  1413. //
  1414. // Function: ScanGetLang
  1415. //
  1416. // Synopsis: retrieves the language of the OS
  1417. //
  1418. // Arguments: [pdwLang] -- output Language ID
  1419. //
  1420. // Returns: Appropriate status code
  1421. //
  1422. // History: 20-Sep-99 HenryLee Created
  1423. //
  1424. //----------------------------------------------------------------------------
  1425. DWORD ScanGetLang (DWORD *pdwLang)
  1426. {
  1427. HKEY hKey;
  1428. DWORD dwErr = ERROR_SUCCESS;
  1429. DWORD langid = 0;
  1430. DWORD dwSize;
  1431. BYTE buffer[LINEBUFSIZE];
  1432. if (Win9x)
  1433. {
  1434. dwErr = RegOpenKeyEx( HKEY_USERS,
  1435. TEXT(".Default\\Control Panel\\desktop\\ResourceLocale"),
  1436. 0, KEY_READ, &hKey );
  1437. if (dwErr == ERROR_SUCCESS)
  1438. {
  1439. dwSize = sizeof(buffer);
  1440. dwErr = RegQueryValueExA( hKey,
  1441. "",
  1442. NULL, //reserved
  1443. NULL, //type
  1444. buffer,
  1445. &dwSize );
  1446. if(dwErr == ERROR_SUCCESS)
  1447. {
  1448. langid = LANGIDFROMLCID(strtoul((CHAR*)buffer,NULL,16));
  1449. *pdwLang = langid;
  1450. }
  1451. RegCloseKey(hKey);
  1452. }
  1453. if ( dwErr != ERROR_SUCCESS )
  1454. {
  1455. dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1456. TEXT("System\\CurrentControlSet\\Control\\Nls\\Locale"),
  1457. 0, KEY_READ, &hKey );
  1458. if (dwErr == ERROR_SUCCESS)
  1459. {
  1460. dwSize = sizeof(buffer);
  1461. dwErr = RegQueryValueExA( hKey,
  1462. "",
  1463. NULL, //reserved
  1464. NULL, //type
  1465. buffer,
  1466. &dwSize );
  1467. if (dwErr == ERROR_SUCCESS)
  1468. {
  1469. langid = LANGIDFROMLCID(strtoul((CHAR*)buffer,NULL,16));
  1470. *pdwLang = langid;
  1471. }
  1472. RegCloseKey(hKey);
  1473. }
  1474. }
  1475. }
  1476. else
  1477. {
  1478. langid = GetNTDLLNativeLangID();
  1479. if (langid == 0x0409)
  1480. {
  1481. if (IsHongKongVersion()) // block Pan-Chinese upgrade to English
  1482. {
  1483. langid = 0x0C04; // map to Chinese (Hong Kong SAR)
  1484. }
  1485. }
  1486. *pdwLang = langid;
  1487. }
  1488. if (Verbose && dwErr != ERROR_SUCCESS)
  1489. Win32Printf (LogFile, "ScanGetLang %d, LangID=%x\n", dwErr, langid);
  1490. return dwErr;
  1491. }
  1492. #define ACCESS_KEY TEXT("Control Panel\\Accessibility\\")
  1493. //+---------------------------------------------------------------------------
  1494. //
  1495. // Function: ScanConvertFlags
  1496. //
  1497. // Synopsis: convert accessibility flags
  1498. //
  1499. // Arguments: [pcsObject] -- registry key name
  1500. // [pOptions] -- conversion table
  1501. // [dwForceValues] -- force these options to be on
  1502. //
  1503. // Returns: Appropriate status code
  1504. //
  1505. // History: 20-Sep-99 HenryLee Created
  1506. //
  1507. //----------------------------------------------------------------------------
  1508. DWORD ScanConvertFlags (HANDLE h,
  1509. TCHAR *pcsObject,
  1510. ACCESS_OPTION *pOptions,
  1511. DWORD dwForceValues)
  1512. {
  1513. HKEY hKey = NULL;
  1514. DWORD dwErr = ERROR_SUCCESS;
  1515. DWORD Flags;
  1516. DWORD dw;
  1517. BYTE *lpBuffer = NULL;
  1518. DWORD dwBufferSize = 0;
  1519. DWORD dwRequiredSize;
  1520. if (ERROR_SUCCESS == RegOpenKeyEx( HKEY_CURRENT_USER,
  1521. pcsObject, 0, KEY_READ, &hKey ))
  1522. {
  1523. //
  1524. // Get flag settings from Win95 registry and convert them to Flags
  1525. //
  1526. Flags = 0;
  1527. while (pOptions->ValueName)
  1528. {
  1529. // How big of a buffer do we need?
  1530. RegQueryValueEx(hKey, pOptions->ValueName, NULL, NULL, NULL, &dwRequiredSize);
  1531. if (dwRequiredSize > dwBufferSize)
  1532. {
  1533. if (lpBuffer == NULL)
  1534. {
  1535. lpBuffer = (BYTE *)malloc(dwRequiredSize * sizeof(BYTE));
  1536. }
  1537. else
  1538. {
  1539. lpBuffer = (BYTE *)realloc(lpBuffer, dwRequiredSize * sizeof(BYTE));
  1540. }
  1541. dwBufferSize = dwRequiredSize;
  1542. }
  1543. ZeroMemory(lpBuffer, dwBufferSize);
  1544. // Read value
  1545. if (ERROR_SUCCESS == RegQueryValueEx( hKey,
  1546. pOptions->ValueName,
  1547. NULL, //reserved
  1548. NULL, //type
  1549. lpBuffer,
  1550. &dwBufferSize ))
  1551. {
  1552. // Convert to int
  1553. dw = atoi((const char *)lpBuffer);
  1554. //
  1555. // Most flags are identical on Win9x and NT, but there's one
  1556. // MouseKey flag that needs to be inverted.
  1557. //
  1558. if (pOptions->FlagVal & SPECIAL_INVERT_OPTION)
  1559. {
  1560. if (dw == 0)
  1561. {
  1562. Flags |= (pOptions->FlagVal & (~SPECIAL_INVERT_OPTION));
  1563. }
  1564. }
  1565. else if (dw != 0)
  1566. {
  1567. Flags |= pOptions->FlagVal;
  1568. }
  1569. }
  1570. pOptions++;
  1571. }
  1572. Flags |= dwForceValues;
  1573. Win32Printf (h, "HKR, \"%s\", \"Flags\", 0x0, \"%d\"\r\n",
  1574. pcsObject, Flags);
  1575. RegCloseKey (hKey);
  1576. }
  1577. return dwErr;
  1578. }
  1579. //+---------------------------------------------------------------------------
  1580. //
  1581. // Function: ScanAccessibility
  1582. //
  1583. // Synopsis: convertes Accessibility settings
  1584. //
  1585. // Arguments:
  1586. //
  1587. // Returns: Appropriate status code
  1588. //
  1589. // History: 20-Sep-99 HenryLee Created
  1590. //
  1591. //----------------------------------------------------------------------------
  1592. DWORD ScanAccessibility (HANDLE h)
  1593. {
  1594. DWORD dwErr = ERROR_SUCCESS;
  1595. const TCHAR ACCESS_AVAILABLE[] = TEXT("Available");
  1596. const TCHAR ACCESS_CLICKON[] = TEXT("ClickOn");
  1597. const TCHAR ACCESS_CONFIRMHOTKEY[] = TEXT("ConfirmHotKey");
  1598. const TCHAR ACCESS_HOTKEYACTIVE[] = TEXT("HotKeyActive");
  1599. const TCHAR ACCESS_HOTKEYSOUND[] = TEXT("HotKeySound");
  1600. const TCHAR ACCESS_ON[] = TEXT("On");
  1601. const TCHAR ACCESS_ONOFFFEEDBACK[] = TEXT("OnOffFeedback");
  1602. const TCHAR ACCESS_SHOWSTATUSINDICATOR[]= TEXT("ShowStatusIndicator");
  1603. const TCHAR ACCESS_MODIFIERS[] = TEXT("Modifiers");
  1604. const TCHAR ACCESS_REPLACENUMBERS[] = TEXT("ReplaceNumbers");
  1605. const TCHAR ACCESS_AUDIBLEFEEDBACK[] = TEXT("AudibleFeedback");
  1606. const TCHAR ACCESS_TRISTATE[] = TEXT("TriState");
  1607. const TCHAR ACCESS_TWOKEYSOFF[] = TEXT("TwoKeysOff");
  1608. const TCHAR ACCESS_HOTKEYAVAILABLE[] = TEXT("HotKeyAvailable");
  1609. ACCESS_OPTION FilterKeys[] = {
  1610. ACCESS_ON, BASICS_ON,
  1611. ACCESS_AVAILABLE, BASICS_AVAILABLE,
  1612. ACCESS_HOTKEYACTIVE, BASICS_HOTKEYACTIVE,
  1613. ACCESS_CONFIRMHOTKEY, BASICS_CONFIRMHOTKEY,
  1614. ACCESS_HOTKEYSOUND, BASICS_HOTKEYSOUND,
  1615. ACCESS_SHOWSTATUSINDICATOR, BASICS_INDICATOR,
  1616. ACCESS_CLICKON, FKF_CLICKON,
  1617. NULL, 0
  1618. };
  1619. ACCESS_OPTION MouseKeys[] = {
  1620. ACCESS_ON, BASICS_ON,
  1621. ACCESS_AVAILABLE, BASICS_AVAILABLE,
  1622. ACCESS_HOTKEYACTIVE, BASICS_HOTKEYACTIVE,
  1623. ACCESS_CONFIRMHOTKEY, BASICS_CONFIRMHOTKEY,
  1624. ACCESS_HOTKEYSOUND, BASICS_HOTKEYSOUND,
  1625. ACCESS_SHOWSTATUSINDICATOR, BASICS_INDICATOR,
  1626. ACCESS_MODIFIERS, MKF_MODIFIERS|SPECIAL_INVERT_OPTION,
  1627. ACCESS_REPLACENUMBERS, MKF_REPLACENUMBERS,
  1628. NULL, 0
  1629. };
  1630. ACCESS_OPTION StickyKeys[] = {
  1631. ACCESS_ON, BASICS_ON,
  1632. ACCESS_AVAILABLE, BASICS_AVAILABLE,
  1633. ACCESS_HOTKEYACTIVE, BASICS_HOTKEYACTIVE,
  1634. ACCESS_CONFIRMHOTKEY, BASICS_CONFIRMHOTKEY,
  1635. ACCESS_HOTKEYSOUND, BASICS_HOTKEYSOUND,
  1636. ACCESS_SHOWSTATUSINDICATOR, BASICS_INDICATOR,
  1637. ACCESS_AUDIBLEFEEDBACK, SKF_AUDIBLEFEEDBACK,
  1638. ACCESS_TRISTATE, SKF_TRISTATE,
  1639. ACCESS_TWOKEYSOFF, SKF_TWOKEYSOFF,
  1640. NULL, 0
  1641. };
  1642. ACCESS_OPTION SoundSentry[] = {
  1643. ACCESS_ON, BASICS_ON,
  1644. ACCESS_AVAILABLE, BASICS_AVAILABLE,
  1645. ACCESS_SHOWSTATUSINDICATOR, BASICS_INDICATOR,
  1646. NULL, 0
  1647. };
  1648. ACCESS_OPTION TimeOut[] = {
  1649. ACCESS_ON, BASICS_ON,
  1650. ACCESS_ONOFFFEEDBACK, ATF_ONOFFFEEDBACK,
  1651. NULL, 0
  1652. };
  1653. ACCESS_OPTION ToggleKeys[] = {
  1654. ACCESS_ON, BASICS_ON,
  1655. ACCESS_AVAILABLE, BASICS_AVAILABLE,
  1656. ACCESS_HOTKEYACTIVE, BASICS_HOTKEYACTIVE,
  1657. ACCESS_CONFIRMHOTKEY, BASICS_CONFIRMHOTKEY,
  1658. ACCESS_HOTKEYSOUND, BASICS_HOTKEYSOUND,
  1659. ACCESS_SHOWSTATUSINDICATOR, BASICS_INDICATOR,
  1660. NULL, 0
  1661. };
  1662. ACCESS_OPTION HighContrast[] = {
  1663. ACCESS_ON, BASICS_ON,
  1664. ACCESS_AVAILABLE, BASICS_AVAILABLE,
  1665. ACCESS_HOTKEYACTIVE, BASICS_HOTKEYACTIVE,
  1666. ACCESS_CONFIRMHOTKEY, BASICS_CONFIRMHOTKEY,
  1667. ACCESS_HOTKEYSOUND, BASICS_HOTKEYSOUND,
  1668. ACCESS_SHOWSTATUSINDICATOR, BASICS_INDICATOR,
  1669. ACCESS_HOTKEYAVAILABLE, HCF_HOTKEYAVAILABLE,
  1670. NULL, 0
  1671. };
  1672. ChkErr (Win32Printf (h, "\r\n[Accessibility]\r\n"));
  1673. ChkErr (ScanConvertFlags (h, ACCESS_KEY "KeyboardResponse", &FilterKeys[0], BASICS_AVAILABLE));
  1674. ChkErr (ScanConvertFlags (h, ACCESS_KEY "MouseKeys", &MouseKeys[0], BASICS_AVAILABLE));
  1675. ChkErr (ScanConvertFlags (h, ACCESS_KEY "StickyKeys", &StickyKeys[0], BASICS_AVAILABLE));
  1676. ChkErr (ScanConvertFlags (h, ACCESS_KEY "SoundSentry", &SoundSentry[0], BASICS_AVAILABLE));
  1677. ChkErr (ScanConvertFlags (h, ACCESS_KEY "TimeOut", &TimeOut[0], 0));
  1678. ChkErr (ScanConvertFlags (h, ACCESS_KEY "ToggleKeys", &ToggleKeys[0], 0));
  1679. ChkErr (ScanConvertFlags (h, ACCESS_KEY "HighContrast",&HighContrast[0],
  1680. BASICS_AVAILABLE | BASICS_INDICATOR | HCF_HOTKEYAVAILABLE));
  1681. Err:
  1682. if (Verbose && dwErr != ERROR_SUCCESS)
  1683. Win32Printf (LogFile, "Out ScanAccessibility => %d\n", dwErr);
  1684. return dwErr;
  1685. }
  1686. #define DESKTOP_KEY TEXT("Control Panel\\desktop")
  1687. //+--------------------------------------------------------------------------
  1688. //
  1689. // Function: ScanGetScreenSaverExe
  1690. //
  1691. // Synopsis: get screen saver name from system.ini
  1692. //
  1693. // Arguments:
  1694. //
  1695. // Returns: Appropriate status code
  1696. //
  1697. // History: 20-Sep-99 HenryLee Created
  1698. //
  1699. //---------------------------------------------------------------------------
  1700. DWORD ScanGetScreenSaverExe (HANDLE h)
  1701. {
  1702. DWORD dwErr = ERROR_SUCCESS;
  1703. TCHAR IniFileSetting[MAX_PATH];
  1704. GetPrivateProfileString (
  1705. TEXT("boot"),
  1706. SCRNSAVE,
  1707. TEXT(""),
  1708. IniFileSetting,
  1709. MAX_PATH,
  1710. TEXT("SYSTEM.INI"));
  1711. if (IniFileSetting[0] == '\0')
  1712. return ERROR_SUCCESS;
  1713. dwErr = Win32Printf (h, "HKR, \"%s\", \"%s\", 0x%x, \"%s\"\r\n",
  1714. DESKTOP_KEY, SCRNSAVE, FLG_ADDREG_TYPE_SZ, IniFileSetting);
  1715. return dwErr;
  1716. }
  1717. //+--------------------------------------------------------------------------
  1718. //
  1719. // Function: ScanDesktop
  1720. //
  1721. // Synopsis: convert desktop settings
  1722. //
  1723. // Arguments:
  1724. //
  1725. // Returns: Appropriate status code
  1726. //
  1727. // History: 20-Sep-99 HenryLee Created
  1728. //
  1729. //---------------------------------------------------------------------------
  1730. DWORD ScanDesktop (HANDLE h)
  1731. {
  1732. DWORD dwErr = ERROR_SUCCESS;
  1733. if (Win9x) // screen savers are already in the registry on NT
  1734. {
  1735. ChkErr (Win32Printf (h, "\r\n[Desktop]\r\n"));
  1736. ChkErr (ScanGetScreenSaverExe (h));
  1737. ChkErr (Win32Printf (h, "\r\n"));
  1738. Err:
  1739. if (Verbose && dwErr != ERROR_SUCCESS)
  1740. Win32Printf (LogFile, "Out ScanDesktop => %x\r\n", dwErr);
  1741. }
  1742. return dwErr;
  1743. }
  1744. #define IS_IME_KBDLAYOUT(hkl) ((HIWORD((ULONG_PTR)(hkl)) & 0xf000) == 0xe000)
  1745. //+--------------------------------------------------------------------------
  1746. //
  1747. // Function: ScanGetKeyboardLayouts
  1748. //
  1749. // Synopsis: retrieve all active input locales
  1750. //
  1751. // Arguments:
  1752. //
  1753. // Returns: Appropriate status code
  1754. //
  1755. // History: 20-Sep-99 HenryLee Created
  1756. //
  1757. //---------------------------------------------------------------------------
  1758. DWORD ScanGetKeyboardLayouts (HANDLE h)
  1759. {
  1760. DWORD dwErr = ERROR_SUCCESS;
  1761. TCHAR kbname[KL_NAMELENGTH];
  1762. int nLayout = GetKeyboardLayoutList(0, NULL);
  1763. HKL hkl = GetKeyboardLayout (0);
  1764. HKL * phkl = new HKL [nLayout];
  1765. if (phkl == NULL)
  1766. ChkErr (ERROR_NOT_ENOUGH_MEMORY);
  1767. if (FALSE != GetKeyboardLayoutName (kbname))
  1768. {
  1769. // get the default input locale
  1770. //
  1771. ChkErr (Win32Printf (h, "%s=%s", INPUTLOCALE, kbname));
  1772. GetKeyboardLayoutList (nLayout, phkl);
  1773. for (int i=0; i < nLayout; i++)
  1774. {
  1775. if (hkl != phkl[i]) // get the alternate layouts
  1776. {
  1777. if (0 == ActivateKeyboardLayout (phkl[i], 0))
  1778. {
  1779. if (!IS_IME_KBDLAYOUT(phkl[i])) // use locale default
  1780. wsprintf (kbname, "%08x", LOWORD(phkl[i]));
  1781. ChkErr (Win32Printf (h, ",%s", kbname));
  1782. }
  1783. else if (FALSE != GetKeyboardLayoutName (kbname))
  1784. ChkErr (Win32Printf (h, ",%s", kbname));
  1785. }
  1786. }
  1787. ChkErr (Win32Printf (h, "\r\n"));
  1788. }
  1789. Err:
  1790. ActivateKeyboardLayout (hkl, 0); // restore current input locale
  1791. if (phkl != NULL)
  1792. delete [] phkl;
  1793. return dwErr;
  1794. }
  1795. //+---------------------------------------------------------------------------
  1796. //
  1797. // Function: ScanSystem
  1798. //
  1799. // Synopsis: scan system settings
  1800. //
  1801. // Arguments:
  1802. //
  1803. // Returns: Appropriate status code
  1804. //
  1805. // History: 20-Sep-99 HenryLee Created
  1806. //
  1807. //----------------------------------------------------------------------------
  1808. DWORD ScanSystem()
  1809. {
  1810. DWORD result = ERROR_SUCCESS;
  1811. if (!CopySystem && !SchedSystem)
  1812. goto cleanup;
  1813. #if 0
  1814. result = ScanEnumerateShares (OutputFile);
  1815. if (result != ERROR_SUCCESS)
  1816. goto cleanup;
  1817. #else
  1818. Win32Printf (OutputFile, (CHAR *) SHARES);
  1819. #endif
  1820. if (DebugOutput)
  1821. Win32Printf(LogFile, " Enumerating Net Resources\r\n");
  1822. result = ScanEnumerateNetResources (OutputFile, RESOURCE_CONNECTED, NULL);
  1823. if (result != ERROR_SUCCESS)
  1824. goto cleanup;
  1825. if (DebugOutput)
  1826. Win32Printf(LogFile, " Enumerating Printers\r\n");
  1827. result = ScanEnumeratePrinters (OutputFile);
  1828. if (result != ERROR_SUCCESS)
  1829. goto cleanup;
  1830. if (DebugOutput)
  1831. Win32Printf(LogFile, " Scanning RAS Settings\r\n");
  1832. result = InitializeRasApi();
  1833. if (result == ERROR_SUCCESS)
  1834. {
  1835. result = ScanRasSettings (OutputFile);
  1836. if (result != ERROR_SUCCESS)
  1837. goto cleanup;
  1838. }
  1839. if (Win9x) // Accessibility settings on NT are registry compatible and forced
  1840. {
  1841. if (DebugOutput)
  1842. Win32Printf(LogFile, " Scanning Accessibility options\r\n");
  1843. result = ScanAccessibility (OutputFile); // convert the settings
  1844. if (result != ERROR_SUCCESS)
  1845. goto cleanup;
  1846. }
  1847. if (DebugOutput)
  1848. Win32Printf(LogFile, " Scanning Desktop\r\n");
  1849. result = ScanDesktop (OutputFile);
  1850. if (result != ERROR_SUCCESS)
  1851. goto cleanup;
  1852. cleanup:
  1853. if (result != ERROR_SUCCESS)
  1854. LogFormatError (result);
  1855. return result;
  1856. }