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.

519 lines
13 KiB

  1. #include <windows.h>
  2. #include "SDKRegEd.h"
  3. #ifndef DBCS
  4. #define AnsiNext(x) ((x)+1)
  5. #endif
  6. HANDLE hPars = NULL;
  7. WORD maxKeys = 0;
  8. BOOL bChangesMade = FALSE;
  9. static HWND hWndVals, hWndDels;
  10. char szListbox[] = "listbox";
  11. extern HANDLE hInstance;
  12. extern HWND hWndIds, hWndMain;
  13. extern char szNull[];
  14. extern VOID NEAR PASCAL MySetSel(HWND hWndList, int index);
  15. static int NEAR PASCAL AddKeyToList(PSTR szPath, int index, int nLevel)
  16. {
  17. PSTR szLast, pNext;
  18. DWORD dwResult;
  19. int nResult = -IDS_OUTOFMEMORY;
  20. WORD *pPars;
  21. int i, nKeys, nParent, nLevels;
  22. /* Create the list of parents if necessary */
  23. if(!hPars) {
  24. if(!(hPars=LocalAlloc(LMEM_MOVEABLE, 8*sizeof(WORD))))
  25. goto Error1;
  26. else
  27. maxKeys = 8;
  28. }
  29. /* Get the current number of keys, and check index
  30. * index == -1 means to add to the end of the list
  31. */
  32. if((nKeys=(WORD)SendMessage(hWndIds, LB_GETCOUNT, 0, 0L)) == LB_ERR)
  33. nKeys = 0;
  34. if(index == 0xffff)
  35. index = nKeys;
  36. else if(index > nKeys)
  37. goto Error1;
  38. if(!(pPars=(WORD *)LocalLock(hPars)))
  39. goto Error1;
  40. szLast = szPath;
  41. if(*szPath == '\\') {
  42. /* This is a full path name, which will be inserted the first
  43. * place it can be. The level and index are ignored: they will
  44. * need to be determined
  45. * if this is the root, set the variables and jump to the adding part
  46. * otherwise, find the existing parent and the new tail
  47. */
  48. if(!*(szPath+1)) {
  49. /* If the root exists, just return its index
  50. */
  51. if((nResult=FindKey(szPath)) >= 0)
  52. goto Error2;
  53. nParent = -1;
  54. nLevels = 0;
  55. pNext = szPath + 1;
  56. goto AddNewKey;
  57. } else {
  58. ++szLast;
  59. if((nParent=FindLastExistingKey(0, szLast)) < 0)
  60. goto Error2;
  61. index = nParent + 1;
  62. }
  63. } else {
  64. /* Not an absolute path
  65. * nLevel == -1 means the preceding index is the parent, so nLevel is ignored
  66. * otherwise, find the ancestor of the preceding key with a lower
  67. * level than nLevel, and that is the parent
  68. * Finally, check for existing keys, and adjust nParent and index if necessary
  69. */
  70. if(nLevel == -1) {
  71. nParent = index - 1;
  72. } else {
  73. for(i=index-1; i>=0; i=pPars[i], --nLevel)
  74. /* do nothing */ ;
  75. if(nLevel > 0)
  76. goto Error2;
  77. for(i=index-1; nLevel<0; i=pPars[i], ++nLevel)
  78. /* do nothing */ ;
  79. nParent = i;
  80. }
  81. if(index < nKeys) {
  82. if((nParent=FindLastExistingKey(nParent, szLast)) < 0)
  83. goto Error2;
  84. else if(nParent >= index)
  85. index = nParent + 1;
  86. }
  87. }
  88. /* At this point, index should be set to the intended index,
  89. * nParent should be set to the parent of the new key,
  90. * and szLast is the path for the new key (which may have subkeys)
  91. */
  92. for(nLevels=0; pNext=OFFSET(MyStrTok(szLast, '\\'));
  93. ++nLevels, szLast=pNext) {
  94. AddNewKey:
  95. if (pNext-szLast > MAX_KEY_LENGTH) {
  96. nResult = -IDS_BADKEY;
  97. goto CleanUp;
  98. }
  99. /* Make sure we have room for the new parents */
  100. if(nKeys+nLevels+1 > (int)maxKeys) {
  101. HANDLE hTemp;
  102. LocalUnlock(hPars);
  103. if(!(hTemp=LocalReAlloc(hPars,(maxKeys+8)*sizeof(WORD),LMEM_MOVEABLE)))
  104. goto Error1;
  105. hPars = hTemp;
  106. if(!(pPars=(WORD *)LocalLock(hPars)))
  107. goto Error1;
  108. maxKeys += 8;
  109. }
  110. if((dwResult=SendMessage(hWndIds, LB_INSERTSTRING, index+nLevels,
  111. (DWORD)((LPSTR)szLast)))==LB_ERR)
  112. break;
  113. if((dwResult=SendMessage(hWndVals, LB_INSERTSTRING, index+nLevels,
  114. (DWORD)((LPSTR)szNull)))==LB_ERR) {
  115. SendMessage(hWndIds, LB_DELETESTRING, index+nLevels, 0L);
  116. break;
  117. }
  118. SendMessage(hWndVals, LB_SETITEMDATA, index+nLevels, 1L);
  119. }
  120. /* If the new key already exists, return it */
  121. if(!nLevels)
  122. nResult = nParent;
  123. else if(dwResult != LB_ERR)
  124. nResult = LOWORD(dwResult);
  125. CleanUp:
  126. /* update the parent list */
  127. for(--nKeys; nKeys>=index; --nKeys) {
  128. if(pPars[nKeys] >= (WORD)index)
  129. pPars[nKeys+nLevels] = pPars[nKeys] + nLevels;
  130. else
  131. pPars[nKeys+nLevels] = pPars[nKeys];
  132. }
  133. for(--nLevels; nLevels>=0; --nLevels)
  134. pPars[index+nLevels] = nParent+nLevels;
  135. Error2:
  136. LocalUnlock(hPars);
  137. Error1:
  138. return(nResult);
  139. }
  140. static WORD NEAR PASCAL ListRegs(HWND hWnd, HKEY hKey, int wLevel)
  141. {
  142. HANDLE hTail;
  143. PSTR pTail;
  144. int i;
  145. HKEY hSubKey;
  146. WORD wErrMsg = NULL;
  147. for(i=0; !wErrMsg; ++i) {
  148. if(MyEnumKey(hKey, i, &hTail) != ERROR_SUCCESS)
  149. break;
  150. pTail = LocalLock(hTail);
  151. if((int)(wErrMsg=-AddKeyToList(pTail, -1, wLevel))>0 ||
  152. (wErrMsg=GetErrMsg((WORD)RegOpenKey(hKey, pTail, &hSubKey))))
  153. goto Error1;
  154. wErrMsg = ListRegs(hWnd, hSubKey, wLevel+1);
  155. RegCloseKey(hSubKey);
  156. Error1:
  157. LocalUnlock(hTail);
  158. LocalFree(hTail);
  159. }
  160. return(wErrMsg);
  161. }
  162. WORD NEAR PASCAL MyResetIdList(HWND hDlg)
  163. {
  164. HKEY hKey;
  165. int i, nNum;
  166. WORD wErrMsg = IDS_OUTOFMEMORY;
  167. if((!hWndVals && !(hWndVals=GetDlgItem(hDlg, ID_VALLIST))) ||
  168. (!hWndDels && !(hWndDels=GetDlgItem(hDlg, ID_DELLIST))))
  169. goto Error1;
  170. bChangesMade = FALSE;
  171. SendMessage(hWndIds, LB_RESETCONTENT, 0, 0L);
  172. SendMessage(hWndVals, LB_RESETCONTENT, 0, 0L);
  173. SendMessage(hWndDels, LB_RESETCONTENT, 0, 0L);
  174. if((int)(wErrMsg=-AddKeyToList("\\", 0, 0)) <= 0) {
  175. if(!(wErrMsg=GetErrMsg((WORD)RegCreateKey(HKEY_CLASSES_ROOT,
  176. NULL, &hKey)))) {
  177. wErrMsg = ListRegs(hWndIds, hKey, 1);
  178. RegCloseKey(hKey);
  179. nNum = (int)SendMessage(hWndVals, LB_GETCOUNT, 0, 0L);
  180. for(i=0; i<nNum; ++i)
  181. SendMessage(hWndVals, LB_SETITEMDATA, i, 0L);
  182. }
  183. MySetSel(hWndIds, 0);
  184. }
  185. Error1:
  186. return(wErrMsg);
  187. }
  188. WORD NEAR PASCAL MySaveChanges(void)
  189. {
  190. HKEY hKeyTemp;
  191. HANDLE hPath, hVal;
  192. WORD wNum, wErrMsg;
  193. DWORD dwTemp;
  194. int i;
  195. if(wErrMsg=GetErrMsg((WORD)RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKeyTemp)))
  196. goto Error1;
  197. wNum = (WORD)SendMessage(hWndDels, LB_GETCOUNT, 0, 0L);
  198. for(i=0; !wErrMsg && (WORD)i<wNum; ++i) {
  199. wErrMsg = IDS_OUTOFMEMORY;
  200. if(!(hPath=GetListboxString(hWndDels, i)))
  201. break;
  202. dwTemp = RegDeleteKey(HKEY_CLASSES_ROOT, LocalLock(hPath)+1);
  203. wErrMsg = dwTemp==ERROR_BADKEY ? NULL : GetErrMsg((WORD)dwTemp);
  204. LocalUnlock(hPath);
  205. LocalFree(hPath);
  206. }
  207. wNum = GetErrMsg((WORD)RegCloseKey(hKeyTemp));
  208. if(wErrMsg || (wErrMsg=wNum) ||
  209. (wErrMsg=GetErrMsg((WORD)RegCreateKey(HKEY_CLASSES_ROOT, NULL,
  210. &hKeyTemp))))
  211. goto Error1;
  212. wNum = (WORD)SendMessage(hWndVals, LB_GETCOUNT, 0, 0L);
  213. for(i=wNum-1; !wErrMsg && i>=0; --i) {
  214. if(!SendMessage(hWndVals, LB_GETITEMDATA, i, 0L))
  215. continue;
  216. wErrMsg = IDS_OUTOFMEMORY;
  217. if(!(hPath=MyGetPath(i)))
  218. break;
  219. if(!(hVal=GetListboxString(hWndVals, i)))
  220. goto Error2;
  221. wErrMsg = GetErrMsg((WORD)RegSetValue(HKEY_CLASSES_ROOT,
  222. LocalLock(hPath)+1, REG_SZ, LocalLock(hVal), 0L));
  223. LocalUnlock(hVal);
  224. LocalUnlock(hPath);
  225. LocalFree(hVal);
  226. Error2:
  227. LocalFree(hPath);
  228. }
  229. wNum = GetErrMsg((WORD)RegCloseKey(hKeyTemp));
  230. Error1:
  231. return(wErrMsg ? wErrMsg : wNum);
  232. }
  233. WORD NEAR PASCAL MyDeleteKey(int nId)
  234. {
  235. HANDLE hPath;
  236. WORD *pPars;
  237. int nKeys, i, j;
  238. WORD wErrMsg = IDS_OUTOFMEMORY;
  239. /* Get the path and try to delete it */
  240. if(!(hPath=MyGetPath(nId)))
  241. goto Error1;
  242. if(SendMessage(hWndDels, LB_ADDSTRING, 0, (DWORD)((LPSTR)LocalLock(hPath)))
  243. == LB_ERR)
  244. goto Error2;
  245. pPars = (WORD *)LocalLock(hPars);
  246. nKeys = (WORD)SendMessage(hWndIds, LB_GETCOUNT, 0, 0L);
  247. /* Find the first key that does not have nId in its parent chain */
  248. for(i=nId+1; i<nKeys; ++i) {
  249. for(j=pPars[i]; j>=0 && j!=nId; j=pPars[j])
  250. /* do nothing */ ;
  251. if(j != nId)
  252. break;
  253. }
  254. /* Do not delete the root from the list */
  255. if(!nId)
  256. ++nId;
  257. /* Delete the string from the listbox */
  258. for(j=nId; j<i; ++j) {
  259. SendMessage(hWndIds, LB_DELETESTRING, nId, 0L);
  260. SendMessage(hWndVals, LB_DELETESTRING, nId, 0L);
  261. }
  262. /* Update the parent list */
  263. i -= nId;
  264. nKeys -= i;
  265. for(j=nId; j<nKeys; ++j) {
  266. if(pPars[j+i] >= (WORD)nId)
  267. pPars[j] = pPars[j+i] - i;
  268. else
  269. pPars[j] = pPars[j+i];
  270. }
  271. bChangesMade = TRUE;
  272. wErrMsg = NULL;
  273. LocalUnlock(hPars);
  274. Error2:
  275. LocalUnlock(hPath);
  276. LocalFree(hPath);
  277. Error1:
  278. return(wErrMsg);
  279. }
  280. unsigned long NEAR PASCAL MyGetValue(int nId, HANDLE *hValue)
  281. {
  282. unsigned long result;
  283. HANDLE hPath;
  284. if(SendMessage(hWndVals, LB_GETITEMDATA, nId, 0L)) {
  285. if(!(*hValue=GetListboxString(hWndVals, nId)))
  286. return(ERROR_OUTOFMEMORY);
  287. result = ERROR_SUCCESS;
  288. } else {
  289. if(!(hPath=MyGetPath(nId)))
  290. return(ERROR_OUTOFMEMORY);
  291. result = MyQueryValue(HKEY_CLASSES_ROOT, LocalLock(hPath)+1, hValue);
  292. LocalUnlock(hPath);
  293. LocalFree(hPath);
  294. }
  295. return(result);
  296. }
  297. /* Strip off leading and trailing spaces, and return
  298. * -1 if there are any invalid characters, otherwise the address
  299. * of the first non-blank.
  300. */
  301. PSTR NEAR PASCAL VerifyKey(PSTR lpK)
  302. {
  303. PSTR lpT;
  304. char cLast = '\0';
  305. /* skip some spaces, just to be wierd
  306. */
  307. while (*lpK == ' ')
  308. lpK++;
  309. /* Special case the string "\"
  310. */
  311. if (*(unsigned int *)lpK == (unsigned int)'\\')
  312. return(lpK);
  313. /* Note that no extended characters are allowed, so no DBCS
  314. * characters are allowed in a key
  315. */
  316. for (lpT=lpK; ; ++lpT)
  317. {
  318. switch (*lpT)
  319. {
  320. case '\0':
  321. /* We do not allow a \ as the last char
  322. */
  323. return(cLast=='\\' ? (PSTR)-1 : lpK);
  324. case '\\':
  325. /* We do not allow two \'s in a row
  326. */
  327. if (cLast == '\\')
  328. return((PSTR)-1);
  329. break;
  330. default:
  331. /* If we get a control or extended character, return -1.
  332. */
  333. if ((char)(*lpT) <= ' ')
  334. return((PSTR)-1);
  335. break;
  336. }
  337. cLast = *lpT;
  338. }
  339. }
  340. unsigned long NEAR PASCAL SDKSetValue(HKEY hKey, PSTR pSubKey, PSTR pVal)
  341. {
  342. WORD wNewKey;
  343. if (hKey == HKEY_CLASSES_ROOT)
  344. hKey = 0L;
  345. else
  346. hKey = -(long)hKey;
  347. if ((pSubKey=VerifyKey(pSubKey)) == (PSTR)-1)
  348. return(ERROR_BADKEY);
  349. if((int)(wNewKey=(WORD)AddKeyToList(pSubKey, (WORD)hKey+1, -1))>=0 &&
  350. SendMessage(hWndVals, LB_INSERTSTRING, wNewKey, (LONG)(LPSTR)pVal)
  351. !=LB_ERR) {
  352. SendMessage(hWndVals, LB_DELETESTRING, wNewKey+1, 0L);
  353. SendMessage(hWndVals, LB_SETITEMDATA, wNewKey, 1L);
  354. MySetSel(hWndIds, wNewKey);
  355. bChangesMade = TRUE;
  356. return(ERROR_SUCCESS);
  357. }
  358. return(ERROR_OUTOFMEMORY);
  359. }
  360. int NEAR PASCAL DoCopyKey(int nId, PSTR pPath)
  361. {
  362. WORD *pPars;
  363. int nParent, result, i, j, nKeys, nNewKey;
  364. pPars = (WORD *)LocalLock(hPars);
  365. /* Cannot copy the whole tree */
  366. result = -IDS_NOSUBKEY;
  367. if(!nId)
  368. goto Error1;
  369. /* Find the longest path that currently exists
  370. * return an error if that is the whole string
  371. * or a subkey of the key to be copied
  372. */
  373. if(*pPath == '\\') {
  374. ++pPath;
  375. if((result=nParent=FindLastExistingKey(0, pPath)) < 0)
  376. goto Error1;
  377. } else {
  378. if((result=nParent=FindLastExistingKey(pPars[nId], pPath)) < 0)
  379. goto Error1;
  380. }
  381. result = -IDS_NOSUBKEY;
  382. for(i=nParent; i>=0; i=pPars[i])
  383. if(i == nId)
  384. goto Error1;
  385. result = -IDS_ALREADYEXIST;
  386. if(!*pPath)
  387. goto Error1;
  388. /* Find the first key that does not have nId in its parent chain */
  389. nKeys = (WORD)SendMessage(hWndIds, LB_GETCOUNT, 0, 0L);
  390. for(i=nId+1; i<nKeys; ++i) {
  391. for(j=pPars[i]; j>=0 && j!=nId; j=pPars[j])
  392. /* do nothing */ ;
  393. if(j != nId)
  394. break;
  395. }
  396. /* Add the new keys
  397. * hPars should be unlocked in case it needs to grow
  398. */
  399. LocalUnlock(hPars);
  400. pPars = NULL;
  401. if(SDKSetValue(-nParent, pPath, szNull) != ERROR_SUCCESS)
  402. goto Error1;
  403. nNewKey = (int)SendMessage(hWndIds, LB_GETCURSEL, 0, 0L);
  404. for(--i, result=nId; i>=nId && result==nId; --i) {
  405. HANDLE hPart, hValue;
  406. PSTR pPart;
  407. if(nNewKey <= nId) {
  408. int nDiff;
  409. /* Need to update i and nId if keys were added before them */
  410. nDiff = (WORD)SendMessage(hWndIds, LB_GETCOUNT, 0, 0L) - nKeys;
  411. nKeys += nDiff;
  412. i += nDiff;
  413. nId += nDiff;
  414. }
  415. result = -IDS_OUTOFMEMORY;
  416. if(!(hPart=MyGetPartialPath(i, nId)))
  417. goto Error2;
  418. pPart = LocalLock(hPart);
  419. if(MyGetValue(i, &hValue) != ERROR_SUCCESS)
  420. goto Error3;
  421. if(SDKSetValue(-nNewKey, pPart, LocalLock(hValue)) != ERROR_SUCCESS)
  422. goto Error4;
  423. result = nId;
  424. Error4:
  425. LocalUnlock(hValue);
  426. LocalFree(hValue);
  427. Error3:
  428. LocalUnlock(hPart);
  429. LocalFree(hPart);
  430. Error2:
  431. ;
  432. }
  433. Error1:
  434. if(pPars)
  435. LocalUnlock(hPars);
  436. return(result);
  437. }