Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1769 lines
48 KiB

  1. /*++
  2. Microsoft Confidential
  3. Copyright (c) 1992-1997 Microsoft Corporation
  4. All rights reserved
  5. Module Name:
  6. envvar.c
  7. Abstract:
  8. Implements the Environment Variables dialog of the System
  9. Control Panel Applet
  10. Author:
  11. Eric Flo (ericflo) 19-Jun-1995
  12. Revision History:
  13. 15-Oct-1997 scotthal
  14. Complete overhaul
  15. --*/
  16. #include "sysdm.h"
  17. #include <help.h>
  18. // C Runtime
  19. #include <stddef.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <debug.h>
  23. // for Hydra
  24. #include <winsta.h>
  25. //==========================================================================
  26. // Local Definitions
  27. //==========================================================================
  28. #define LB_SYSVAR 1
  29. #define LB_USERVAR 2
  30. #define SYSTEMROOT TEXT("SystemRoot")
  31. #define SYSTEMDRIVE TEXT("SystemDrive")
  32. //==========================================================================
  33. // Typedefs and Structs
  34. //==========================================================================
  35. // Registry valuename linked-list structure
  36. typedef struct _regval
  37. {
  38. struct _regval *prvNext;
  39. LPTSTR szValueName;
  40. } REGVAL;
  41. //==========================================================================
  42. // Local Functions
  43. //==========================================================================
  44. void EVDoCommand(HWND hDlg, HWND hwndCtl, int idCtl, int iNotify );
  45. void EVSave(HWND hDlg);
  46. void EVCleanUp (HWND hDlg);
  47. PENVAR GetVar(HWND hDlg, UINT VarType, int iSelection);
  48. int FindVar (HWND hwndLB, LPTSTR szVar);
  49. void
  50. SetVar(
  51. IN HWND hDlg,
  52. IN UINT VarType,
  53. IN LPCTSTR szVarName,
  54. IN LPCTSTR szVarValue
  55. );
  56. void
  57. DeleteVar(
  58. IN HWND hDlg,
  59. IN UINT VarType,
  60. IN LPCTSTR szVarName
  61. );
  62. //
  63. // New.../Edit... subdialog functions
  64. //
  65. INT_PTR
  66. APIENTRY
  67. EnvVarsEditDlg(
  68. IN HWND hDlg,
  69. IN UINT uMsg,
  70. IN WPARAM wParam,
  71. IN LPARAM lParam
  72. );
  73. void
  74. EVDoEdit(
  75. IN HWND hWnd,
  76. IN UINT VarType,
  77. IN UINT EditType,
  78. IN int iSelection
  79. );
  80. BOOL
  81. ExpandSystemVar(
  82. IN LPCTSTR pszSrc,
  83. OUT LPTSTR pszDst,
  84. IN DWORD cchDst
  85. );
  86. //==========================================================================
  87. // "Global" Variables for this page
  88. //==========================================================================
  89. BOOL bEditSystemVars = FALSE;
  90. DWORD cxLBSysVars = 0;
  91. BOOL bUserVars = TRUE;
  92. //
  93. // Help ID's
  94. //
  95. DWORD aEnvVarsHelpIds[] = {
  96. IDC_STATIC, NO_HELP,
  97. IDC_ENVVAR_SYS_USERGROUP, (IDH_ENV + 2),
  98. IDC_ENVVAR_SYS_LB_USERVARS, (IDH_ENV + 2),
  99. IDC_ENVVAR_SYS_SYSGROUP, (IDH_ENV + 0),
  100. IDC_ENVVAR_SYS_LB_SYSVARS, (IDH_ENV + 0),
  101. IDC_ENVVAR_SYS_NEWUV, (IDH_ENV + 7),
  102. IDC_ENVVAR_SYS_EDITUV, (IDH_ENV + 8),
  103. IDC_ENVVAR_SYS_NDELUV, (IDH_ENV + 9),
  104. IDC_ENVVAR_SYS_NEWSV, (IDH_ENV + 10),
  105. IDC_ENVVAR_SYS_EDITSV, (IDH_ENV + 11),
  106. IDC_ENVVAR_SYS_DELSV, (IDH_ENV + 12),
  107. 0, 0
  108. };
  109. TCHAR szUserEnv[] = TEXT( "Environment" );
  110. TCHAR szSysEnv[] = TEXT( "System\\CurrentControlSet\\Control\\Session Manager\\Environment" );
  111. HRESULT
  112. _AddVarToListbox(HWND hwndListBox,
  113. DWORD dwIndex,
  114. LPTSTR pszValueName,
  115. LPTSTR pszValue,
  116. DWORD dwType)
  117. {
  118. HRESULT hr;
  119. ENVARS* penvar = (ENVARS *) LocalAlloc (LPTR, sizeof(ENVARS));
  120. if (!penvar)
  121. {
  122. hr = E_OUTOFMEMORY;
  123. }
  124. else
  125. {
  126. TCHAR szExpValue[BUFZ];
  127. if (!ExpandSystemVar (pszValue, szExpValue, ARRAYSIZE(szExpValue)))
  128. {
  129. hr = E_FAIL;
  130. }
  131. else
  132. {
  133. penvar->szValueName = StrDup(pszValueName);
  134. penvar->szValue = StrDup(pszValue);
  135. penvar->szExpValue = StrDup(szExpValue);
  136. penvar->dwType = dwType;
  137. if (!penvar->szValueName || !penvar->szValue || !penvar->szExpValue)
  138. {
  139. hr = E_OUTOFMEMORY;
  140. }
  141. else
  142. {
  143. LV_ITEM item;
  144. int n;
  145. item.mask = LVIF_TEXT | LVIF_PARAM;
  146. item.iItem = (dwIndex - 1);
  147. item.iSubItem = 0;
  148. item.pszText = penvar->szValueName;
  149. item.lParam = (LPARAM) penvar;
  150. n = (int)SendMessage (hwndListBox, LVM_INSERTITEM, 0, (LPARAM) &item);
  151. if (n == -1)
  152. {
  153. hr = E_FAIL;
  154. }
  155. else
  156. {
  157. item.mask = LVIF_TEXT;
  158. item.iItem = n;
  159. item.iSubItem = 1;
  160. item.pszText = penvar->szExpValue;
  161. SendMessage (hwndListBox, LVM_SETITEMTEXT, n, (LPARAM) &item);
  162. hr = S_OK;
  163. }
  164. }
  165. }
  166. }
  167. if (FAILED(hr))
  168. {
  169. if (penvar)
  170. {
  171. LocalFree(penvar->szValueName);
  172. LocalFree(penvar->szValue);
  173. LocalFree(penvar->szExpValue);
  174. LocalFree(penvar);
  175. }
  176. }
  177. return hr;
  178. }
  179. DWORD
  180. _LoadEnvVars(HKEY hkeyEnv,
  181. HWND hwndListBox)
  182. {
  183. TCHAR szValueName[BUFZ] = {0};
  184. TCHAR szValue[BUFZ] = {0};
  185. DWORD dwBufz = ARRAYSIZE(szValueName);
  186. DWORD dwValz = sizeof(szValue);
  187. DWORD dwIndex = 0;
  188. DWORD dwCount = 0;
  189. DWORD dwType;
  190. // Read all values until an error is encountered
  191. while (ERROR_SUCCESS == RegEnumValue(hkeyEnv,
  192. dwIndex++, // Index'th value name/data
  193. szValueName, // Ptr to ValueName buffer
  194. &dwBufz, // Size of ValueName buffer
  195. NULL, // Title index return
  196. &dwType, // Type code of entry
  197. (LPBYTE) szValue, // Ptr to ValueData buffer
  198. &dwValz)) // Size of ValueData buffer
  199. {
  200. if (dwValz < sizeof(szValue) && // must not be truncated
  201. ((dwType == REG_SZ) || (dwType == REG_EXPAND_SZ))) // and must be an SZ or EXPAND_SZ
  202. {
  203. if (SUCCEEDED(_AddVarToListbox(hwndListBox, dwIndex, szValueName, szValue, dwType)))
  204. {
  205. dwCount++;
  206. }
  207. }
  208. dwBufz = ARRAYSIZE(szValueName); // reset
  209. dwValz = sizeof(szValue);
  210. }
  211. return dwCount;
  212. }
  213. BOOL
  214. InitEnvVarsDlg(
  215. IN HWND hDlg
  216. )
  217. /*++
  218. Routine Description:
  219. Initializes the environment variables page
  220. Arguments:
  221. hDlg -
  222. Supplies window handle
  223. Return Value:
  224. TRUE if successful
  225. FALSE if an error occurs
  226. --*/
  227. {
  228. TCHAR szBuffer1[200];
  229. TCHAR szBuffer2[300];
  230. TCHAR szUserName[MAX_USER_NAME];
  231. DWORD cchUserName = ARRAYSIZE(szUserName);
  232. HWND hwndTemp;
  233. HKEY hkeyEnv;
  234. DWORD dwBufz, dwValz, dwIndex, dwType;
  235. LONG Error;
  236. int n;
  237. LV_COLUMN col;
  238. RECT rect;
  239. int cxFirstCol;
  240. DWORD dwSysRegMode;
  241. LV_ITEM item;
  242. HourGlass (TRUE);
  243. //
  244. // Create the first column
  245. //
  246. LoadString (hInstance, IDS_ENVVAR_VARIABLE_HEADING, szBuffer1, ARRAYSIZE(szBuffer1));
  247. if (!GetClientRect (GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_SYSVARS), &rect)) {
  248. rect.right = 300;
  249. }
  250. cxFirstCol = (int)(rect.right * .3);
  251. col.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
  252. col.fmt = LVCFMT_LEFT;
  253. col.cx = cxFirstCol;
  254. col.pszText = szBuffer1;
  255. col.iSubItem = 0;
  256. SendDlgItemMessage (hDlg, IDC_ENVVAR_SYS_LB_SYSVARS, LVM_INSERTCOLUMN,
  257. 0, (LPARAM) &col);
  258. SendDlgItemMessage (hDlg, IDC_ENVVAR_SYS_LB_USERVARS, LVM_INSERTCOLUMN,
  259. 0, (LPARAM) &col);
  260. //
  261. // Create the second column
  262. //
  263. LoadString (hInstance, IDS_ENVVAR_VALUE_HEADING, szBuffer1, ARRAYSIZE(szBuffer1));
  264. col.cx = rect.right - cxFirstCol - GetSystemMetrics(SM_CYHSCROLL);
  265. col.iSubItem = 1;
  266. SendDlgItemMessage (hDlg, IDC_ENVVAR_SYS_LB_SYSVARS, LVM_INSERTCOLUMN,
  267. 1, (LPARAM) &col);
  268. SendDlgItemMessage (hDlg, IDC_ENVVAR_SYS_LB_USERVARS, LVM_INSERTCOLUMN,
  269. 1, (LPARAM) &col);
  270. ////////////////////////////////////////////////////////////////////
  271. // Display System Variables from registry in listbox
  272. ////////////////////////////////////////////////////////////////////
  273. cxLBSysVars = 0;
  274. hkeyEnv = NULL;
  275. // If user is an admin, then try to open the System Environment variables area with R/W, allow to edit
  276. if (IsUserAnAdmin())
  277. {
  278. dwSysRegMode = KEY_READ | KEY_WRITE;
  279. bEditSystemVars = TRUE;
  280. }
  281. else // If not ad admin, open with Read-Only, disallow edit of System Env variables area
  282. {
  283. dwSysRegMode = KEY_READ;
  284. bEditSystemVars = FALSE;
  285. }
  286. if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, szSysEnv, 0, dwSysRegMode, &hkeyEnv))
  287. {
  288. _LoadEnvVars(hkeyEnv, GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_SYSVARS));
  289. RegCloseKey (hkeyEnv);
  290. }
  291. ////////////////////////////////////////////////////////////////////
  292. // Display USER variables from registry in listbox
  293. ////////////////////////////////////////////////////////////////////
  294. //
  295. // Set the "User Environments for <username>" string
  296. //
  297. LoadString(hInstance, IDS_USERENVVARS, szBuffer1, ARRAYSIZE(szBuffer1));
  298. if (GetUserName(szUserName, &cchUserName) &&
  299. SUCCEEDED(StringCchPrintf(szBuffer2, ARRAYSIZE(szBuffer2), szBuffer1, szUserName)))
  300. {
  301. SetDlgItemText (hDlg, IDC_ENVVAR_SYS_USERGROUP, szBuffer2);
  302. }
  303. Error = RegCreateKeyEx(HKEY_CURRENT_USER, szUserEnv, 0, NULL, 0, KEY_READ, NULL, &hkeyEnv, NULL);
  304. if (Error == ERROR_SUCCESS)
  305. {
  306. _LoadEnvVars(hkeyEnv, GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_USERVARS));
  307. RegCloseKey (hkeyEnv);
  308. }
  309. else
  310. {
  311. // Report opening USER Environment key
  312. if (MsgBoxParam (hDlg, IsUserAnAdmin() ? IDS_SYSDM_NOOPEN_USER_UNK : IDS_SYSDM_NOOPEN_USER_NOTADMIN,
  313. IDS_SYSDM_TITLE, MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
  314. {
  315. HourGlass (FALSE);
  316. return FALSE;
  317. }
  318. }
  319. //
  320. // Select the first items in the listviews
  321. // It is important to set the User listview first, and
  322. // then the system. When the system listview is set,
  323. // we will receive a LVN_ITEMCHANGED notification and
  324. // clear the focus in the User listview. But when someone
  325. // tabs to the control the arrow keys will work correctly.
  326. //
  327. item.mask = LVIF_STATE;
  328. item.iItem = 0;
  329. item.iSubItem = 0;
  330. item.state = LVIS_SELECTED | LVIS_FOCUSED;
  331. item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
  332. SendDlgItemMessage (hDlg, IDC_ENVVAR_SYS_LB_USERVARS,
  333. LVM_SETITEMSTATE, 0, (LPARAM) &item);
  334. SendDlgItemMessage (hDlg, IDC_ENVVAR_SYS_LB_SYSVARS,
  335. LVM_SETITEMSTATE, 0, (LPARAM) &item);
  336. // Set extended LV style for whole line selection
  337. SendDlgItemMessage(hDlg, IDC_ENVVAR_SYS_LB_SYSVARS, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
  338. SendDlgItemMessage(hDlg, IDC_ENVVAR_SYS_LB_USERVARS, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
  339. HourGlass (FALSE);
  340. //
  341. // Disable System Var Editing buttons if
  342. // user is not an administrator
  343. //
  344. EnableWindow(
  345. GetDlgItem(hDlg, IDC_ENVVAR_SYS_NEWSV),
  346. bEditSystemVars
  347. );
  348. EnableWindow(
  349. GetDlgItem(hDlg, IDC_ENVVAR_SYS_EDITSV),
  350. bEditSystemVars
  351. );
  352. EnableWindow(
  353. GetDlgItem(hDlg, IDC_ENVVAR_SYS_DELSV),
  354. bEditSystemVars
  355. );
  356. return TRUE;
  357. }
  358. INT_PTR
  359. APIENTRY
  360. EnvVarsDlgProc(
  361. IN HWND hDlg,
  362. IN UINT uMsg,
  363. IN WPARAM wParam,
  364. IN LPARAM lParam
  365. )
  366. /*++
  367. Routine Description:
  368. Handles messages sent to the Environment Variables dialog box
  369. Arguments:
  370. hDlg -
  371. Supplies window handle
  372. uMsg -
  373. Supplies message being sent
  374. wParam -
  375. Supplies message parameter
  376. lParam -
  377. Supplies message parameter
  378. Return Value:
  379. TRUE if message was handled
  380. FALSE if message was unhandled
  381. --*/
  382. {
  383. INT i = 0;
  384. HWND hWndTemp = NULL;
  385. switch (uMsg)
  386. {
  387. case WM_INITDIALOG:
  388. if (!InitEnvVarsDlg(hDlg)) {
  389. EndDialog (hDlg, 0);
  390. }
  391. break;
  392. case WM_NOTIFY:
  393. switch (((NMHDR FAR*)lParam)->code)
  394. {
  395. case LVN_KEYDOWN:
  396. switch (((NMHDR FAR*)lParam)->idFrom) {
  397. case IDC_ENVVAR_SYS_LB_USERVARS:
  398. i = IDC_ENVVAR_SYS_NDELUV;
  399. break;
  400. case IDC_ENVVAR_SYS_LB_SYSVARS:
  401. i = IDC_ENVVAR_SYS_DELSV;
  402. break;
  403. default:
  404. return(FALSE);
  405. break;
  406. } // switch
  407. hWndTemp = GetDlgItem(hDlg, i);
  408. if ((VK_DELETE == ((LV_KEYDOWN FAR *) lParam)->wVKey)) {
  409. if (IsWindowEnabled(hWndTemp)) {
  410. SendMessage(
  411. hDlg,
  412. WM_COMMAND,
  413. MAKEWPARAM(i, BN_CLICKED),
  414. (LPARAM) hWndTemp
  415. );
  416. } // if (IsWindowEnabled...
  417. else {
  418. MessageBeep(MB_ICONASTERISK);
  419. } // else
  420. } // if (VK_DELETE...
  421. break;
  422. case NM_DBLCLK:
  423. switch (((NMHDR FAR*)lParam)->idFrom) {
  424. case IDC_ENVVAR_SYS_LB_USERVARS:
  425. i = IDC_ENVVAR_SYS_EDITUV;
  426. break;
  427. case IDC_ENVVAR_SYS_LB_SYSVARS:
  428. i = IDC_ENVVAR_SYS_EDITSV;
  429. break;
  430. default:
  431. return(FALSE);
  432. break;
  433. } // switch
  434. hWndTemp = GetDlgItem(hDlg, i);
  435. if (IsWindowEnabled(hWndTemp)) {
  436. SendMessage(
  437. hDlg,
  438. WM_COMMAND,
  439. MAKEWPARAM(i, BN_CLICKED),
  440. (LPARAM) hWndTemp
  441. );
  442. } // if (IsWindowEnabled...
  443. else {
  444. MessageBeep(MB_ICONASTERISK);
  445. } // else
  446. break;
  447. default:
  448. return FALSE;
  449. }
  450. break;
  451. case WM_COMMAND:
  452. EVDoCommand(hDlg, (HWND)lParam, LOWORD(wParam), HIWORD(wParam));
  453. break;
  454. case WM_DESTROY:
  455. EVCleanUp (hDlg);
  456. break;
  457. case WM_HELP: // F1
  458. WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP, (DWORD_PTR) (LPSTR) aEnvVarsHelpIds);
  459. break;
  460. case WM_CONTEXTMENU: // right mouse click
  461. WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU, (DWORD_PTR) (LPSTR) aEnvVarsHelpIds);
  462. break;
  463. default:
  464. return FALSE;
  465. }
  466. return TRUE;
  467. }
  468. void
  469. EVDoCommand(
  470. IN HWND hDlg,
  471. IN HWND hwndCtl,
  472. IN int idCtl,
  473. IN int iNotify
  474. )
  475. /*++
  476. Routine Description:
  477. Handles WM_COMMAND messages sent to Environment Variables dialog box
  478. Arguments:
  479. hDlg -
  480. Supplies window handle
  481. hwndCtl -
  482. Supplies window handle of control which sent the WM_COMMAND
  483. idCtl -
  484. Supplies ID of control which sent the WM_COMMAND
  485. iNotify -
  486. Supplies notification code
  487. Return Value:
  488. None
  489. --*/
  490. {
  491. TCHAR szTemp[MAX_PATH];
  492. int i;
  493. HWND hwndTemp;
  494. PENVAR penvar;
  495. switch (idCtl) {
  496. case IDOK:
  497. EVSave(hDlg);
  498. EndDialog(hDlg, 0);
  499. break;
  500. case IDCANCEL:
  501. EndDialog(hDlg, 0);
  502. break;
  503. case IDC_ENVVAR_SYS_EDITSV:
  504. EVDoEdit(
  505. hDlg,
  506. SYSTEM_VAR,
  507. EDIT_VAR,
  508. GetSelectedItem(GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_SYSVARS))
  509. );
  510. break;
  511. case IDC_ENVVAR_SYS_EDITUV:
  512. EVDoEdit(
  513. hDlg,
  514. USER_VAR,
  515. EDIT_VAR,
  516. GetSelectedItem(GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_USERVARS))
  517. );
  518. break;
  519. case IDC_ENVVAR_SYS_NEWSV:
  520. EVDoEdit(hDlg, SYSTEM_VAR, NEW_VAR, -1);
  521. break;
  522. case IDC_ENVVAR_SYS_NEWUV:
  523. EVDoEdit(hDlg, USER_VAR, NEW_VAR, -1);
  524. break;
  525. case IDC_ENVVAR_SYS_DELSV:
  526. i = GetSelectedItem(GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_SYSVARS));
  527. if (-1 != i)
  528. {
  529. penvar = GetVar(hDlg, SYSTEM_VAR, i);
  530. if (penvar)
  531. {
  532. DeleteVar(hDlg, SYSTEM_VAR, penvar->szValueName);
  533. }
  534. } // if
  535. break;
  536. case IDC_ENVVAR_SYS_NDELUV:
  537. i = GetSelectedItem(GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_USERVARS));
  538. if (-1 != i)
  539. {
  540. penvar = GetVar(hDlg, USER_VAR, i);
  541. if (penvar)
  542. {
  543. DeleteVar(hDlg, USER_VAR, penvar->szValueName);
  544. }
  545. } // if
  546. break;
  547. default:
  548. break;
  549. } // switch
  550. return;
  551. }
  552. void
  553. DeleteVar(
  554. IN HWND hDlg,
  555. IN UINT VarType,
  556. IN LPCTSTR szVarName
  557. )
  558. /*++
  559. Routine Description:
  560. Deletes an environment variable of a given name and type
  561. Arguments:
  562. hDlg -
  563. Supplies window handle
  564. VarType -
  565. Supplies variable type (user or system)
  566. szVarName -
  567. Supplies variable name
  568. Return Value:
  569. None, although it really should have one someday.
  570. --*/
  571. {
  572. TCHAR szTemp2[MAX_PATH];
  573. int i, n;
  574. TCHAR *bBuffer;
  575. TCHAR *pszTemp;
  576. LPTSTR pszString;
  577. HWND hwndTemp;
  578. ENVARS *penvar;
  579. LV_ITEM item;
  580. // Delete listbox entry that matches value in szVarName
  581. // If found, delete entry else ignore
  582. if (szVarName[0] &&
  583. SUCCEEDED(StringCchCopy(szTemp2, ARRAYSIZE(szTemp2), szVarName)))
  584. {
  585. // Determine which Listbox to use (SYSTEM or USER vars)
  586. switch (VarType) {
  587. case SYSTEM_VAR:
  588. i = IDC_ENVVAR_SYS_LB_SYSVARS;
  589. break;
  590. case USER_VAR:
  591. default:
  592. i = IDC_ENVVAR_SYS_LB_USERVARS;
  593. break;
  594. } // switch (VarType)
  595. hwndTemp = GetDlgItem (hDlg, i);
  596. n = FindVar (hwndTemp, szTemp2);
  597. if (n != -1)
  598. {
  599. // Free existing strings (listbox and ours)
  600. item.mask = LVIF_PARAM;
  601. item.iItem = n;
  602. item.iSubItem = 0;
  603. if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  604. penvar = (ENVARS *) item.lParam;
  605. } else {
  606. penvar = NULL;
  607. }
  608. if (penvar) {
  609. LocalFree (penvar->szValueName);
  610. LocalFree (penvar->szValue);
  611. LocalFree (penvar->szExpValue);
  612. LocalFree ((LPVOID) penvar);
  613. }
  614. SendMessage (hwndTemp, LVM_DELETEITEM, n, 0L);
  615. PropSheet_Changed(GetParent(hDlg), hDlg);
  616. // Fix selection state in listview
  617. if (n > 0) {
  618. n--;
  619. }
  620. item.mask = LVIF_STATE;
  621. item.iItem = n;
  622. item.iSubItem = 0;
  623. item.state = LVIS_SELECTED | LVIS_FOCUSED;
  624. item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
  625. SendDlgItemMessage (hDlg, i,
  626. LVM_SETITEMSTATE, n, (LPARAM) &item);
  627. }
  628. }
  629. }
  630. void
  631. SetVar(
  632. IN HWND hDlg,
  633. IN UINT VarType,
  634. IN LPCTSTR szVarName,
  635. IN LPCTSTR szVarValue
  636. )
  637. /*++
  638. Routine Description:
  639. Given an environment variable's type (system or user), name, and value,
  640. creates a ENVVARS structure for that environment variable and inserts
  641. it into the proper list view control, deleteing any existing variable
  642. of the same name.
  643. Arguments:
  644. hDlg -
  645. Supplies window handle
  646. VarType -
  647. Supplies the type of the environment variable (system or user)
  648. szVarName -
  649. Supplies the name of the environment variable
  650. szVarValue -
  651. Supplies the value of the environment variable
  652. Return Value:
  653. None, although it really should have one someday.
  654. --*/
  655. {
  656. TCHAR szTemp2[BUFZ];
  657. int i, n;
  658. TCHAR *bBuffer;
  659. TCHAR *pszTemp;
  660. LPTSTR pszString;
  661. HWND hwndTemp;
  662. int idTemp;
  663. ENVARS *penvar;
  664. LV_ITEM item;
  665. if (SUCCEEDED(StringCchCopy(szTemp2, ARRAYSIZE(szTemp2), szVarName)))
  666. {
  667. // Strip trailing whitespace from end of Env Variable
  668. i = lstrlen(szTemp2) - 1;
  669. while (i >= 0)
  670. {
  671. if (iswspace(szTemp2[i]))
  672. szTemp2[i--] = TEXT('\0');
  673. else
  674. break;
  675. }
  676. // Make sure variable name does not contain the "=" sign.
  677. pszTemp = StrChr (szTemp2, TEXT('='));
  678. if (pszTemp)
  679. *pszTemp = TEXT('\0');
  680. if (szTemp2[0] == TEXT('\0'))
  681. return;
  682. bBuffer = (TCHAR *) LocalAlloc (LPTR, BUFZ * sizeof(TCHAR));
  683. if (bBuffer)
  684. {
  685. pszString = (LPTSTR) LocalAlloc (LPTR, BUFZ * sizeof(TCHAR));
  686. if (pszString)
  687. {
  688. if (SUCCEEDED(StringCchCopy(bBuffer, BUFZ, szVarValue)))
  689. {
  690. // Determine which Listbox to use (SYSTEM or USER vars)
  691. switch (VarType)
  692. {
  693. case SYSTEM_VAR:
  694. idTemp = IDC_ENVVAR_SYS_LB_SYSVARS;
  695. break;
  696. case USER_VAR:
  697. default:
  698. idTemp = IDC_ENVVAR_SYS_LB_USERVARS;
  699. break;
  700. } // switch (VarType)
  701. hwndTemp = GetDlgItem(hDlg, idTemp);
  702. n = FindVar(hwndTemp, szTemp2);
  703. if (n != -1)
  704. {
  705. // Free existing strings (listview and ours)
  706. item.mask = LVIF_PARAM;
  707. item.iItem = n;
  708. item.iSubItem = 0;
  709. if (SendMessage(hwndTemp, LVM_GETITEM, 0, (LPARAM) &item))
  710. {
  711. penvar = (ENVARS *) item.lParam;
  712. }
  713. else
  714. {
  715. penvar = NULL;
  716. }
  717. if (penvar)
  718. {
  719. LocalFree(penvar->szValueName);
  720. LocalFree(penvar->szValue);
  721. LocalFree(penvar->szExpValue);
  722. }
  723. SendMessage(hwndTemp, LVM_DELETEITEM, n, 0L);
  724. }
  725. else
  726. {
  727. // Get some storage for new Env Var
  728. penvar = (ENVARS *) LocalAlloc(LPTR, sizeof(ENVARS));
  729. }
  730. // If there are two '%' chars in string, then this is a
  731. // REG_EXPAND_SZ style environment string
  732. pszTemp = StrChr (bBuffer, TEXT('%'));
  733. if (penvar)
  734. {
  735. if (pszTemp && StrChr (pszTemp, TEXT('%')))
  736. penvar->dwType = REG_EXPAND_SZ;
  737. else
  738. penvar->dwType = REG_SZ;
  739. }
  740. switch (VarType)
  741. {
  742. case SYSTEM_VAR:
  743. ExpandSystemVar(bBuffer, pszString, BUFZ);
  744. break;
  745. case USER_VAR:
  746. ExpandEnvironmentStrings (bBuffer, pszString, BUFZ);
  747. break;
  748. default:
  749. break;
  750. } // switch
  751. n = -1;
  752. if (penvar)
  753. {
  754. penvar->szValueName = StrDup (szTemp2);
  755. if (penvar->szValueName)
  756. {
  757. penvar->szValue = StrDup (bBuffer);
  758. if (penvar->szValue)
  759. {
  760. penvar->szExpValue = StrDup (pszString);
  761. if (penvar->szExpValue)
  762. {
  763. item.mask = LVIF_TEXT | LVIF_PARAM;
  764. item.iItem = ListView_GetItemCount(hwndTemp);
  765. item.iSubItem = 0;
  766. item.pszText = penvar->szValueName;
  767. item.lParam = (LPARAM) penvar;
  768. n = (int)SendMessage (hwndTemp, LVM_INSERTITEM, 0, (LPARAM) &item);
  769. }
  770. }
  771. }
  772. if (n == -1) // on failure, free memory
  773. {
  774. LocalFree(penvar->szExpValue);
  775. LocalFree(penvar->szValueName);
  776. LocalFree(penvar->szValue);
  777. }
  778. else // success!
  779. {
  780. item.mask = LVIF_TEXT;
  781. item.iItem = n;
  782. item.iSubItem = 1;
  783. item.pszText = penvar->szExpValue;
  784. SendMessage (hwndTemp, LVM_SETITEMTEXT, n, (LPARAM) &item);
  785. item.mask = LVIF_STATE;
  786. item.iItem = n;
  787. item.iSubItem = 0;
  788. item.state = LVIS_SELECTED | LVIS_FOCUSED;
  789. item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
  790. SendDlgItemMessage (hDlg, idTemp, LVM_SETITEMSTATE, n, (LPARAM) &item);
  791. }
  792. }
  793. }
  794. LocalFree(pszString);
  795. }
  796. LocalFree(bBuffer);
  797. }
  798. }
  799. }
  800. void
  801. EVDoEdit(
  802. IN HWND hWnd,
  803. IN UINT VarType,
  804. IN UINT EditType,
  805. IN int iSelection
  806. )
  807. /*++
  808. Routine Description:
  809. Sets up for, executes, and cleans up after an Environment Variable
  810. New... or Edit... dialog. Called when user presses a New... or Edit...
  811. button.
  812. Arguments:
  813. hWnd -
  814. Supplies window handle
  815. VarType -
  816. Supplies the type of the variable: User (USER_VAR) or
  817. System (SYSTEM_VAR)
  818. EditType -
  819. Supplies the type of the edit: create New (NEW_VAR) or
  820. Edit existing (EDIT_VAR)
  821. iSelection -
  822. Supplies the currently selected variable of type VarType. This
  823. value is ignored if EditType is NEW_VAR.
  824. Return Value:
  825. None. May alter the contents of a list view control as a side effect.
  826. --*/
  827. {
  828. LRESULT Result = 0;
  829. BOOL fVarChanged = FALSE;
  830. HWND hWndLB = NULL;
  831. ENVARS *penvar = NULL;
  832. LV_ITEM item;
  833. ASSERT((-1 != iSelection) || (NEW_VAR == EditType));
  834. g_VarType = VarType;
  835. g_EditType = EditType;
  836. penvar = GetVar(hWnd, VarType, iSelection);
  837. switch (EditType) {
  838. case NEW_VAR:
  839. ZeroMemory((LPVOID) g_szVarName, sizeof(g_szVarName));
  840. ZeroMemory((LPVOID) g_szVarValue, sizeof(g_szVarValue));
  841. break;
  842. case EDIT_VAR:
  843. if (!penvar ||
  844. FAILED(StringCchCopy(g_szVarName, ARRAYSIZE(g_szVarName), penvar->szValueName)) ||
  845. FAILED(StringCchCopy(g_szVarValue, ARRAYSIZE(g_szVarValue), penvar->szValue)))
  846. {
  847. MessageBeep(MB_ICONASTERISK);
  848. return;
  849. }
  850. break;
  851. case INVALID_EDIT_TYPE:
  852. default:
  853. return;
  854. } // switch
  855. Result = DialogBox(
  856. hInstance,
  857. (LPTSTR) MAKEINTRESOURCE(IDD_ENVVAREDIT),
  858. hWnd,
  859. EnvVarsEditDlg
  860. );
  861. //
  862. // Only update the list view control if the user
  863. // actually changed or created a variable
  864. //
  865. switch (Result) {
  866. case EDIT_CHANGE:
  867. if (EDIT_VAR == EditType) {
  868. fVarChanged =
  869. lstrcmp(penvar->szValueName, g_szVarName) ||
  870. lstrcmp(penvar->szValue, g_szVarValue);
  871. } // if (EDIT_VAR...
  872. else if (NEW_VAR == EditType) {
  873. fVarChanged =
  874. lstrlen(g_szVarName) && lstrlen(g_szVarValue);
  875. } // else if (NEW_VAR...
  876. else {
  877. fVarChanged = FALSE;
  878. } // else
  879. if (fVarChanged) {
  880. if (EDIT_VAR == EditType) {
  881. DeleteVar(hWnd, VarType, penvar->szValueName);
  882. } // if (EDIT_VAR...
  883. SetVar(hWnd, VarType, g_szVarName, g_szVarValue);
  884. } // if (fVarChanged)
  885. break;
  886. default:
  887. break;
  888. } // switch (Result)
  889. g_VarType = INVALID_VAR_TYPE;
  890. g_EditType = INVALID_EDIT_TYPE;
  891. return;
  892. }
  893. PENVAR
  894. GetVar(
  895. IN HWND hDlg,
  896. IN UINT VarType,
  897. IN int iSelection
  898. )
  899. /*++
  900. Routine Description:
  901. Returns a given System or User environment variable, as stored
  902. in the System or User environment variable listview control.
  903. Changing the structure returned by this routine is not
  904. recommended, because it will alter the values actually stored
  905. in the listview control.
  906. Arguments:
  907. hDlg -
  908. Supplies window handle
  909. VarType -
  910. Supplies variable type--System or User
  911. iSelection -
  912. Supplies the selection index into the listview control of
  913. the desired environment variable
  914. Return Value:
  915. Pointer to a valid ENVARS structure if successful.
  916. NULL if unsuccessful.
  917. --*/
  918. {
  919. HWND hWndLB = NULL;
  920. PENVAR penvar = NULL;
  921. LV_ITEM item;
  922. switch (VarType)
  923. {
  924. case SYSTEM_VAR:
  925. hWndLB = GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_SYSVARS);
  926. break;
  927. case USER_VAR:
  928. hWndLB = GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_USERVARS);
  929. break;
  930. case INVALID_VAR_TYPE:
  931. default:
  932. return NULL;
  933. } // switch (VarType)
  934. item.mask = LVIF_PARAM;
  935. item.iItem = iSelection;
  936. item.iSubItem = 0;
  937. if (iSelection >= 0 && SendMessage (hWndLB, LVM_GETITEM, 0, (LPARAM) &item))
  938. {
  939. penvar = (ENVARS *) item.lParam;
  940. }
  941. else
  942. {
  943. penvar = NULL;
  944. }
  945. return penvar;
  946. }
  947. int
  948. FindVar(
  949. IN HWND hwndLV,
  950. IN LPTSTR szVar
  951. )
  952. /*++
  953. Routine Description:
  954. Find the USER Environment variable that matches passed string
  955. and return its listview index or -1
  956. Arguments:
  957. hwndLV -
  958. Supplies window handle to the list view control containing the
  959. environment variables
  960. szVar -
  961. Supplies the variable name in string form
  962. Return Value:
  963. List view item index which matches the passed in string if the string
  964. is the name of an environment variable
  965. -1 if the passed in string is not the name of an environment variable
  966. --*/
  967. {
  968. LV_FINDINFO FindInfo;
  969. FindInfo.flags = LVFI_STRING;
  970. FindInfo.psz = szVar;
  971. return (int)(SendMessage (hwndLV, LVM_FINDITEM, (WPARAM) -1, (LPARAM) &FindInfo));
  972. }
  973. //
  974. // Hydra's
  975. // WinStationBroadcastSystemMessage(
  976. //
  977. typedef
  978. LONG
  979. (*PWINSTABSM_ROUTINE) (
  980. HANDLE hServer,
  981. BOOL sendToAllWinstations, // you set this to TRUE
  982. ULONG sessionID, // set to NULL, due to above
  983. ULONG timeOut,
  984. DWORD dwFlags,
  985. DWORD *lpdwRecipients,
  986. ULONG uiMessage,
  987. WPARAM wParam,
  988. LPARAM lParam,
  989. LONG *pResponse);
  990. PWINSTABSM_ROUTINE fp_WinStaBroadcastSystemMessage;
  991. // load winsta.dll (if any) and initialize the global function pointers to use
  992. HANDLE
  993. InitializeHydraInterface(
  994. void
  995. )
  996. {
  997. HANDLE hwinStaLib=NULL;
  998. //
  999. // Load the Terminal Server base library that contains the user message dispatch
  1000. // routines if termial server is running.
  1001. //
  1002. if (hwinStaLib = LoadLibrary(TEXT("WINSTA.DLL")))
  1003. {
  1004. fp_WinStaBroadcastSystemMessage = (PWINSTABSM_ROUTINE)GetProcAddress(
  1005. hwinStaLib,"WinStationBroadcastSystemMessage");
  1006. if (fp_WinStaBroadcastSystemMessage )
  1007. {
  1008. return (hwinStaLib);
  1009. }
  1010. else
  1011. {
  1012. // this must not be a NT5 running Terminal Services, which means
  1013. // it could be NT5 WKS, or some flavor of NT4.
  1014. // So, we just bail out, no problem.
  1015. FreeLibrary(hwinStaLib);
  1016. return (NULL);
  1017. }
  1018. }
  1019. return NULL;
  1020. }
  1021. void
  1022. _DeleteEnvVars(IN HKEY hkey)
  1023. {
  1024. TCHAR szTemp[BUFZ];
  1025. REGVAL* prvFirst;
  1026. REGVAL* prvRegVal;
  1027. DWORD dwBufz = ARRAYSIZE(szTemp);
  1028. DWORD dwIndex = 0;
  1029. DWORD dwType;
  1030. prvFirst = NULL;
  1031. while (!RegEnumValue(hkey,
  1032. dwIndex++, // Index'th value name/data
  1033. szTemp, // Ptr to ValueName buffer
  1034. &dwBufz, // Size of ValueName buffer
  1035. NULL, // Title index return
  1036. &dwType, // Type code of entry
  1037. NULL, // Ptr to ValueData buffer
  1038. NULL)) // Size of ValueData buffer
  1039. {
  1040. if ((dwType == REG_SZ) || (dwType == REG_EXPAND_SZ))
  1041. {
  1042. REGVAL* prvRegValNew = (REGVAL *) LocalAlloc (LPTR, sizeof(REGVAL));
  1043. if (prvRegValNew)
  1044. {
  1045. prvRegValNew->szValueName = StrDup(szTemp);
  1046. if (!prvRegValNew->szValueName)
  1047. {
  1048. LocalFree(prvRegValNew);
  1049. }
  1050. else
  1051. {
  1052. if (prvFirst)
  1053. {
  1054. prvRegVal->prvNext = prvRegValNew;
  1055. prvRegVal = prvRegVal->prvNext;
  1056. }
  1057. else
  1058. {
  1059. prvFirst = prvRegVal = prvRegValNew;
  1060. }
  1061. }
  1062. }
  1063. }
  1064. dwBufz = ARRAYSIZE(szTemp);
  1065. }
  1066. // Now traverse the list, deleting them all
  1067. prvRegVal = prvFirst;
  1068. while (prvRegVal)
  1069. {
  1070. RegDeleteValue (hkey, prvRegVal->szValueName);
  1071. LocalFree (prvRegVal->szValueName);
  1072. prvFirst = prvRegVal;
  1073. prvRegVal = prvRegVal->prvNext;
  1074. LocalFree ((LPVOID) prvFirst);
  1075. }
  1076. }
  1077. void
  1078. EVSave(
  1079. IN HWND hDlg
  1080. )
  1081. /*++
  1082. Routine Description:
  1083. Saves the environment variables in the registry
  1084. Arguments:
  1085. hDlg -
  1086. Supplies window handle
  1087. Return Value:
  1088. None
  1089. --*/
  1090. {
  1091. int selection;
  1092. int i, n;
  1093. TCHAR *bBuffer;
  1094. TCHAR *pszTemp;
  1095. HWND hwndTemp;
  1096. ENVARS *penvar;
  1097. HKEY hkeyEnv;
  1098. DWORD dwBufz, dwIndex, dwType;
  1099. LV_ITEM item;
  1100. HourGlass (TRUE);
  1101. /////////////////////////////////////////////////////////////////
  1102. // Set all new USER environment variables to current values
  1103. // but delete all old environment variables first
  1104. /////////////////////////////////////////////////////////////////
  1105. if (RegOpenKeyEx (HKEY_CURRENT_USER, szUserEnv, 0,
  1106. KEY_READ | KEY_WRITE | DELETE, &hkeyEnv)
  1107. == ERROR_SUCCESS)
  1108. {
  1109. _DeleteEnvVars(hkeyEnv);
  1110. ///////////////////////////////////////////////////////////////
  1111. // Set all new USER environment variables to current values
  1112. ///////////////////////////////////////////////////////////////
  1113. hwndTemp = GetDlgItem (hDlg, IDC_ENVVAR_SYS_LB_USERVARS);
  1114. if ((n = (int)SendMessage (hwndTemp, LVM_GETITEMCOUNT, 0, 0L)) != LB_ERR)
  1115. {
  1116. item.mask = LVIF_PARAM;
  1117. item.iSubItem = 0;
  1118. for (i = 0; i < n; i++)
  1119. {
  1120. item.iItem = i;
  1121. if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1122. penvar = (ENVARS *) item.lParam;
  1123. } else {
  1124. penvar = NULL;
  1125. }
  1126. if (penvar) {
  1127. if (RegSetValueEx (hkeyEnv,
  1128. penvar->szValueName,
  1129. 0L,
  1130. penvar->dwType,
  1131. (LPBYTE) penvar->szValue,
  1132. (lstrlen (penvar->szValue)+1) * sizeof(TCHAR)))
  1133. {
  1134. // Report error trying to set registry values
  1135. if (MsgBoxParam (hDlg, IsUserAnAdmin() ? IDS_SYSDM_NONEW_ENV_UNK : IDS_SYSDM_NONEW_ENV_NOTADMIN, IDS_SYSDM_TITLE,
  1136. MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
  1137. break;
  1138. }
  1139. }
  1140. }
  1141. }
  1142. RegFlushKey (hkeyEnv);
  1143. RegCloseKey (hkeyEnv);
  1144. }
  1145. else
  1146. {
  1147. // Report opening USER Environment key
  1148. if (MsgBoxParam (hDlg, IsUserAnAdmin() ? IDS_SYSDM_NOOPEN_USER_UNK : IDS_SYSDM_NOOPEN_USER_NOTADMIN, IDS_SYSDM_TITLE,
  1149. MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
  1150. goto Exit;
  1151. }
  1152. /////////////////////////////////////////////////////////////////
  1153. // Set all new SYSTEM environment variables to current values
  1154. // but delete all old environment variables first
  1155. /////////////////////////////////////////////////////////////////
  1156. if (!bEditSystemVars)
  1157. goto SkipSystemVars;
  1158. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  1159. szSysEnv,
  1160. 0,
  1161. KEY_READ | KEY_WRITE | DELETE,
  1162. &hkeyEnv)
  1163. == ERROR_SUCCESS)
  1164. {
  1165. _DeleteEnvVars(hkeyEnv);
  1166. ///////////////////////////////////////////////////////////////
  1167. // Set all new SYSTEM environment variables to current values
  1168. ///////////////////////////////////////////////////////////////
  1169. hwndTemp = GetDlgItem (hDlg, IDC_ENVVAR_SYS_LB_SYSVARS);
  1170. if ((n = (int)SendMessage (hwndTemp, LVM_GETITEMCOUNT, 0, 0L)) != LB_ERR)
  1171. {
  1172. item.mask = LVIF_PARAM;
  1173. item.iSubItem = 0;
  1174. for (i = 0; i < n; i++)
  1175. {
  1176. item.iItem = i;
  1177. if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1178. penvar = (ENVARS *) item.lParam;
  1179. } else {
  1180. penvar = NULL;
  1181. }
  1182. if (penvar) {
  1183. if (RegSetValueEx (hkeyEnv,
  1184. penvar->szValueName,
  1185. 0L,
  1186. penvar->dwType,
  1187. (LPBYTE) penvar->szValue,
  1188. (lstrlen (penvar->szValue)+1) * sizeof(TCHAR)))
  1189. {
  1190. // Report error trying to set registry values
  1191. if (MsgBoxParam (hDlg, IsUserAnAdmin() ? IDS_SYSDM_NONEW_ENV_UNK : IDS_SYSDM_NONEW_ENV_NOTADMIN, IDS_SYSDM_TITLE,
  1192. MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
  1193. break;
  1194. }
  1195. }
  1196. }
  1197. }
  1198. RegFlushKey (hkeyEnv);
  1199. RegCloseKey (hkeyEnv);
  1200. }
  1201. else
  1202. {
  1203. // Report opening SYSTEM Environment key
  1204. if (MsgBoxParam (hDlg, IsUserAnAdmin() ? IDS_SYSDM_NOOPEN_SYS_UNK : IDS_SYSDM_NOOPEN_SYS_NOTADMIN, IDS_SYSDM_TITLE,
  1205. MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
  1206. goto Exit;
  1207. }
  1208. SkipSystemVars:
  1209. // Send public message announcing change to Environment
  1210. SendMessageTimeout( (HWND)-1, WM_WININICHANGE, 0L, (LPARAM)szUserEnv,
  1211. SMTO_ABORTIFHUNG, 1000, NULL );
  1212. // the folllowing block will send a message to all terminal server session
  1213. // if and only if this is a NT5 and terminal services has been enabled.
  1214. if ( IsUserAnAdmin() )
  1215. {
  1216. HANDLE hwinStaLib;
  1217. // if this is an NT5, then we get a valid handle to winsta.dll library
  1218. // and the function pointer will be valid/initialized
  1219. hwinStaLib = InitializeHydraInterface();
  1220. if ( hwinStaLib)
  1221. {
  1222. // these are not used
  1223. DWORD dwRecipients=0;
  1224. LONG dwResponse=0;
  1225. // Broadcast the message to all hydra sessions (if any)
  1226. fp_WinStaBroadcastSystemMessage( SERVERNAME_CURRENT, TRUE, 0,
  1227. 1 /*timeout in seconds*/ , BSF_NOHANG,
  1228. &dwRecipients,
  1229. WM_WININICHANGE, 0L,
  1230. (LPARAM)szUserEnv,
  1231. &dwResponse );
  1232. //Close the handle to Winsta
  1233. FreeLibrary (hwinStaLib);
  1234. }
  1235. }
  1236. Exit:
  1237. HourGlass (FALSE);
  1238. }
  1239. void
  1240. EVCleanUp(
  1241. IN HWND hDlg
  1242. )
  1243. /*++
  1244. Routine Description:
  1245. Frees memory allocated for environment variables
  1246. Arguments:
  1247. hDlg -
  1248. Supplies window handle
  1249. Return Value:
  1250. None.
  1251. --*/
  1252. {
  1253. int i, n;
  1254. HWND hwndTemp;
  1255. ENVARS *penvar;
  1256. LV_ITEM item;
  1257. //
  1258. // Free alloc'd strings and memory for UserEnvVars list box items
  1259. //
  1260. hwndTemp = GetDlgItem (hDlg, IDC_ENVVAR_SYS_LB_USERVARS);
  1261. n = (int)SendMessage (hwndTemp, LVM_GETITEMCOUNT, 0, 0L);
  1262. item.mask = LVIF_PARAM;
  1263. item.iSubItem = 0;
  1264. for (i = 0; i < n; i++) {
  1265. item.iItem = i;
  1266. if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1267. penvar = (ENVARS *) item.lParam;
  1268. } else {
  1269. penvar = NULL;
  1270. }
  1271. if (penvar) {
  1272. LocalFree (penvar->szValueName);
  1273. LocalFree (penvar->szValue);
  1274. LocalFree (penvar->szExpValue);
  1275. LocalFree ((LPVOID) penvar);
  1276. }
  1277. }
  1278. //
  1279. // Free alloc'd strings and memory for SysEnvVars list box items
  1280. //
  1281. hwndTemp = GetDlgItem (hDlg, IDC_ENVVAR_SYS_LB_SYSVARS);
  1282. n = (int)SendMessage (hwndTemp, LVM_GETITEMCOUNT, 0, 0L);
  1283. for (i = 0; i < n; i++) {
  1284. item.iItem = i;
  1285. if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
  1286. penvar = (ENVARS *) item.lParam;
  1287. } else {
  1288. penvar = NULL;
  1289. }
  1290. if (penvar) {
  1291. LocalFree (penvar->szValueName);
  1292. LocalFree (penvar->szValue);
  1293. LocalFree (penvar->szExpValue);
  1294. LocalFree ((LPVOID) penvar);
  1295. }
  1296. }
  1297. }
  1298. BOOL
  1299. ExpandSystemVar(
  1300. IN LPCTSTR pszSrc,
  1301. OUT LPTSTR pszDst,
  1302. IN DWORD cchDst
  1303. )
  1304. /*++
  1305. Routine Description:
  1306. Private version of ExpandEnvironmentStrings() which only expands
  1307. references to the variables "SystemRoot" and "SystemDrive".
  1308. This behavior is intended to match the way SMSS expands system
  1309. environment variables.
  1310. Arguments:
  1311. pszSrc -
  1312. Supplies the system variable value to be expanded.
  1313. pszDst -
  1314. Returns the expanded system variable value.
  1315. cchDst -
  1316. Supplies the size, in characters, of the buffer pointed to
  1317. by pszDst
  1318. Return Value:
  1319. TRUE if there was room in the supplied buffer for the entire
  1320. expanded string.
  1321. FALSE if there was insufficient space in the supplied buffer
  1322. for the entire expanded string.
  1323. --*/
  1324. {
  1325. TCHAR ch;
  1326. LPTSTR p;
  1327. TCHAR szVar[BUFZ];
  1328. DWORD cch;
  1329. do {
  1330. ch = *pszSrc++;
  1331. if (ch != TEXT('%') ) {
  1332. // no space left, truncate string and return false
  1333. if (--cchDst == 0) {
  1334. *pszDst = TEXT('\0');
  1335. return FALSE;
  1336. }
  1337. *pszDst++ = ch;
  1338. } else {
  1339. /*
  1340. * Expand variable
  1341. */
  1342. // look for the next '%'
  1343. p = szVar;
  1344. while( *pszSrc != TEXT('\0') && *pszSrc != TEXT('%') )
  1345. *p++ = *pszSrc++;
  1346. *p = TEXT('\0');
  1347. if (*pszSrc == TEXT('\0')) {
  1348. // end of string, first '%' must be literal
  1349. cch = lstrlen(szVar) + 1;
  1350. // no more space, return false
  1351. if (cch + 1 > cchDst) {
  1352. *pszDst++ = TEXT('\0');
  1353. return FALSE;
  1354. }
  1355. *pszDst++ = TEXT('%');
  1356. CopyMemory( pszDst, szVar, cch * sizeof(TCHAR));
  1357. return TRUE;
  1358. } else {
  1359. // we found the ending '%' sign, expand that string
  1360. //
  1361. // We're expanding a SYSTEM variable, so only expand
  1362. // references to SystemRoot and SystemDrive.
  1363. //
  1364. if ((!lstrcmpi(szVar, SYSTEMROOT)) || (!lstrcmpi(szVar, SYSTEMDRIVE))) {
  1365. cch = GetEnvironmentVariable(szVar, pszDst, cchDst);
  1366. } /* if */
  1367. else {
  1368. cch = 0;
  1369. } /* else */
  1370. if (cch == 0 || cch >= cchDst) {
  1371. //String didn't expand, copy it as a literal
  1372. cch = lstrlen(szVar);
  1373. // no space left, trunc string and return FALSE
  1374. if (cch + 2 + 1 > cchDst ) {
  1375. *pszDst = TEXT('\0');
  1376. return FALSE;
  1377. }
  1378. *pszDst++ = TEXT('%');
  1379. CopyMemory(pszDst, szVar, cch * sizeof(TCHAR));
  1380. pszDst += cch;
  1381. *pszDst++ = TEXT('%');
  1382. // cchDst -= two %'s and the string
  1383. cchDst -= (2 + cch);
  1384. } else {
  1385. // string was expanded in place, bump pointer past its end
  1386. pszDst += cch;
  1387. cchDst -= cch;
  1388. }
  1389. // continue with next char after ending '%'
  1390. pszSrc++;
  1391. }
  1392. }
  1393. } while( ch != TEXT('\0') );
  1394. return TRUE;
  1395. }