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.

1408 lines
36 KiB

  1. /*-----------------------------------------------------------------------------
  2. misc.cpp
  3. service functions
  4. History:
  5. 1/7/98 DONALDM Moved to new ICW project and string
  6. and nuked 16 bit stuff
  7. -----------------------------------------------------------------------------*/
  8. //#include <stdio.h>
  9. #include "obcomglb.h"
  10. #include <shlobj.h>
  11. #include <winsock2.h>
  12. #include <assert.h>
  13. #include <ras.h>
  14. #include <util.h>
  15. #include <inetreg.h>
  16. #include <userenv.h>
  17. #include <userenvp.h>
  18. #include <shlwapi.h>
  19. #include <sddl.h>
  20. extern "C"
  21. {
  22. #include <sputils.h>
  23. }
  24. #define DIR_SIGNUP L"signup"
  25. #define DIR_WINDOWS L"windows"
  26. #define DIR_SYSTEM L"system"
  27. #define DIR_TEMP L"temp"
  28. #define INF_DEFAULT L"SPAM SPAM SPAM SPAM SPAM SPAM EGGS AND SPAM"
  29. const WCHAR cszFALSE[] = L"FALSE";
  30. const WCHAR cszTRUE[] = L"TRUE";
  31. BOOL g_bGotProxy=FALSE;
  32. //+----------------------------------------------------------------------------
  33. // NAME: GetSz
  34. //
  35. // Load strings from resources
  36. //
  37. // Created 1/28/96, Chris Kauffman
  38. //+----------------------------------------------------------------------------
  39. LPWSTR GetSz(DWORD dwszID)
  40. {
  41. /*
  42. LPWSTR psz = szStrTable[iSzTable];
  43. iSzTable++;
  44. if (iSzTable >= MAX_STRINGS)
  45. iSzTable = 0;
  46. if (!LoadString(_Module.GetModuleInstance(), dwszID, psz, 512))
  47. {
  48. *psz = 0;
  49. }
  50. return (psz);
  51. */
  52. return (NULL);
  53. }
  54. //+---------------------------------------------------------------------------
  55. //
  56. // Function: ProcessDBCS
  57. //
  58. // Synopsis: Converts control to use DBCS compatible font
  59. // Use this at the beginning of the dialog procedure
  60. //
  61. // Note that this is required due to a bug in Win95-J that prevents
  62. // it from properly mapping MS Shell Dlg. This hack is not needed
  63. // under winNT.
  64. //
  65. // Arguments: hwnd - Window handle of the dialog
  66. // cltID - ID of the control you want changed.
  67. //
  68. // Returns: ERROR_SUCCESS
  69. //
  70. // History: 4/31/97 a-frankh Created
  71. // 5/13/97 jmazner Stole from CM to use here
  72. //----------------------------------------------------------------------------
  73. void ProcessDBCS(HWND hDlg, int ctlID)
  74. {
  75. HFONT hFont = NULL;
  76. /*if( IsNT() )
  77. {
  78. return;
  79. }*/
  80. hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
  81. if (hFont == NULL)
  82. hFont = (HFONT) GetStockObject(SYSTEM_FONT);
  83. if (hFont != NULL)
  84. SendMessage(GetDlgItem(hDlg, ctlID), WM_SETFONT, (WPARAM) hFont, MAKELPARAM(TRUE, 0));
  85. }
  86. // ############################################################################
  87. // StoreInSignUpReg
  88. //
  89. // Created 3/18/96, Chris Kauffman
  90. // ############################################################################
  91. HRESULT StoreInSignUpReg(LPBYTE lpbData, DWORD dwSize, DWORD dwType, LPCWSTR pszKey)
  92. {
  93. HRESULT hr = ERROR_ACCESS_DENIED;
  94. HKEY hKey;
  95. hr = RegCreateKey(HKEY_LOCAL_MACHINE, SIGNUPKEY, &hKey);
  96. if (hr != ERROR_SUCCESS) goto StoreInSignUpRegExit;
  97. hr = RegSetValueEx(hKey, pszKey, 0,dwType,lpbData,dwSize);
  98. RegCloseKey(hKey);
  99. StoreInSignUpRegExit:
  100. return hr;
  101. }
  102. HRESULT ReadSignUpReg(LPBYTE lpbData, DWORD *pdwSize, DWORD dwType, LPCWSTR pszKey)
  103. {
  104. HRESULT hr = ERROR_ACCESS_DENIED;
  105. HKEY hKey = 0;
  106. hr = RegOpenKey(HKEY_LOCAL_MACHINE, SIGNUPKEY, &hKey);
  107. if (hr != ERROR_SUCCESS) goto ReadSignUpRegExit;
  108. hr = RegQueryValueEx(hKey, pszKey, 0,&dwType,lpbData,pdwSize);
  109. ReadSignUpRegExit:
  110. if (hKey) RegCloseKey (hKey);
  111. return hr;
  112. }
  113. HRESULT DeleteSignUpReg(LPCWSTR pszKey)
  114. {
  115. HRESULT hr = ERROR_ACCESS_DENIED;
  116. HKEY hKey = 0;
  117. hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SIGNUPKEY, 0, KEY_ALL_ACCESS, &hKey);
  118. if (hr != ERROR_SUCCESS) goto ReadSignUpRegExit;
  119. hr = RegDeleteValue(hKey, pszKey);
  120. ReadSignUpRegExit:
  121. if (hKey) RegCloseKey (hKey);
  122. return hr;
  123. }
  124. // ############################################################################
  125. // GetDataFromISPFile
  126. //
  127. // This function will read a specific piece of information from an ISP file.
  128. //
  129. // Created 3/16/96, Chris Kauffman
  130. // ############################################################################
  131. HRESULT GetDataFromISPFile
  132. (
  133. LPWSTR pszISPCode,
  134. LPWSTR pszSection,
  135. LPWSTR pszDataName,
  136. LPWSTR pszOutput,
  137. DWORD cchOutput)
  138. {
  139. LPWSTR pszTemp;
  140. HRESULT hr = ERROR_SUCCESS;
  141. WCHAR szTempPath[MAX_PATH];
  142. //WCHAR szBuff256[256];
  143. *pszOutput = L'\0'; // since lstrlen(pszOutput) is used later when
  144. // pszOutput may be otherwise still uninitialized
  145. // Locate ISP file
  146. if (!SearchPath(NULL, pszISPCode, INF_SUFFIX,MAX_PATH,szTempPath,&pszTemp))
  147. {
  148. //wsprintf(szBuff256, L"Can not find:%s%s (%d) (connect.exe)", pszISPCode,INF_SUFFIX,GetLastError());
  149. ////AssertMsg(0, szBuff256);
  150. //lstrcpyn(szTempPath, pszISPCode, MAX_PATH);
  151. //lstrcpyn(&szTempPath[lstrlen(szTempPath)], INF_SUFFIX, MAX_PATH-lstrlen(szTempPath));
  152. //wsprintf(szBuff256, GetSz(IDS_CANTLOADINETCFG), szTempPath);
  153. ////MessageBox(NULL, szBuff256, GetSz(IDS_TITLE),MB_MYERROR);
  154. hr = ERROR_FILE_NOT_FOUND;
  155. } else if (!GetPrivateProfileString(pszSection, pszDataName, INF_DEFAULT,
  156. pszOutput, (int)cchOutput, szTempPath))
  157. {
  158. //TraceMsg(TF_GENERAL, L"ICWHELP: %s not specified in ISP file.\n", pszDataName);
  159. hr = ERROR_FILE_NOT_FOUND;
  160. }
  161. // 10/23/96 jmazner Normandy #9921
  162. // CompareString does _not_ have same return values as lsrtcmp!
  163. // Return value of 2 indicates strings are equal.
  164. //if (!CompareString(LOCALE_SYSTEM_DEFAULT, 0, INF_DEFAULT,lstrlen(INF_DEFAULT),pszOutput,lstrlen(pszOutput)))
  165. if (2 == CompareString(LOCALE_SYSTEM_DEFAULT, 0, INF_DEFAULT,lstrlen(INF_DEFAULT),pszOutput,lstrlen(pszOutput)))
  166. {
  167. hr = ERROR_FILE_NOT_FOUND;
  168. }
  169. if (hr != ERROR_SUCCESS && cchOutput)
  170. *pszOutput = L'\0'; // I suppose if CompareString fails, this is not
  171. // redundant with the first *pszOutput = L'\0';.
  172. return hr;
  173. }
  174. // ############################################################################
  175. // GetINTFromISPFile
  176. //
  177. // This function will read a specific integer from an ISP file.
  178. //
  179. //
  180. // ############################################################################
  181. HRESULT GetINTFromISPFile
  182. (
  183. LPWSTR pszISPCode,
  184. LPWSTR pszSection,
  185. LPWSTR pszDataName,
  186. int far *lpData,
  187. int iDefaultValue
  188. )
  189. {
  190. LPWSTR pszTemp;
  191. HRESULT hr = ERROR_SUCCESS;
  192. WCHAR szTempPath[MAX_PATH];
  193. //WCHAR szBuff256[256];
  194. // Locate ISP file
  195. if (!SearchPath(NULL, pszISPCode, INF_SUFFIX,MAX_PATH,szTempPath,&pszTemp))
  196. {
  197. //wsprintf(szBuff256, L"Can not find:%s%s (%d) (connect.exe)", pszISPCode,INF_SUFFIX,GetLastError());
  198. ////AssertMsg(0, szBuff256);
  199. //lstrcpyn(szTempPath, pszISPCode, MAX_PATH);
  200. //lstrcpyn(&szTempPath[lstrlen(szTempPath)], INF_SUFFIX, MAX_PATH-lstrlen(szTempPath));
  201. //wsprintf(szBuff256, GetSz(IDS_CANTLOADINETCFG), szTempPath);
  202. //MessageBox(NULL, szBuff256, GetSz(IDS_TITLE),MB_MYERROR);
  203. hr = ERROR_FILE_NOT_FOUND;
  204. }
  205. *lpData = GetPrivateProfileInt(pszSection,
  206. pszDataName,
  207. iDefaultValue,
  208. szTempPath);
  209. return hr;
  210. }
  211. //+-------------------------------------------------------------------
  212. //
  213. // Function: IsNT
  214. //
  215. // Synopsis: findout If we are running on NT
  216. //
  217. // Arguements: none
  218. //
  219. // Return: TRUE - Yes
  220. // FALSE - No
  221. //
  222. //--------------------------------------------------------------------
  223. BOOL IsNT ()
  224. {
  225. OSVERSIONINFO OsVersionInfo;
  226. ZeroMemory(&OsVersionInfo, sizeof(OSVERSIONINFO));
  227. OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  228. GetVersionEx(&OsVersionInfo);
  229. return (VER_PLATFORM_WIN32_NT == OsVersionInfo.dwPlatformId);
  230. } //end of IsNT function call
  231. //+-------------------------------------------------------------------
  232. //
  233. // Function: IsNT4SP3Lower
  234. //
  235. // Synopsis: findout If we are running on NTSP3 or lower
  236. //
  237. // Arguements: none
  238. //
  239. // Return: TRUE - Yes
  240. // FALSE - No
  241. //
  242. //--------------------------------------------------------------------
  243. BOOL IsNT4SP3Lower()
  244. {
  245. return FALSE;
  246. }
  247. // ############################################################################
  248. HRESULT ClearProxySettings()
  249. {
  250. /*
  251. HINSTANCE hinst = NULL;
  252. FARPROC fp;
  253. HRESULT hr = ERROR_SUCCESS;
  254. hinst = LoadLibrary(L"INETCFG.DLL");
  255. if (hinst)
  256. {
  257. fp = GetProcAddress(hinst, "InetGetProxy");
  258. if (!fp)
  259. {
  260. hr = GetLastError();
  261. goto ClearProxySettingsExit;
  262. }
  263. //hr = ((PFNINETGETPROXY)fp)(&g_bProxy, NULL, 0,NULL,0);
  264. if (hr == ERROR_SUCCESS)
  265. g_bGotProxy = TRUE;
  266. else
  267. goto ClearProxySettingsExit;
  268. if (g_bProxy)
  269. {
  270. fp = GetProcAddress(hinst, "InetSetProxy");
  271. if (!fp)
  272. {
  273. hr = GetLastError();
  274. goto ClearProxySettingsExit;
  275. }
  276. ((PFNINETSETPROXY)fp)(FALSE, (LPCSTR)NULL, (LPCSTR)NULL);
  277. }
  278. } else {
  279. hr = GetLastError();
  280. }
  281. ClearProxySettingsExit:
  282. if (hinst)
  283. FreeLibrary(hinst);
  284. return hr;
  285. */
  286. return ERROR_SUCCESS;
  287. }
  288. // ############################################################################
  289. HRESULT RestoreProxySettings()
  290. {
  291. /*
  292. HINSTANCE hinst = NULL;
  293. FARPROC fp;
  294. HRESULT hr = ERROR_SUCCESS;
  295. hinst = LoadLibrary(L"INETCFG.DLL");
  296. if (hinst && g_bGotProxy)
  297. {
  298. fp = GetProcAddress(hinst, "InetSetProxy");
  299. if (!fp)
  300. {
  301. hr = GetLastError();
  302. goto RestoreProxySettingsExit;
  303. }
  304. ((PFNINETSETPROXY)fp)(g_bProxy, (LPCSTR)NULL, (LPCSTR)NULL);
  305. } else {
  306. hr = GetLastError();
  307. }
  308. RestoreProxySettingsExit:
  309. if (hinst)
  310. FreeLibrary(hinst);
  311. return hr;
  312. */
  313. return ERROR_SUCCESS;
  314. }
  315. // ############################################################################
  316. BOOL FSz2Dw(LPCWSTR pSz, LPDWORD dw)
  317. {
  318. DWORD val = 0;
  319. while (*pSz && *pSz != L'.')
  320. {
  321. if (*pSz >= L'0' && *pSz <= L'9')
  322. {
  323. val *= 10;
  324. val += *pSz++ - L'0';
  325. }
  326. else
  327. {
  328. return FALSE; //bad number
  329. }
  330. }
  331. *dw = val;
  332. return (TRUE);
  333. }
  334. // ############################################################################
  335. LPWSTR GetNextNumericChunk(LPWSTR psz, LPWSTR pszLim, LPWSTR* ppszNext)
  336. {
  337. LPWSTR pszEnd;
  338. // init for error case
  339. *ppszNext = NULL;
  340. // skip non numerics if any to start of next numeric chunk
  341. while(*psz<L'0' || *psz>L'9')
  342. {
  343. if(psz >= pszLim) return NULL;
  344. psz++;
  345. }
  346. // skip all numerics to end of country code
  347. for(pszEnd=psz; *pszEnd>=L'0' && *pszEnd<=L'9' && pszEnd<pszLim; pszEnd++)
  348. ;
  349. // zap whatever delimiter there was to terminate this chunk
  350. *pszEnd++ = L'\0';
  351. // return ptr to next chunk (pszEnd now points to it)
  352. if(pszEnd<pszLim)
  353. *ppszNext = pszEnd;
  354. return psz; // return ptr to start of chunk
  355. }
  356. // ############################################################################
  357. // BOOL FSz2DwEx(PCSTR pSz, DWORD *dw)
  358. // Accepts -1 as a valid number. currently this is used for LCID, since all langs has a LDID == -1
  359. BOOL FSz2DwEx(LPCWSTR pSz, DWORD far *dw)
  360. {
  361. DWORD val = 0;
  362. BOOL bNeg = FALSE;
  363. while (*pSz)
  364. {
  365. if( *pSz == L'-' )
  366. {
  367. bNeg = TRUE;
  368. pSz++;
  369. }
  370. else if ((*pSz >= L'0' && *pSz <= L'9'))
  371. {
  372. val *= 10;
  373. val += *pSz++ - L'0';
  374. }
  375. else
  376. {
  377. return FALSE; //bad number
  378. }
  379. }
  380. if(bNeg)
  381. val = 0 - val;
  382. *dw = val;
  383. return (TRUE);
  384. }
  385. // ############################################################################
  386. // BOOL FSz2WEx(PCSTR pSz, WORD *w)
  387. //Accepts -1 as a valid number. currently this is used for LCID, since all langs has a LDID == -1
  388. BOOL FSz2WEx(LPCWSTR pSz, WORD far *w)
  389. {
  390. DWORD dw;
  391. if (FSz2DwEx(pSz, &dw))
  392. {
  393. *w = (WORD)dw;
  394. return TRUE;
  395. }
  396. return FALSE;
  397. }
  398. // ############################################################################
  399. // BOOL FSz2W(PCSTR pSz, WORD *w)
  400. BOOL FSz2W(LPCWSTR pSz, WORD far *w)
  401. {
  402. DWORD dw;
  403. if (FSz2Dw(pSz, &dw))
  404. {
  405. *w = (WORD)dw;
  406. return TRUE;
  407. }
  408. return FALSE;
  409. }
  410. // ############################################################################
  411. WORD Sz2W (LPCWSTR szBuf)
  412. {
  413. DWORD dw;
  414. if (FSz2Dw(szBuf, &dw))
  415. {
  416. return (WORD)dw;
  417. }
  418. return 0;
  419. }
  420. // ############################################################################
  421. // BOOL FSz2B(PCSTR pSz, BYTE *pb)
  422. BOOL FSz2BOOL(LPCWSTR pSz, BOOL far *pbool)
  423. {
  424. if (lstrcmpi(cszFALSE, pSz) == 0)
  425. {
  426. *pbool = (BOOL)FALSE;
  427. }
  428. else
  429. {
  430. *pbool = (BOOL)TRUE;
  431. }
  432. return TRUE;
  433. }
  434. // ############################################################################
  435. // BOOL FSz2B(PCSTR pSz, BYTE *pb)
  436. BOOL FSz2B(LPCWSTR pSz, BYTE far *pb)
  437. {
  438. DWORD dw;
  439. if (FSz2Dw(pSz, &dw))
  440. {
  441. *pb = (BYTE)dw;
  442. return TRUE;
  443. }
  444. return FALSE;
  445. }
  446. BOOL FSz2SPECIAL(LPCWSTR pSz, BOOL far *pbool, BOOL far *pbIsSpecial, int far *pInt)
  447. {
  448. // See if the value is a BOOL (TRUE or FALSE)
  449. if (lstrcmpi(cszFALSE, pSz) == 0)
  450. {
  451. *pbool = FALSE;
  452. *pbIsSpecial = FALSE;
  453. }
  454. else if (lstrcmpi(cszTRUE, pSz) == 0)
  455. {
  456. *pbool = (BOOL)TRUE;
  457. *pbIsSpecial = FALSE;
  458. }
  459. else
  460. {
  461. // Not a BOOL, so it must be special
  462. *pbool = (BOOL)FALSE;
  463. *pbIsSpecial = TRUE;
  464. *pInt = _wtoi(pSz);
  465. }
  466. return TRUE;
  467. }
  468. // ############################################################################
  469. int FIsDigit( int c )
  470. {
  471. WCHAR szIn[2];
  472. WORD rwOut[2];
  473. szIn[0] = (WCHAR)c;
  474. szIn[1] = L'\0';
  475. GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, szIn,-1,rwOut);
  476. return rwOut[0] & C1_DIGIT;
  477. }
  478. // ############################################################################
  479. LPBYTE MyMemSet(LPBYTE dest, int c, size_t count)
  480. {
  481. LPVOID pv = dest;
  482. LPVOID pvEnd = (LPVOID)(dest + (WORD)count);
  483. while (pv < pvEnd)
  484. {
  485. *(LPINT)pv = c;
  486. //((WORD)pv)++;
  487. pv=((LPINT)pv)+1;
  488. }
  489. return dest;
  490. }
  491. // ############################################################################
  492. LPBYTE MyMemCpy(LPBYTE dest, const LPBYTE src, size_t count)
  493. {
  494. LPBYTE pbDest = (LPBYTE)dest;
  495. LPBYTE pbSrc = (LPBYTE)src;
  496. LPBYTE pbEnd = (LPBYTE)((DWORD_PTR)src + (DWORD_PTR)count);
  497. while (pbSrc < pbEnd)
  498. {
  499. *pbDest = *pbSrc;
  500. pbSrc++;
  501. pbDest++;
  502. }
  503. return dest;
  504. }
  505. // ############################################################################
  506. BOOL ShowControl(HWND hDlg, int idControl, BOOL fShow)
  507. {
  508. HWND hWnd;
  509. if (NULL == hDlg)
  510. {
  511. ////AssertMsg(0, L"Null Param");
  512. return FALSE;
  513. }
  514. hWnd = GetDlgItem(hDlg, idControl);
  515. if (hWnd)
  516. {
  517. ShowWindow(hWnd, fShow ? SW_SHOW : SW_HIDE);
  518. }
  519. return TRUE;
  520. }
  521. BOOL isAlnum(WCHAR c)
  522. {
  523. if ((c >= L'0' && c <= L'9') ||
  524. (c >= L'a' && c <= L'z') ||
  525. (c >= L'A' && c <= L'Z') )
  526. return TRUE;
  527. return FALSE;
  528. }
  529. // ############################################################################
  530. BOOL FShouldRetry2(HRESULT hrErr)
  531. {
  532. BOOL bRC;
  533. if (hrErr == ERROR_LINE_BUSY ||
  534. hrErr == ERROR_VOICE_ANSWER ||
  535. hrErr == ERROR_NO_ANSWER ||
  536. hrErr == ERROR_NO_CARRIER ||
  537. hrErr == ERROR_AUTHENTICATION_FAILURE ||
  538. hrErr == ERROR_PPP_TIMEOUT ||
  539. hrErr == ERROR_REMOTE_DISCONNECTION ||
  540. hrErr == ERROR_AUTH_INTERNAL ||
  541. hrErr == ERROR_PROTOCOL_NOT_CONFIGURED ||
  542. hrErr == ERROR_PPP_NO_PROTOCOLS_CONFIGURED)
  543. {
  544. bRC = TRUE;
  545. } else {
  546. bRC = FALSE;
  547. }
  548. return bRC;
  549. }
  550. //+----------------------------------------------------------------------------
  551. //
  552. // Function: FCampusNetOverride
  553. //
  554. // Synopsis: Detect if the dial should be skipped for the campus network
  555. //
  556. // Arguments: None
  557. //
  558. // Returns: TRUE - overide enabled
  559. //
  560. // History: 8/15/96 ChrisK Created
  561. //
  562. //-----------------------------------------------------------------------------
  563. #if defined(PRERELEASE)
  564. BOOL FCampusNetOverride()
  565. {
  566. HKEY hkey = NULL;
  567. BOOL bRC = FALSE;
  568. DWORD dwType = 0;
  569. DWORD dwSize = 0;
  570. DWORD dwData = 0;
  571. if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,
  572. L"Software\\Microsoft\\ISignup\\Debug", &hkey))
  573. goto FCampusNetOverrideExit;
  574. dwSize = sizeof(dwData);
  575. if (ERROR_SUCCESS != RegQueryValueEx(hkey, L"CampusNet", 0,&dwType,
  576. (LPBYTE)&dwData, &dwSize))
  577. goto FCampusNetOverrideExit;
  578. ////AssertMsg(REG_DWORD == dwType, L"Wrong value type for CampusNet. Must be DWORD.\r\n");
  579. bRC = (0 != dwData);
  580. if (bRC)
  581. {
  582. if (IDOK != MessageBox(NULL, L"DEBUG ONLY: CampusNet will be used.", L"Testing Override",MB_OKCANCEL))
  583. bRC = FALSE;
  584. }
  585. FCampusNetOverrideExit:
  586. if (hkey)
  587. RegCloseKey(hkey);
  588. return bRC;
  589. }
  590. #endif //PRERELEASE
  591. //+----------------------------------------------------------------------------
  592. // Function CopyUntil
  593. //
  594. // Synopsis Copy from source until destination until running out of source
  595. // or until the next character of the source is the chend character
  596. //
  597. // Arguments dest - buffer to recieve characters
  598. // src - source buffer
  599. // lpdwLen - length of dest buffer
  600. // chend - the terminating character
  601. //
  602. // Returns FALSE - ran out of room in dest buffer
  603. //
  604. // Histroy 10/25/96 ChrisK Created
  605. //-----------------------------------------------------------------------------
  606. static BOOL CopyUntil(LPWSTR *dest, LPWSTR *src, LPDWORD lpdwLen, WCHAR chend)
  607. {
  608. while ((L'\0' != **src) && (chend != **src) && (0 != *lpdwLen))
  609. {
  610. **dest = **src;
  611. (*lpdwLen)--;
  612. (*dest)++;
  613. (*src)++;
  614. }
  615. return (0 != *lpdwLen);
  616. }
  617. //+---------------------------------------------------------------------------
  618. //
  619. // Function: GenericMsg
  620. //
  621. //----------------------------------------------------------------------------
  622. void GenericMsg
  623. (
  624. HWND hwnd,
  625. UINT uId,
  626. LPCWSTR lpszArg,
  627. UINT uType
  628. )
  629. {
  630. WCHAR szTemp[MAX_STRING + 1];
  631. WCHAR szMsg[MAX_STRING + MAX_PATH + 1];
  632. LPWSTR psz;
  633. //Assert( lstrlen( GetSz(uId) ) <= MAX_STRING );
  634. psz = GetSz( (DWORD)uId );
  635. if (psz) {
  636. lstrcpy( szTemp, psz );
  637. }
  638. else {
  639. szTemp[0] = '\0';
  640. }
  641. if (lpszArg)
  642. {
  643. //Assert( lstrlen( lpszArg ) <= MAX_PATH );
  644. wsprintf(szMsg, szTemp, lpszArg);
  645. }
  646. else
  647. {
  648. lstrcpy(szMsg, szTemp);
  649. }
  650. //MessageBox(hwnd,
  651. // szMsg,
  652. // GetSz(IDS_TITLE),
  653. // uType);
  654. }
  655. //=--------------------------------------------------------------------------=
  656. // MakeWideFromAnsi
  657. //=--------------------------------------------------------------------------=
  658. // given a string, make a BSTR out of it.
  659. //
  660. // Parameters:
  661. // LPWSTR - [in]
  662. // BYTE - [in]
  663. //
  664. // Output:
  665. // LPWSTR - needs to be cast to final desired result
  666. //
  667. // Notes:
  668. //
  669. LPWSTR MakeWideStrFromAnsi
  670. (
  671. LPSTR psz,
  672. BYTE bType
  673. )
  674. {
  675. LPWSTR pwsz = NULL;
  676. int i;
  677. // arg checking.
  678. //
  679. if (!psz)
  680. return NULL;
  681. // compute the length of the required BSTR
  682. //
  683. i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
  684. if (i <= 0) return NULL;
  685. // allocate the widestr
  686. //
  687. switch (bType) {
  688. case STR_BSTR:
  689. // -1 since it'll add it's own space for a NULL terminator
  690. //
  691. pwsz = (LPWSTR) SysAllocStringLen(NULL, i - 1);
  692. break;
  693. case STR_OLESTR:
  694. pwsz = (LPWSTR) CoTaskMemAlloc(BYTES_REQUIRED_BY_CCH(i));
  695. break;
  696. //default:
  697. ////AssertMsg(0, L"Bogus String Type.");
  698. }
  699. if (!pwsz) return NULL;
  700. MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, i);
  701. pwsz[i - 1] = 0;
  702. return pwsz;
  703. }
  704. //=--------------------------------------------------------------------------=
  705. // MakeWideStrFromResId
  706. //=--------------------------------------------------------------------------=
  707. // given a resource ID, load it, and allocate a wide string for it.
  708. //
  709. // Parameters:
  710. // WORD - [in] resource id.
  711. // BYTE - [in] type of string desired.
  712. //
  713. // Output:
  714. // LPWSTR - needs to be cast to desired string type.
  715. //
  716. // Notes:
  717. //
  718. LPWSTR MakeWideStrFromResourceId
  719. (
  720. WORD wId,
  721. BYTE bType
  722. )
  723. {
  724. //int i;
  725. CHAR szTmp[512] = "0";
  726. // load the string from the resources.
  727. //
  728. //i = LoadString(_Module.GetModuleInstance(), wId, szTmp, 512);
  729. //if (!i) return NULL;
  730. return MakeWideStrFromAnsi(szTmp, bType);
  731. }
  732. //=--------------------------------------------------------------------------=
  733. // MakeWideStrFromWide
  734. //=--------------------------------------------------------------------------=
  735. // given a wide string, make a new wide string with it of the given type.
  736. //
  737. // Parameters:
  738. // LPWSTR - [in] current wide str.
  739. // BYTE - [in] desired type of string.
  740. //
  741. // Output:
  742. // LPWSTR
  743. //
  744. // Notes:
  745. //
  746. LPWSTR MakeWideStrFromWide
  747. (
  748. LPWSTR pwsz,
  749. BYTE bType
  750. )
  751. {
  752. LPWSTR pwszTmp = NULL;
  753. int i;
  754. if (!pwsz) return NULL;
  755. // just copy the string, depending on what type they want.
  756. //
  757. switch (bType) {
  758. case STR_OLESTR:
  759. i = lstrlenW(pwsz);
  760. pwszTmp = (LPWSTR)CoTaskMemAlloc(BYTES_REQUIRED_BY_CCH(i+1));
  761. if (!pwszTmp) return NULL;
  762. memcpy(pwszTmp, pwsz, (BYTES_REQUIRED_BY_CCH(i+1)));
  763. break;
  764. case STR_BSTR:
  765. pwszTmp = (LPWSTR)SysAllocString(pwsz);
  766. break;
  767. }
  768. return pwszTmp;
  769. }
  770. HRESULT
  771. GetCommonAppDataDirectory(
  772. LPWSTR szDirectory,
  773. DWORD cchDirectory
  774. )
  775. {
  776. assert(MAX_PATH <= cchDirectory);
  777. if (MAX_PATH > cchDirectory)
  778. {
  779. return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  780. }
  781. return SHGetFolderPath(NULL, // hwndOwner
  782. CSIDL_COMMON_APPDATA,
  783. NULL, // hAccessToken
  784. SHGFP_TYPE_CURRENT,
  785. szDirectory
  786. );
  787. }
  788. const LPWSTR cszPhoneBookPath =
  789. L"Microsoft\\Network\\Connections\\Pbk";
  790. const LPWSTR cszDefPhoneBook = L"rasphone.pbk";
  791. HRESULT
  792. GetDefaultPhoneBook(
  793. LPWSTR szPhoneBook,
  794. DWORD cchPhoneBook
  795. )
  796. {
  797. WCHAR rgchDirectory[MAX_PATH];
  798. int cch;
  799. HRESULT hr = GetCommonAppDataDirectory(rgchDirectory, MAX_PATH);
  800. if (FAILED(hr))
  801. {
  802. return hr;
  803. }
  804. if (cchPhoneBook < (DWORD)(lstrlen(rgchDirectory) + lstrlen(cszPhoneBookPath) + lstrlen(cszDefPhoneBook) + 3)
  805. )
  806. {
  807. return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  808. }
  809. cch = wsprintf(szPhoneBook, L"%s\\%s\\%s",
  810. rgchDirectory, cszPhoneBookPath, cszDefPhoneBook
  811. );
  812. assert(cch == lstrlen(rgchDirectory) + lstrlen(cszPhoneBookPath) +
  813. lstrlen(cszDefPhoneBook) + 2
  814. );
  815. return hr;
  816. }
  817. BOOL
  818. INetNToW(
  819. struct in_addr inaddr,
  820. LPWSTR szAddr
  821. )
  822. {
  823. USES_CONVERSION;
  824. LPSTR sz = inet_ntoa(inaddr);
  825. if (NULL != sz)
  826. {
  827. lstrcpy(szAddr, A2W(sz));
  828. }
  829. return (NULL != sz);
  830. } // INetNToW
  831. #ifndef REGSTR_VAL_NONETAUTODIAL
  832. #define REGSTR_VAL_NONETAUTODIAL L"NoNetAutodial"
  833. #endif
  834. LONG
  835. SetAutodial(
  836. IN HKEY hUserRoot, // HKEY_CURRENT_USER or other user hive root
  837. IN AUTODIAL_TYPE eType, // Type of autodial for the connectoid
  838. IN LPCWSTR szConnectoidName, // NULL terminated string of connectoid name
  839. IN BOOL bSetICWCompleted // set ICW completed flag or not
  840. )
  841. /*++
  842. Routine Description:
  843. Set a particular per-user registry settings to default an autodial
  844. connectoid to the name specified and always dial the autodial connection, and/or
  845. set the ICW completed flag
  846. Return Value:
  847. WIN32 Error code, i.e. ERROR_SUCCESS on success, -1 or other non-zero value
  848. on failure.
  849. Note:
  850. Despite the name, this function sets ICW Completed flag if bSetICWCompleted
  851. is true and do not set autodial if szConnectoidName is NULL.
  852. --*/
  853. {
  854. LONG ret = -1;
  855. HKEY hKey = NULL;
  856. DWORD dwRet = -1;
  857. if (bSetICWCompleted)
  858. {
  859. if (ERROR_SUCCESS == RegCreateKey( hUserRoot,
  860. ICWSETTINGSPATH,
  861. &hKey) )
  862. {
  863. DWORD dwCompleted = 1;
  864. ret = RegSetValueEx( hKey,
  865. ICWCOMPLETEDKEY,
  866. 0,
  867. REG_DWORD,
  868. (CONST BYTE*)&dwCompleted,
  869. sizeof(dwCompleted) );
  870. TRACE1(L"Setting ICW Completed key 0x%08lx", ret);
  871. RegCloseKey(hKey);
  872. }
  873. }
  874. // Set the name if given, else do not change the entry.
  875. if (szConnectoidName)
  876. {
  877. // Set the name of the connectoid for autodial.
  878. // HKCU\RemoteAccess\InternetProfile
  879. if (ERROR_SUCCESS == RegCreateKey( hUserRoot,
  880. REGSTR_PATH_REMOTEACCESS,
  881. &hKey) )
  882. {
  883. ret = RegSetValueEx( hKey,
  884. REGSTR_VAL_INTERNETPROFILE,
  885. 0,
  886. REG_SZ,
  887. (BYTE*)szConnectoidName,
  888. BYTES_REQUIRED_BY_SZ(szConnectoidName) );
  889. TRACE2(L"Setting IE autodial connectoid to %s 0x%08lx", szConnectoidName, ret);
  890. RegCloseKey(hKey);
  891. }
  892. hKey = NULL;
  893. if (ERROR_SUCCESS == ret)
  894. {
  895. // Set setting in the registry that indicates whether autodialing is enabled.
  896. // HKCU\Software\Microsoft\Windows\CurrentVersion\InternetSettings\EnableAutodial
  897. if (ERROR_SUCCESS == RegCreateKey( hUserRoot,
  898. REGSTR_PATH_INTERNET_SETTINGS,
  899. &hKey) )
  900. {
  901. DWORD dwValue;
  902. dwValue = (eType == AutodialTypeAlways || eType == AutodialTypeNoNet) ? 1 : 0;
  903. ret = RegSetValueEx( hKey,
  904. REGSTR_VAL_ENABLEAUTODIAL,
  905. 0,
  906. REG_DWORD,
  907. (BYTE*)&dwValue,
  908. sizeof(DWORD) );
  909. TRACE1(L"Enable/Disable IE Autodial 0x%08lx", ret);
  910. dwValue = (eType == AutodialTypeNoNet) ? 1 : 0;
  911. ret = RegSetValueEx( hKey,
  912. REGSTR_VAL_NONETAUTODIAL,
  913. 0,
  914. REG_DWORD,
  915. (BYTE*)&dwValue,
  916. sizeof(DWORD) );
  917. TRACE1(L"Setting Autodial mode 0x%08lx", ret);
  918. RegCloseKey(hKey);
  919. }
  920. }
  921. }
  922. return ret;
  923. }
  924. LONG
  925. SetUserAutodial(
  926. IN LPWSTR szProfileDir, // Directory containing a user's ntuser.dat file
  927. IN AUTODIAL_TYPE eType, // type of autodial for the connectoid
  928. IN LPCWSTR szConnectoidName,// NULL terminated string of connectoid name
  929. IN BOOL bSetICWCompleted // set the ICW completed key or not
  930. )
  931. /*++
  932. Routine Description:
  933. Modified a user profile, specified by the profile directory, to enable
  934. autodial. SE_BACKUP_NAME and SE_RESTORE_NAME privileges are required to
  935. load and unload a user hive.
  936. Return Value:
  937. WIN32 Error code, i.e. ERROR_SUCCESS on success, -1 or other non-zero value
  938. on failure.
  939. --*/
  940. {
  941. const WCHAR OOBE_USER_HIVE[] = L"OOBEUSERHIVE";
  942. HKEY hUserHive = NULL;
  943. WCHAR szProfilePath[MAX_PATH+1] = L"";
  944. LONG ret = -1;
  945. lstrcpyn(szProfilePath, szProfileDir, MAX_CHARS_IN_BUFFER(szProfilePath));
  946. pSetupConcatenatePaths(szProfilePath,
  947. L"\\NTUSER.DAT",
  948. MAX_CHARS_IN_BUFFER(szProfilePath),
  949. NULL);
  950. ret = RegLoadKey(HKEY_USERS, OOBE_USER_HIVE, szProfilePath);
  951. if (ret == ERROR_SUCCESS)
  952. {
  953. ret = RegOpenKeyEx( HKEY_USERS,
  954. OOBE_USER_HIVE,
  955. 0,
  956. KEY_WRITE,
  957. &hUserHive );
  958. if (ERROR_SUCCESS == ret)
  959. {
  960. ret = SetAutodial(hUserHive, eType, szConnectoidName, bSetICWCompleted);
  961. RegCloseKey(hUserHive);
  962. TRACE1(L"Autodial set %s", szProfilePath);
  963. }
  964. else
  965. {
  966. TRACE2(L"RegOpenKey %s failed %d", szProfilePath, ret);
  967. }
  968. RegUnLoadKey(HKEY_USERS, OOBE_USER_HIVE);
  969. }
  970. else
  971. {
  972. TRACE2(L"RegLoadKey %s failed %d", szProfilePath, ret);
  973. }
  974. return ret;
  975. }
  976. BOOL
  977. MyGetUserProfileDirectory(
  978. IN LPWSTR szUser, // a user account name
  979. OUT LPWSTR szUserProfileDir, // buffer to receive null terminate string
  980. IN OUT LPDWORD pcchSize // input the buffer size in TCHAR, including terminating NULL
  981. )
  982. /*++
  983. Routine Description:
  984. This function does what the SDK function GetUserProfileDirectory does,
  985. except that it accepts a user account name instead of handle to a user
  986. token.
  987. Return Value:
  988. TRUE - Success
  989. FALSE - Failure
  990. --*/
  991. {
  992. PSID pSid = NULL;
  993. DWORD cbSid = 0;
  994. LPWSTR szDomainName = NULL;
  995. DWORD cbDomainName = 0;
  996. SID_NAME_USE eUse = SidTypeUser;
  997. BOOL bRet;
  998. bRet = LookupAccountName(NULL,
  999. szUser,
  1000. NULL,
  1001. &cbSid,
  1002. NULL,
  1003. &cbDomainName,
  1004. &eUse);
  1005. if (!bRet && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  1006. {
  1007. pSid = (PSID) LocalAlloc(LPTR, cbSid);
  1008. szDomainName = (LPWSTR) LocalAlloc(LPTR, cbDomainName * sizeof(TCHAR));
  1009. if (pSid && szDomainName)
  1010. {
  1011. bRet = LookupAccountName(NULL,
  1012. szUser,
  1013. pSid,
  1014. &cbSid,
  1015. szDomainName,
  1016. &cbDomainName,
  1017. &eUse);
  1018. }
  1019. }
  1020. if (bRet && SidTypeUser == eUse)
  1021. {
  1022. bRet = GetUserProfileDirFromSid(pSid, szUserProfileDir, pcchSize);
  1023. if (!bRet)
  1024. {
  1025. TRACE1(L"GetUserProfileDirFromSid (%d)", GetLastError());
  1026. }
  1027. }
  1028. else
  1029. {
  1030. if (SidTypeUser == eUse)
  1031. {
  1032. TRACE2(L"LookupAccountName %s (%d)", szUser, GetLastError());
  1033. }
  1034. }
  1035. if (pSid)
  1036. {
  1037. LocalFree(pSid);
  1038. pSid = NULL;
  1039. }
  1040. if (szDomainName)
  1041. {
  1042. LocalFree(szDomainName);
  1043. szDomainName = NULL;
  1044. }
  1045. return bRet;
  1046. }
  1047. BOOL EnumBuildInAdministrators(
  1048. OUT LPWSTR* pszAlias // list of name delimited by null, double null-terminated
  1049. )
  1050. /*++
  1051. Routine Description:
  1052. List all the build-in administrator accounts created by Windows Setup.
  1053. Return Value:
  1054. TRUE - Success
  1055. FALSE - Failure
  1056. --*/
  1057. {
  1058. WCHAR szReservedAdmins[MAX_PATH * 2] = L"";
  1059. PWCHAR p = NULL;
  1060. DWORD len;
  1061. BOOL ret = FALSE;
  1062. HINSTANCE hInstance = NULL;
  1063. if (pszAlias != NULL)
  1064. {
  1065. *pszAlias = NULL;
  1066. hInstance = LoadLibraryEx(OOBE_MAIN_DLL, NULL, LOAD_LIBRARY_AS_DATAFILE);
  1067. if (hInstance != NULL)
  1068. {
  1069. len = LoadString(hInstance,
  1070. 566, // IDS_ACCTLIST_RESERVEDADMINS in OOBE_MAIN_DLL
  1071. szReservedAdmins,
  1072. MAX_CHARS_IN_BUFFER(szReservedAdmins));
  1073. if (len)
  1074. {
  1075. DWORD cbSize;
  1076. p = StrChr(szReservedAdmins, L'|');
  1077. while ( p )
  1078. {
  1079. PWCHAR t = CharNext(p);
  1080. *p = L'\0';
  1081. p = StrChr(t, L'|');
  1082. }
  1083. cbSize = sizeof(WCHAR) * (len + 1);
  1084. // Make sure we have enough space for
  1085. // double NULL terminate the return value
  1086. *pszAlias = (LPWSTR) GlobalAlloc(GPTR, cbSize + sizeof(WCHAR));
  1087. if (*pszAlias)
  1088. {
  1089. CopyMemory(*pszAlias, szReservedAdmins, cbSize);
  1090. // double NULL terminate the string
  1091. (*pszAlias)[cbSize / sizeof(WCHAR)] = L'\0';
  1092. ret = TRUE;
  1093. }
  1094. }
  1095. FreeLibrary(hInstance);
  1096. }
  1097. }
  1098. return ret;
  1099. }
  1100. BOOL
  1101. SetMultiUserAutodial(
  1102. IN AUTODIAL_TYPE eType, // type of autodial for the connectoid
  1103. IN LPCWSTR szConnectoidName,// NULL terminated string of connectoid name
  1104. IN BOOL bSetICWCompleted // set the ICW completed key or not
  1105. )
  1106. {
  1107. BOOL bSucceed = TRUE;
  1108. LONG lRet = ERROR_SUCCESS;
  1109. WCHAR szProfileDir[MAX_PATH+1] = L"";
  1110. DWORD dwSize;
  1111. LPWSTR szAdmins = NULL;
  1112. // SYSTEM
  1113. lRet = SetAutodial(HKEY_CURRENT_USER, eType, szConnectoidName, bSetICWCompleted);
  1114. if (lRet != ERROR_SUCCESS)
  1115. {
  1116. bSucceed = FALSE;
  1117. }
  1118. pSetupEnablePrivilege(SE_BACKUP_NAME, TRUE);
  1119. pSetupEnablePrivilege(SE_RESTORE_NAME, TRUE);
  1120. // Default User, which will apply to any new user profiles created
  1121. // afterward.
  1122. dwSize = MAX_CHARS_IN_BUFFER(szProfileDir);
  1123. if (GetDefaultUserProfileDirectory(szProfileDir, &dwSize))
  1124. {
  1125. lRet = SetUserAutodial(szProfileDir, eType, szConnectoidName, bSetICWCompleted);
  1126. if (lRet != ERROR_SUCCESS)
  1127. {
  1128. bSucceed = FALSE;
  1129. }
  1130. }
  1131. // Built-in Administrators, e.g. Administrator.
  1132. if (EnumBuildInAdministrators(&szAdmins))
  1133. {
  1134. LPWSTR szAdmin = szAdmins;
  1135. while (*szAdmin)
  1136. {
  1137. // MAX_CHARS_IN_BUFFER excludes the terminating NULL
  1138. dwSize = MAX_CHARS_IN_BUFFER(szProfileDir) + 1;
  1139. if (MyGetUserProfileDirectory(szAdmin, szProfileDir, &dwSize))
  1140. {
  1141. lRet = SetUserAutodial(szProfileDir, eType, szConnectoidName, bSetICWCompleted);
  1142. if (lRet != ERROR_SUCCESS)
  1143. {
  1144. bSucceed = FALSE;
  1145. }
  1146. }
  1147. szAdmin += (lstrlen(szAdmin) + 1);
  1148. }
  1149. GlobalFree(szAdmins);
  1150. }
  1151. return bSucceed;
  1152. }
  1153. BOOL
  1154. SetDefaultConnectoid(
  1155. IN AUTODIAL_TYPE eType, // type of autodial for the connectoid
  1156. IN LPCWSTR szConnectoidName // null terminated autodial connectoid name
  1157. )
  1158. /*++
  1159. Routine Description:
  1160. Set the default autodial connectoid for SYSTEM, Default User and
  1161. build-in administrators. Assume that this function is run in System
  1162. context, i.e. it is SYSTEM who runs OOBE.
  1163. Return Value:
  1164. TRUE - Success to set all user accounts
  1165. FALSE - Failure to set any one of the user accounts
  1166. --*/
  1167. {
  1168. BOOL bSucceed = TRUE;
  1169. LONG lRet = ERROR_SUCCESS;
  1170. RASAUTODIALENTRY adEntry;
  1171. //
  1172. // IE on WinXP use Ras autodial address, instead of its own registry
  1173. // key for autodial connection name, but it keeps using its own registry
  1174. // key for autodial mode.
  1175. //
  1176. ZeroMemory(&adEntry, sizeof(RASAUTODIALENTRY));
  1177. adEntry.dwSize = sizeof(RASAUTODIALENTRY);
  1178. lstrcpyn(adEntry.szEntry, szConnectoidName,
  1179. sizeof(adEntry.szEntry)/sizeof(WCHAR)
  1180. );
  1181. lRet = RasSetAutodialAddress(NULL,
  1182. NULL,
  1183. &adEntry,
  1184. sizeof(RASAUTODIALENTRY),
  1185. 1
  1186. );
  1187. TRACE2(L"Setting default autodial connectoid to %s %d\n",
  1188. szConnectoidName, lRet);
  1189. if (lRet != ERROR_SUCCESS)
  1190. {
  1191. bSucceed = FALSE;
  1192. return bSucceed;
  1193. }
  1194. bSucceed = SetMultiUserAutodial(eType, szConnectoidName, FALSE);
  1195. return bSucceed;
  1196. }