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.

896 lines
27 KiB

  1. //*********************************************************************
  2. //* Microsoft Windows **
  3. //* Copyright(c) Microsoft Corp., 1993 **
  4. //*********************************************************************
  5. #include "admincfg.h"
  6. UINT LoadUsersFromKey(HWND hwndList,HKEY hkeyRoot,TABLEENTRY * pTableEntry,
  7. DWORD dwType);
  8. UINT LoadOneEntry(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
  9. TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD *pdwFoundSettings);
  10. UINT LoadUserData(USERDATA ** ppUserData,HGLOBAL hTable,HKEY hkeyRoot,
  11. TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD *pdwFoundSettings);
  12. UINT LoadPolicy(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
  13. TCHAR * pszCurrentKeyName,HGLOBAL hUser);
  14. UINT LoadSettings(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
  15. TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD *pdwFoundSettings);
  16. UINT LoadListboxData(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
  17. TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD * pdwFound);
  18. BOOL ReadStandardValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
  19. TABLEENTRY * pTableEntry,DWORD * pdwData,DWORD * pdwFound);
  20. BOOL ReadCustomValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
  21. TCHAR * pszValue,UINT cbValue,DWORD * pdwValue,DWORD * pdwFlags);
  22. BOOL CompareCustomValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
  23. STATEVALUE * pStateValue,DWORD * pdwFound);
  24. // flags for detected settings
  25. #define FS_PRESENT 0x0001
  26. #define FS_DELETED 0x0002
  27. /*******************************************************************
  28. NAME: LoadFile
  29. SYNOPSIS: Loads the specified policy file
  30. ********************************************************************/
  31. BOOL LoadFile(TCHAR * pszFilename,HWND hwndApp,HWND hwndList,BOOL fDisplayErrors)
  32. {
  33. HKEY hkeyMain=NULL,hkeyUser=NULL,hkeyWorkstation=NULL,hkeyGroup=NULL,hkeyGroupPriority=NULL;
  34. UINT uRet;
  35. OFSTRUCT of;
  36. HCURSOR hOldCursor;
  37. HFILE hFile;
  38. of.cBytes = sizeof(of);
  39. hOldCursor=SetCursor(LoadCursor(NULL,IDC_WAIT));
  40. // RegLoadKey returns totally coarse error codes, so first do
  41. // an open file on the file to get a sane error message if there's
  42. // a problem
  43. hFile = OpenFile(pszFilename,&of,OF_EXIST);
  44. if (hFile == HFILE_ERROR) {
  45. SetCursor(hOldCursor);
  46. if (fDisplayErrors)
  47. DisplayStandardError(hwndApp,pszFilename,IDS_ErrREGERR_LOADKEY1,
  48. of.nErrCode);
  49. return FALSE;
  50. }
  51. // Not needed. This will raise an exception.
  52. // _lclose (hFile);
  53. // load the hive file
  54. if ((uRet = MyRegLoadKey(HKEY_LOCAL_MACHINE,szTMPDATA,pszFilename))
  55. != ERROR_SUCCESS) {
  56. SetCursor(hOldCursor);
  57. if (fDisplayErrors)
  58. DisplayStandardError(hwndApp,pszFilename,IDS_ErrREGERR_LOADKEY1,uRet);
  59. return FALSE;
  60. }
  61. // read information from local registry
  62. if ( (RegOpenKey(HKEY_LOCAL_MACHINE,szTMPDATA,&hkeyMain) !=
  63. ERROR_SUCCESS) ||
  64. (RegOpenKey(hkeyMain,szUSERS,&hkeyUser) != ERROR_SUCCESS) ||
  65. (RegOpenKey(hkeyMain,szWORKSTATIONS,&hkeyWorkstation)
  66. != ERROR_SUCCESS)) {
  67. SetCursor(hOldCursor);
  68. if (fDisplayErrors)
  69. MsgBoxParam(hwndApp,IDS_ErrINVALIDPOLICYFILE,pszFilename,
  70. MB_ICONEXCLAMATION,MB_OK);
  71. if (hkeyWorkstation) RegCloseKey(hkeyWorkstation);
  72. if (hkeyUser) RegCloseKey(hkeyUser);
  73. if (hkeyMain) RegCloseKey(hkeyMain);
  74. MyRegUnLoadKey(HKEY_LOCAL_MACHINE,szTMPDATA);
  75. return FALSE;
  76. }
  77. // if we fail to open these two keys no big deal, these are optional keys.
  78. // HKEYs are checked below before we use them
  79. RegOpenKey(hkeyMain,szUSERGROUPS,&hkeyGroup);
  80. RegOpenKey(hkeyMain,szUSERGROUPDATA,&hkeyGroupPriority);
  81. // load users
  82. if ((uRet = LoadUsersFromKey(hwndList,hkeyUser,gClassList.pUserCategoryList,
  83. UT_USER)) != ERROR_SUCCESS)
  84. goto cleanup;
  85. // load workstations
  86. if ((uRet = LoadUsersFromKey(hwndList,hkeyWorkstation,gClassList.pMachineCategoryList,
  87. UT_MACHINE))
  88. != ERROR_SUCCESS)
  89. goto cleanup;
  90. #ifdef INCL_GROUP_SUPPORT
  91. // load groups
  92. if (hkeyGroupPriority && hkeyGroup) {
  93. if ((uRet = LoadGroupPriorityList(hkeyGroupPriority,hkeyGroup)) != ERROR_SUCCESS)
  94. goto cleanup;
  95. if (uRet = LoadUsersFromKey(hwndList,hkeyGroup,gClassList.pUserCategoryList,
  96. UT_USER | UF_GROUP)
  97. != ERROR_SUCCESS)
  98. goto cleanup;
  99. }
  100. #endif
  101. uRet = ERROR_SUCCESS;
  102. cleanup:
  103. RegCloseKey(hkeyUser);
  104. RegCloseKey(hkeyWorkstation);
  105. RegCloseKey(hkeyMain);
  106. if (hkeyGroup)
  107. RegCloseKey(hkeyGroup);
  108. if (hkeyGroupPriority)
  109. RegCloseKey(hkeyGroupPriority);
  110. MyRegUnLoadKey(HKEY_LOCAL_MACHINE,szTMPDATA);
  111. SetFileAttributes(pszFilename,FILE_ATTRIBUTE_ARCHIVE);
  112. ClearDeletedUserList();
  113. SetCursor(hOldCursor);
  114. if (uRet != ERROR_SUCCESS && fDisplayErrors) {
  115. if (uRet == ERROR_NOT_ENOUGH_MEMORY) {
  116. MsgBox(hwndApp,IDS_ErrOUTOFMEMORY,MB_ICONEXCLAMATION,MB_OK);
  117. } else {
  118. TCHAR szFmt[REGBUFLEN],szMsg[REGBUFLEN+MAX_PATH+1];
  119. LoadSz(IDS_ErrREGERR_LOADKEY,szFmt,ARRAYSIZE(szFmt));
  120. wsprintf(szMsg,szFmt,pszFilename,uRet);
  121. MsgBoxSz(hwndApp,szMsg,MB_ICONEXCLAMATION,MB_OK);
  122. }
  123. // remove any users that might have gotten loaded
  124. RemoveAllUsers(hwndList);
  125. }
  126. return (uRet == ERROR_SUCCESS);
  127. }
  128. /*******************************************************************
  129. NAME: LoadFromRegistry
  130. SYNOPSIS: Loads policies from the registry
  131. NOTES: Errors will be displayed if fDisplayErrors is TRUE.
  132. ********************************************************************/
  133. BOOL LoadFromRegistry(HWND hwndApp,HWND hwndList,BOOL fDisplayErrors)
  134. {
  135. HKEY hkeyUser=NULL,hkeyWorkstation=NULL;
  136. UINT uRet = ERROR_SUCCESS;
  137. HGLOBAL hUser,hWorkstation;
  138. USERDATA * pUserData=NULL,* pWorkstationData=NULL;
  139. HCURSOR hOldCursor;
  140. if ((RegOpenKeyEx(hkeyVirtHCU,NULL,0,KEY_ALL_ACCESS,&hkeyUser) != ERROR_SUCCESS) ||
  141. (RegOpenKeyEx(hkeyVirtHLM,NULL,0,KEY_ALL_ACCESS,&hkeyWorkstation) != ERROR_SUCCESS)) {
  142. if (fDisplayErrors)
  143. MsgBox(hwndApp,IDS_ErrCANTOPENREGISTRY,MB_ICONEXCLAMATION,MB_OK);
  144. if (hkeyUser) RegCloseKey(hkeyUser);
  145. if (hkeyWorkstation) RegCloseKey(hkeyWorkstation);
  146. return FALSE;
  147. }
  148. hUser = AddUser(hwndList,LoadSz(IDS_LOCALUSER,szSmallBuf,ARRAYSIZE(szSmallBuf))
  149. ,UT_USER);
  150. hWorkstation = AddUser(hwndList,LoadSz(IDS_LOCALCOMPUTER,szSmallBuf,
  151. ARRAYSIZE(szSmallBuf)),UT_MACHINE);
  152. if (!hUser || !hWorkstation || !(pUserData = (USERDATA *) GlobalLock(hUser)) ||
  153. !(pWorkstationData = (USERDATA *) GlobalLock(hWorkstation)) ) {
  154. uRet = ERROR_NOT_ENOUGH_MEMORY;
  155. }
  156. hOldCursor=SetCursor(LoadCursor(NULL,IDC_WAIT));
  157. if (uRet == ERROR_SUCCESS)
  158. uRet = LoadUserData(&pUserData,gClassList.pUserCategoryList,hkeyUser,NULL,
  159. hUser,NULL);
  160. if (uRet == ERROR_SUCCESS)
  161. uRet = LoadUserData(&pWorkstationData,gClassList.pMachineCategoryList,
  162. hkeyWorkstation,NULL,hWorkstation,NULL);
  163. RegCloseKey(hkeyUser);
  164. RegCloseKey(hkeyWorkstation);
  165. GlobalUnlock(hUser);
  166. GlobalUnlock(hWorkstation);
  167. SetCursor(hOldCursor);
  168. if (uRet != ERROR_SUCCESS) {
  169. if (uRet == ERROR_NOT_ENOUGH_MEMORY) {
  170. if (fDisplayErrors)
  171. MsgBox(hwndApp,IDS_ErrOUTOFMEMORY,MB_ICONEXCLAMATION,MB_OK);
  172. } else {
  173. TCHAR szMsg[REGBUFLEN+1];
  174. wsprintf(szMsg,TEXT("%lu"),uRet);
  175. if (fDisplayErrors)
  176. MsgBoxParam(hwndApp,IDS_ErrREGERR_LOAD,szMsg,MB_ICONEXCLAMATION,MB_OK);
  177. }
  178. RemoveAllUsers(hwndList);
  179. return FALSE;
  180. }
  181. ClearDeletedUserList();
  182. return TRUE;
  183. }
  184. UINT LoadUsersFromKey(HWND hwndList,HKEY hkeyRoot,TABLEENTRY * pTableEntry,
  185. DWORD dwType)
  186. {
  187. TCHAR szKeyName[MAX_PATH+1];
  188. UINT uRet,nIndex=0;
  189. HGLOBAL hUser;
  190. USERDATA * pUserData;
  191. HKEY hKey;
  192. TCHAR szUnmappedName[MAXNAMELEN+1];
  193. do {
  194. // enumerate the subkeys, which will be user/workstation names
  195. if ((uRet=RegEnumKey(hkeyRoot,nIndex,szKeyName,ARRAYSIZE(szKeyName)))
  196. == ERROR_SUCCESS) {
  197. // open the subkey
  198. if ((uRet = RegOpenKey(hkeyRoot,szKeyName,&hKey)) != ERROR_SUCCESS)
  199. return uRet;
  200. // allocate this user and add to list control
  201. UnmapUserName(szKeyName,szUnmappedName,(BOOL) (dwType & UT_USER));
  202. hUser = AddUser(hwndList,szUnmappedName,dwType);
  203. if ( !hUser || !(pUserData = (USERDATA *) GlobalLock(hUser))) {
  204. RegCloseKey(hKey);
  205. return ERROR_NOT_ENOUGH_MEMORY;
  206. }
  207. // load user data into user's buffer
  208. uRet=LoadUserData(&pUserData,pTableEntry,hKey,NULL,hUser,NULL);
  209. #ifdef INCL_GROUP_SUPPORT
  210. // add group name to bottom of priority list. The group name
  211. // should already be somewhere on priority list because we loaded
  212. // the list earlier, but this will add the group name to the bottom
  213. // of the list if it's not on the list already. Adds extra robustness
  214. // in the face of god-knows-whose-app creating flaky policy files.
  215. if (dwType == (UT_USER | UF_GROUP))
  216. AddGroupPriEntry(szUnmappedName);
  217. #endif
  218. RegCloseKey(hKey);
  219. GlobalUnlock(hUser);
  220. // make a copy of the initial state of each user, so on
  221. // a save we only have to save the deltas. We need to only
  222. // save the deltas, because saves have to be non-destructive--
  223. // we can't clean the user's tree out and start over because
  224. // there might be stuff in there we don't know about.
  225. CloneUser(hUser);
  226. if (uRet != ERROR_SUCCESS) return uRet;
  227. }
  228. nIndex++;
  229. } while (uRet == ERROR_SUCCESS);
  230. // end of enum will report ERROR_NO_MORE_ITEMS, don't report this as error
  231. if (uRet == ERROR_NO_MORE_ITEMS) uRet = ERROR_SUCCESS;
  232. return uRet;
  233. }
  234. UINT LoadUserData(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
  235. TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD *pdwFoundSettings)
  236. {
  237. UINT uRet=ERROR_SUCCESS;
  238. while (pTableEntry && (uRet == ERROR_SUCCESS)) {
  239. uRet = LoadOneEntry(ppUserData,pTableEntry,hkeyRoot,
  240. pszCurrentKeyName,hUser,pdwFoundSettings);
  241. pTableEntry = pTableEntry->pNext;
  242. }
  243. return uRet;
  244. }
  245. UINT LoadOneEntry(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
  246. TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD *pdwFoundSettings)
  247. {
  248. UINT uRet;
  249. #if 0
  250. wsprintf(szDebugOut,TEXT("LoadOneEntry: %s\r\n"),GETNAMEPTR(pTableEntry));
  251. OutputDebugString(szDebugOut);
  252. #endif
  253. // if there is a key name for this entry, it becomes the "current"
  254. // key name-- it will be overridden if child entries specify their
  255. // own keys, otherwise it's the default key for children to use
  256. if (pTableEntry->uOffsetKeyName) {
  257. pszCurrentKeyName = GETKEYNAMEPTR(pTableEntry);
  258. }
  259. if ((pTableEntry->dwType == ETYPE_CATEGORY || pTableEntry->dwType
  260. == ETYPE_ROOT) &&
  261. (pTableEntry->pChild)) {
  262. // if entry is a category, recusively process sub-categories and policies
  263. if ((uRet=LoadUserData(ppUserData,pTableEntry->pChild,
  264. hkeyRoot,pszCurrentKeyName,hUser,pdwFoundSettings)) != ERROR_SUCCESS) {
  265. return uRet;
  266. }
  267. } else if (pTableEntry->dwType == ETYPE_POLICY) {
  268. if ((uRet = LoadPolicy(ppUserData,pTableEntry,hkeyRoot,
  269. pszCurrentKeyName,hUser)) != ERROR_SUCCESS) {
  270. return uRet;
  271. }
  272. } else if ( (pTableEntry->dwType & ETYPE_MASK) == ETYPE_SETTING
  273. && !(pTableEntry->dwType & STYPE_TEXT)) {
  274. if ((uRet = LoadSettings(ppUserData,pTableEntry,hkeyRoot,
  275. pszCurrentKeyName,hUser,pdwFoundSettings)) != ERROR_SUCCESS) {
  276. return uRet;
  277. }
  278. }
  279. return ERROR_SUCCESS;
  280. }
  281. UINT LoadPolicy(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
  282. TCHAR * pszCurrentKeyName,HGLOBAL hUser)
  283. {
  284. DWORD dwData=0;
  285. UINT uRet;
  286. TCHAR * pszValueName;
  287. DWORD dwFoundSettings=0;
  288. BOOL fHasPolicySwitch=FALSE;
  289. BOOL fFound=FALSE,fCustomOn=FALSE,fCustomOff=FALSE;
  290. // get the name of the value to read, if any
  291. if (((POLICY *) pTableEntry)->uOffsetValueName) {
  292. fHasPolicySwitch = TRUE;
  293. pszValueName = GETVALUENAMEPTR(((POLICY *) pTableEntry));
  294. // first look for custom on/off values
  295. if (((POLICY *) pTableEntry)->uOffsetValue_On) {
  296. fCustomOn = TRUE;
  297. if (CompareCustomValue(hkeyRoot,pszCurrentKeyName,pszValueName,
  298. (STATEVALUE *) ((TCHAR *) pTableEntry + ((POLICY *)
  299. pTableEntry)->uOffsetValue_On),&dwFoundSettings)) {
  300. dwData = 1;
  301. fFound = TRUE;
  302. }
  303. }
  304. if (!fFound && ((POLICY *) pTableEntry)->uOffsetValue_Off) {
  305. fCustomOff = TRUE;
  306. if (CompareCustomValue(hkeyRoot,pszCurrentKeyName,pszValueName,
  307. (STATEVALUE *) ((TCHAR *) pTableEntry + ((POLICY *)
  308. pTableEntry)->uOffsetValue_Off),&dwFoundSettings)) {
  309. dwData = 0;
  310. fFound = TRUE;
  311. }
  312. }
  313. // look for standard values if custom values have not been specified
  314. if (!fCustomOn && !fCustomOff &&
  315. ReadStandardValue(hkeyRoot,pszCurrentKeyName,pszValueName,
  316. pTableEntry,&dwData,&dwFoundSettings)) {
  317. fFound = TRUE;
  318. }
  319. if (fFound) {
  320. // store data in user's buffer
  321. (*ppUserData)->SettingData[((POLICY *) pTableEntry)->uDataIndex].uData =
  322. (dwData ? IMG_CHECKED : IMG_UNCHECKED);
  323. }
  324. }
  325. dwFoundSettings = 0;
  326. // process settings underneath this policy (if any)
  327. if (pTableEntry->pChild && (dwData || !fHasPolicySwitch)) {
  328. if ((uRet=LoadUserData(ppUserData,pTableEntry->pChild,hkeyRoot,
  329. pszCurrentKeyName,hUser,&dwFoundSettings)) !=ERROR_SUCCESS) {
  330. return uRet;
  331. }
  332. }
  333. if (!fHasPolicySwitch) {
  334. // store data in user's buffer
  335. if (dwFoundSettings) {
  336. (*ppUserData)->SettingData[((POLICY *) pTableEntry)->uDataIndex].uData =
  337. (dwFoundSettings & FS_PRESENT ? IMG_CHECKED : IMG_UNCHECKED);
  338. }
  339. }
  340. return ERROR_SUCCESS;
  341. }
  342. UINT LoadSettings(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
  343. TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD * pdwFound)
  344. {
  345. UINT uRet = ERROR_SUCCESS;
  346. TCHAR * pszValueName = NULL;
  347. DWORD dwData,dwFlags,dwFoundSettings=0;
  348. TCHAR szData[MAXSTRLEN];
  349. BOOL fCustomOn=FALSE,fCustomOff=FALSE,fFound=FALSE;
  350. TCHAR * pObjectData = GETOBJECTDATAPTR(((SETTINGS *)pTableEntry));
  351. TCHAR szNewValueName[MAX_PATH+1];
  352. // get the name of the value to read
  353. if (((SETTINGS *) pTableEntry)->uOffsetValueName) {
  354. pszValueName = GETVALUENAMEPTR(((SETTINGS *) pTableEntry));
  355. }
  356. else return ERROR_NOT_ENOUGH_MEMORY;
  357. switch (pTableEntry->dwType & STYPE_MASK) {
  358. case STYPE_EDITTEXT:
  359. case STYPE_COMBOBOX:
  360. dwFlags = ( (SETTINGS *) pTableEntry)->dwFlags;
  361. // add prefixes if appropriate
  362. PrependValueName(pszValueName,dwFlags,
  363. szNewValueName,ARRAYSIZE(szNewValueName));
  364. if ((uRet = ReadRegistryStringValue(hkeyRoot,pszCurrentKeyName,
  365. szNewValueName,szData,ARRAYSIZE(szData) * sizeof(TCHAR))) == ERROR_SUCCESS) {
  366. GlobalUnlock(hUser);
  367. if (!SetVariableLengthData(hUser,((SETTINGS *)
  368. pTableEntry)->uDataIndex,szData,lstrlen(szData)+1)) {
  369. return ERROR_NOT_ENOUGH_MEMORY;
  370. }
  371. if (!((*ppUserData) = (USERDATA *) GlobalLock(hUser)))
  372. return ERROR_NOT_ENOUGH_MEMORY;
  373. // set flag that we found setting in registry/policy file
  374. if (pdwFound)
  375. *pdwFound |= FS_PRESENT;
  376. } else if ((dwAppState & AS_POLICYFILE) && !(dwFlags & VF_DELETE)) {
  377. // see if this key is marked as deleted
  378. PrependValueName(pszValueName,VF_DELETE,
  379. szNewValueName,ARRAYSIZE(szNewValueName));
  380. if ((uRet = ReadRegistryStringValue(hkeyRoot,pszCurrentKeyName,
  381. szNewValueName,szData,ARRAYSIZE(szData) * sizeof(TCHAR))) == ERROR_SUCCESS) {
  382. // set flag that we found setting marked as deleted in
  383. // policy file
  384. if (pdwFound)
  385. *pdwFound |= FS_DELETED;
  386. }
  387. }
  388. return ERROR_SUCCESS;
  389. break;
  390. case STYPE_CHECKBOX:
  391. // first look for custom on/off values
  392. if (((CHECKBOXINFO *) pObjectData)->uOffsetValue_On) {
  393. fCustomOn = TRUE;
  394. if (CompareCustomValue(hkeyRoot,pszCurrentKeyName,pszValueName,
  395. (STATEVALUE *) ((TCHAR *) pTableEntry + ((CHECKBOXINFO *)
  396. pObjectData)->uOffsetValue_On),&dwFoundSettings)) {
  397. dwData = 1;
  398. fFound = TRUE;
  399. }
  400. }
  401. if (!fFound && ((CHECKBOXINFO *) pObjectData)->uOffsetValue_Off) {
  402. fCustomOff = TRUE;
  403. if (CompareCustomValue(hkeyRoot,pszCurrentKeyName,pszValueName,
  404. (STATEVALUE *) ((TCHAR *) pTableEntry + ((CHECKBOXINFO *)
  405. pObjectData)->uOffsetValue_Off),&dwFoundSettings)) {
  406. dwData = 0;
  407. fFound = TRUE;
  408. }
  409. }
  410. // look for standard values if custom values have not been specified
  411. if (!fFound &&
  412. ReadStandardValue(hkeyRoot,pszCurrentKeyName,pszValueName,
  413. pTableEntry,&dwData,&dwFoundSettings)) {
  414. fFound = TRUE;
  415. }
  416. if (fFound) {
  417. (*ppUserData)->SettingData[((SETTINGS *)
  418. pTableEntry)->uDataIndex].uData = dwData;
  419. // set flag that we found setting in registry
  420. if (pdwFound)
  421. *pdwFound |= dwFoundSettings;
  422. }
  423. return ERROR_SUCCESS;
  424. break;
  425. case STYPE_NUMERIC:
  426. if (ReadStandardValue(hkeyRoot,pszCurrentKeyName,pszValueName,
  427. pTableEntry,&dwData,&dwFoundSettings)) {
  428. (*ppUserData)->SettingData[((SETTINGS *)
  429. pTableEntry)->uDataIndex].uData = dwData;
  430. // set flag that we found setting in registry
  431. if (pdwFound)
  432. *pdwFound |= dwFoundSettings;
  433. }
  434. break;
  435. case STYPE_DROPDOWNLIST:
  436. if (ReadCustomValue(hkeyRoot,pszCurrentKeyName,pszValueName,
  437. szData,ARRAYSIZE(szData) * sizeof(TCHAR),&dwData,&dwFlags)) {
  438. BOOL fMatch = FALSE;
  439. if ((dwAppState & AS_POLICYFILE) &&
  440. (dwFlags & VF_DELETE)) {
  441. // set flag that we found setting marked as deleted
  442. // in policy file
  443. if (pdwFound)
  444. *pdwFound |= FS_DELETED;
  445. return ERROR_SUCCESS;
  446. }
  447. // walk the list of DROPDOWNINFO structs (one for each state),
  448. // and see if the value we found matches the value for the state
  449. if ( ((SETTINGS *) pTableEntry)->uOffsetObjectData) {
  450. DROPDOWNINFO * pddi = (DROPDOWNINFO *)
  451. GETOBJECTDATAPTR( ((SETTINGS *) pTableEntry));
  452. UINT nIndex = 0;
  453. do {
  454. if (dwFlags == pddi->dwFlags) {
  455. if (pddi->dwFlags & VF_ISNUMERIC) {
  456. if (dwData == pddi->dwValue)
  457. fMatch = TRUE;
  458. } else if (!pddi->dwFlags) {
  459. if (!lstrcmpi(szData,(TCHAR *) pTableEntry +
  460. pddi->uOffsetValue))
  461. fMatch = TRUE;
  462. }
  463. }
  464. if (!pddi->uOffsetNextDropdowninfo || fMatch)
  465. break;
  466. pddi = (DROPDOWNINFO *) ( (TCHAR *) pTableEntry +
  467. pddi->uOffsetNextDropdowninfo);
  468. nIndex++;
  469. } while (!fMatch);
  470. if (fMatch) {
  471. (*ppUserData)->SettingData[((SETTINGS *)
  472. pTableEntry)->uDataIndex].uData = nIndex;
  473. // set flag that we found setting in registry
  474. if (pdwFound)
  475. *pdwFound |= FS_PRESENT;
  476. }
  477. }
  478. }
  479. break;
  480. case STYPE_LISTBOX:
  481. return LoadListboxData(ppUserData,pTableEntry,hkeyRoot,
  482. pszCurrentKeyName,hUser,pdwFound);
  483. break;
  484. }
  485. return ERROR_SUCCESS;
  486. }
  487. /*******************************************************************
  488. NAME: ReadCustomValue
  489. SYNOPSIS: For specified keyname and value name, retrieve the
  490. value (if there is one).
  491. NOTES: fills in pszValue if value is REG_SZ, fills in *pdwValue
  492. if value is REG_DWORD (and sets VF_ISNUMERIC). Sets
  493. VF_DELETE if value is marked for deletion.
  494. ********************************************************************/
  495. BOOL ReadCustomValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
  496. TCHAR * pszValue,UINT cbValue,DWORD * pdwValue,DWORD * pdwFlags)
  497. {
  498. HKEY hKey;
  499. DWORD dwType,dwSize=cbValue * sizeof(TCHAR);
  500. BOOL fSuccess = FALSE;
  501. TCHAR szNewValueName[MAX_PATH+1];
  502. *( (DWORD *)pszValue) = *pdwValue=0;
  503. if (RegOpenKey(hkeyRoot,pszKeyName,&hKey) == ERROR_SUCCESS) {
  504. if (RegQueryValueEx(hKey,pszValueName,NULL,&dwType,(LPBYTE) pszValue,
  505. &dwSize) == ERROR_SUCCESS) {
  506. if (dwType == REG_SZ) {
  507. // value returned in pszValueName
  508. *pdwFlags = 0;
  509. fSuccess = TRUE;
  510. } else if (dwType == REG_DWORD || dwType == REG_BINARY) {
  511. // copy value to *pdwValue
  512. memcpy(pdwValue,pszValue,sizeof(DWORD));
  513. *pdwFlags = VF_ISNUMERIC;
  514. fSuccess = TRUE;
  515. }
  516. } else {
  517. // see if this is a value that's marked for deletion
  518. // (valuename is prepended with "**del."
  519. PrependValueName(pszValueName,VF_DELETE,
  520. szNewValueName,ARRAYSIZE(szNewValueName));
  521. if (RegQueryValueEx(hKey,szNewValueName,NULL,&dwType,(LPBYTE) pszValue,
  522. &dwSize) == ERROR_SUCCESS) {
  523. fSuccess=TRUE;
  524. *pdwFlags = VF_DELETE;
  525. } else {
  526. // see if this is a soft value
  527. // (valuename is prepended with "**soft."
  528. PrependValueName(pszValueName,VF_SOFT,
  529. szNewValueName,ARRAYSIZE(szNewValueName));
  530. if (RegQueryValueEx(hKey,szNewValueName,NULL,&dwType,(LPBYTE) pszValue,
  531. &dwSize) == ERROR_SUCCESS) {
  532. fSuccess=TRUE;
  533. *pdwFlags = VF_SOFT;
  534. }
  535. }
  536. }
  537. RegCloseKey(hKey);
  538. }
  539. return fSuccess;
  540. }
  541. BOOL CompareCustomValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
  542. STATEVALUE * pStateValue,DWORD * pdwFound)
  543. {
  544. TCHAR szValue[MAXSTRLEN];
  545. DWORD dwValue;
  546. TCHAR szNewValueName[MAX_PATH+1];
  547. // add prefixes if appropriate
  548. PrependValueName(pszValueName,pStateValue->dwFlags,
  549. szNewValueName,ARRAYSIZE(szNewValueName));
  550. if (pStateValue->dwFlags & VF_ISNUMERIC) {
  551. if ((ReadRegistryDWordValue(hkeyRoot,pszKeyName,
  552. szNewValueName,&dwValue) == ERROR_SUCCESS) &&
  553. dwValue == pStateValue->dwValue) {
  554. *pdwFound = FS_PRESENT;
  555. return TRUE;
  556. }
  557. } else if (pStateValue->dwFlags & VF_DELETE) {
  558. if (dwAppState & AS_POLICYFILE) {
  559. // see if this is a value that's marked for deletion
  560. // (valuename is prepended with "**del."
  561. if ((ReadRegistryStringValue(hkeyRoot,pszKeyName,
  562. szNewValueName,szValue,ARRAYSIZE(szValue) * sizeof(TCHAR))) == ERROR_SUCCESS) {
  563. *pdwFound = FS_DELETED;
  564. return TRUE;
  565. }
  566. } else {
  567. // return TRUE if value ISN't there...
  568. if (ReadRegistryDWordValue(hkeyRoot,pszKeyName,
  569. szNewValueName,&dwValue) != ERROR_SUCCESS) {
  570. *pdwFound = FS_DELETED;
  571. return TRUE;
  572. }
  573. }
  574. } else {
  575. if ((ReadRegistryStringValue(hkeyRoot,pszKeyName,
  576. szNewValueName,szValue,ARRAYSIZE(szValue) * sizeof(TCHAR))) == ERROR_SUCCESS &&
  577. !lstrcmpi(szValue,pStateValue->szValue)) {
  578. *pdwFound = FS_PRESENT;
  579. return TRUE;
  580. }
  581. }
  582. return FALSE;
  583. }
  584. BOOL ReadStandardValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
  585. TABLEENTRY * pTableEntry,DWORD * pdwData,DWORD * pdwFound)
  586. {
  587. UINT uRet;
  588. TCHAR szNewValueName[MAX_PATH+1];
  589. // add prefixes if appropriate
  590. PrependValueName(pszValueName,((SETTINGS *) pTableEntry)->dwFlags,
  591. szNewValueName,ARRAYSIZE(szNewValueName));
  592. if ( ((SETTINGS *) pTableEntry)->dwFlags & DF_TXTCONVERT) {
  593. // read numeric value as text if specified
  594. TCHAR szNum[11];
  595. uRet = ReadRegistryStringValue(hkeyRoot,pszKeyName,
  596. szNewValueName,szNum,ARRAYSIZE(szNum) * sizeof(TCHAR));
  597. if (uRet == ERROR_SUCCESS) {
  598. StringToNum(szNum,pdwData);
  599. *pdwFound = FS_PRESENT;
  600. return TRUE;
  601. }
  602. } else {
  603. // read numeric value as binary
  604. uRet = ReadRegistryDWordValue(hkeyRoot,pszKeyName,
  605. szNewValueName,pdwData);
  606. if (uRet == ERROR_SUCCESS) {
  607. *pdwFound = FS_PRESENT;
  608. return TRUE;
  609. }
  610. }
  611. // see if this settings has been marked as 'deleted'
  612. if ((dwAppState & AS_POLICYFILE) && !(dwCmdLineFlags & CLF_DIALOGMODE)) {
  613. TCHAR szVal[MAX_PATH+1];
  614. *pdwData = 0;
  615. PrependValueName(pszValueName,VF_DELETE,szNewValueName,
  616. ARRAYSIZE(szNewValueName));
  617. uRet=ReadRegistryStringValue(hkeyRoot,pszKeyName,
  618. szNewValueName,szVal,ARRAYSIZE(szVal) * sizeof(TCHAR));
  619. if (uRet == ERROR_SUCCESS) {
  620. *pdwFound = FS_DELETED;
  621. return TRUE;
  622. }
  623. }
  624. return FALSE;
  625. }
  626. UINT LoadListboxData(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
  627. TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD * pdwFound)
  628. {
  629. HKEY hKey;
  630. UINT nIndex=0,nLen;
  631. TCHAR szValueName[MAX_PATH+1],szValueData[MAX_PATH+1];
  632. DWORD cbValueName,cbValueData;
  633. DWORD dwType,dwAlloc=1024,dwUsed=0;
  634. HGLOBAL hBuf;
  635. TCHAR * pBuf;
  636. SETTINGS * pSettings = (SETTINGS *) pTableEntry;
  637. LISTBOXINFO * pListboxInfo = (LISTBOXINFO *)
  638. GETOBJECTDATAPTR(pSettings);
  639. BOOL fFoundValues=FALSE,fFoundDelvals=FALSE;
  640. UINT uRet=ERROR_SUCCESS;
  641. if (RegOpenKey(hkeyRoot,pszCurrentKeyName,&hKey) != ERROR_SUCCESS)
  642. return ERROR_SUCCESS; // nothing to do
  643. // allocate a temp buffer to read entries into
  644. if (!(hBuf = GlobalAlloc(GHND,dwAlloc * sizeof(TCHAR))) ||
  645. !(pBuf = (TCHAR *) GlobalLock(hBuf))) {
  646. if (hBuf)
  647. GlobalFree(hBuf);
  648. return ERROR_NOT_ENOUGH_MEMORY;
  649. }
  650. while (TRUE) {
  651. cbValueName=ARRAYSIZE(szValueName);
  652. cbValueData=ARRAYSIZE(szValueData) * sizeof(TCHAR);
  653. uRet=RegEnumValue(hKey,nIndex,szValueName,&cbValueName,NULL,
  654. &dwType,szValueData,&cbValueData);
  655. // stop if we're out of items
  656. if (uRet != ERROR_SUCCESS && uRet != ERROR_MORE_DATA)
  657. break;
  658. nIndex++;
  659. // if valuename prefixed with '**', it's a control code, ignore it
  660. if (szValueName[0] == TEXT('*') && szValueName[1] == TEXT('*')) {
  661. // if we found **delvals., then some sort of listbox stuff
  662. // is going on, remember that we found this code
  663. if (!lstrcmpi(szValueName,szDELVALS))
  664. fFoundDelvals = TRUE;
  665. continue;
  666. }
  667. // only process this item if enum was successful
  668. // (so we'll skip items with weird errors like ERROR_MORE_DATA and
  669. // but keep going with the enum)
  670. if (uRet == ERROR_SUCCESS) {
  671. TCHAR * pszData;
  672. // if there's no value name prefix scheme specified (e.g.
  673. // value names are "foo1", "foo2", etc), and the explicit valuename
  674. // flag isn't set where we remember the value name as well as
  675. // the data for every value, then we need the value name to
  676. // be the same as the value data ("thing.exe=thing.exe").
  677. if (!(pSettings->dwFlags & DF_EXPLICITVALNAME) &&
  678. !(pListboxInfo->uOffsetPrefix) && !(pListboxInfo->uOffsetValue)) {
  679. if (dwType != REG_SZ || lstrcmpi(szValueName,szValueData))
  680. continue; // skip this value if val name != val data
  681. }
  682. // if explicit valuenames used, then copy the value name into
  683. // buffer
  684. if (pSettings->dwFlags & DF_EXPLICITVALNAME) {
  685. nLen = lstrlen(szValueName) + 1;
  686. if (!(pBuf=ResizeBuffer(pBuf,hBuf,dwUsed+nLen+4,&dwAlloc)))
  687. return ERROR_NOT_ENOUGH_MEMORY;
  688. lstrcpy(pBuf+dwUsed,szValueName);
  689. dwUsed += nLen;
  690. }
  691. // for default listbox type, value data is the actual "data"
  692. // and value name either will be the same as the data or
  693. // some prefix + "1", "2", etc. If there's a data value to
  694. // write for each entry, then the "data" is the value name
  695. // (e.g. "Larry = foo", "Dave = foo"), etc. If explicit value names
  696. // are turned on, then both the value name and data are stored
  697. // and editable
  698. // copy value data into buffer
  699. if (pListboxInfo->uOffsetValue) {
  700. // data value set, use value name for data
  701. pszData = szValueName;
  702. } else pszData = szValueData;
  703. nLen = lstrlen(pszData) + 1;
  704. if (!(pBuf=ResizeBuffer(pBuf,hBuf,dwUsed+nLen+4,&dwAlloc)))
  705. return ERROR_NOT_ENOUGH_MEMORY;
  706. lstrcpy(pBuf+dwUsed,pszData);
  707. dwUsed += nLen;
  708. fFoundValues=TRUE;
  709. }
  710. }
  711. // doubly null-terminate the buffer... safe to do this because we
  712. // tacked on the extra "+4" in the ResizeBuffer calls above
  713. *(pBuf+dwUsed) = TEXT('\0');
  714. dwUsed++;
  715. uRet = ERROR_SUCCESS;
  716. if (fFoundValues) {
  717. // add the value data to user's buffer
  718. GlobalUnlock(hUser);
  719. if (!SetVariableLengthData(hUser,((SETTINGS *)
  720. pTableEntry)->uDataIndex,pBuf,dwUsed)) {
  721. uRet = ERROR_NOT_ENOUGH_MEMORY;
  722. } else if (!((*ppUserData) = (USERDATA *) GlobalLock(hUser)))
  723. uRet = ERROR_NOT_ENOUGH_MEMORY;
  724. // set flag that we found setting in registry/policy file
  725. if (pdwFound)
  726. *pdwFound |= FS_PRESENT;
  727. } else {
  728. if (fFoundDelvals && pdwFound) {
  729. *pdwFound |= FS_DELETED;
  730. }
  731. }
  732. GlobalUnlock(hBuf);
  733. GlobalFree(hBuf);
  734. RegCloseKey(hKey);
  735. return uRet;
  736. }