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.

377 lines
8.9 KiB

  1. #include <windows.h>
  2. #include "SDKRegEd.h"
  3. extern HWND hWndIds;
  4. extern HANDLE hPars;
  5. extern char szHkeyClassesRoot[];
  6. DWORD NEAR PASCAL GetTreeMarkers(int nId)
  7. {
  8. int *pPars;
  9. int nKeys, nLevel, nTemp;
  10. DWORD dwMarkers, thisMarker;
  11. int i, j;
  12. nKeys = (WORD)SendMessage(hWndIds, LB_GETCOUNT, 0, 0L);
  13. pPars = (WORD *)LocalLock(hPars);
  14. for(i=nId, nLevel= -1; i>=0; i=pPars[i], ++nLevel)
  15. /* do nothing */ ;
  16. dwMarkers = 0L;
  17. for(thisMarker=1; nLevel>0; thisMarker<<=1, --nLevel) {
  18. for(i=nId, nTemp=nLevel; nTemp>0; i=pPars[i], --nTemp)
  19. /* do nothing */ ;
  20. for(j=nId+1; j<nKeys; ++j) {
  21. if(pPars[j] == i) {
  22. dwMarkers |= thisMarker;
  23. break;
  24. }
  25. }
  26. nKeys = j;
  27. }
  28. LocalUnlock(hPars);
  29. return(dwMarkers);
  30. }
  31. int NEAR PASCAL GetLevel(int nId)
  32. {
  33. int nLevel;
  34. int *pPars;
  35. if(!hPars || !(pPars=(WORD *)LocalLock(hPars)))
  36. return(0);
  37. for(nLevel= -1; nId>=0; nId=pPars[nId], ++nLevel)
  38. /* do nothing */ ;
  39. LocalUnlock(hPars);
  40. return(nLevel);
  41. }
  42. HANDLE NEAR PASCAL MyGetPartialPath(int index, int nParent)
  43. {
  44. BOOL bFirst;
  45. HANDLE hPath;
  46. PSTR pPath;
  47. int nLevel, nTemp, i;
  48. DWORD dwLen;
  49. WORD wLen = 2;
  50. int *pPars;
  51. if(!hPars || !(pPars=(WORD *)LocalLock(hPars)))
  52. goto Error1;
  53. for(i=index, nLevel=0; i!=nParent; i=pPars[i], ++nLevel) {
  54. if((dwLen=SendMessage(hWndIds, LB_GETTEXTLEN, i, 0L)) == LB_ERR)
  55. goto Error2;
  56. wLen += LOWORD(dwLen) + 1;
  57. }
  58. if(!(hPath=LocalAlloc(LMEM_MOVEABLE, wLen)))
  59. goto Error2;
  60. if(!(pPath=LocalLock(hPath)))
  61. goto Error3;
  62. if(nParent == 0)
  63. *pPath++ = '\\';
  64. *pPath = '\0';
  65. for(--nLevel, bFirst=TRUE; nLevel>=0; --nLevel) {
  66. for(i=index, nTemp=nLevel; nTemp>0; i=pPars[i], --nTemp)
  67. /* do nothing */ ;
  68. if(bFirst)
  69. bFirst = FALSE;
  70. else
  71. *pPath++ = '\\';
  72. dwLen = SendMessage(hWndIds, LB_GETTEXT, i, (DWORD)((LPSTR)pPath));
  73. pPath += LOWORD(dwLen);
  74. }
  75. LocalUnlock(hPath);
  76. goto Error2;
  77. Error3:
  78. LocalFree(hPath);
  79. hPath = NULL;
  80. Error2:
  81. LocalUnlock(hPars);
  82. Error1:
  83. return(hPath);
  84. }
  85. HANDLE NEAR PASCAL MyGetPath(int i)
  86. {
  87. return(MyGetPartialPath(i, 0));
  88. }
  89. int NEAR PASCAL FindKey(PSTR pKey)
  90. {
  91. HANDLE hPath;
  92. PSTR pLast, pTemp;
  93. int nLast, index, nCmp;
  94. pLast = pKey;
  95. if(*(pKey+1)) {
  96. for(pTemp=pKey; *pTemp; pTemp=OFFSET(AnsiNext(pTemp))) {
  97. if(*pTemp == '\\') {
  98. pLast = pTemp + 1;
  99. }
  100. }
  101. }
  102. nLast = index = -1;
  103. do {
  104. if((index=(int)SendMessage(hWndIds, LB_FINDSTRING, index,
  105. (DWORD)((LPSTR)pLast)))==LB_ERR ||
  106. index<=nLast || !(hPath=MyGetPath(index)))
  107. return(-1);
  108. nLast = index;
  109. nCmp = lstrcmpi(pKey, LocalLock(hPath));
  110. LocalUnlock(hPath);
  111. LocalFree(hPath);
  112. } while(nCmp) ;
  113. return(index);
  114. }
  115. int NEAR PASCAL FindLastExistingKey(int nParent, PSTR pPath)
  116. {
  117. HANDLE hPath, hTemp;
  118. PSTR pEnd, pLast, pFullPath;
  119. int nFound, nResult = -1;
  120. WORD wLen;
  121. if(!(hPath=MyGetPath(nParent)))
  122. goto Error1;
  123. wLen = lstrlen(LocalLock(hPath));
  124. LocalUnlock(hPath);
  125. if(!(hTemp=LocalReAlloc(hPath, wLen+lstrlen(pPath)+2, LMEM_MOVEABLE)))
  126. goto Error2;
  127. if(!(pFullPath=LocalLock(hPath=hTemp)))
  128. goto Error2;
  129. pEnd = pFullPath + wLen;
  130. if(nParent) {
  131. *pEnd++ = '\\';
  132. *pEnd = '\0';
  133. }
  134. lstrcpy(pEnd, pPath);
  135. for(pLast=pEnd; *pEnd; pEnd=OFFSET(AnsiNext(pEnd))) {
  136. if(*pEnd == '\\') {
  137. *pEnd = '\0';
  138. nFound = FindKey(pFullPath);
  139. *pEnd = '\\';
  140. if(nFound == -1)
  141. goto FoundLast;
  142. pLast = pEnd + 1;
  143. nParent = nFound;
  144. }
  145. }
  146. /* If we got to the end of the string, try the whole thing */
  147. if((nFound=FindKey(pFullPath)) >= 0) {
  148. /* The key already exists */
  149. nParent = nFound;
  150. pLast = pEnd;
  151. }
  152. FoundLast:
  153. nResult = nParent;
  154. lstrcpy(pPath, pLast);
  155. LocalUnlock(hPath);
  156. Error2:
  157. LocalFree(hPath);
  158. Error1:
  159. return(nResult);
  160. }
  161. #define BIGBLOCK 1024L
  162. static WORD NEAR PASCAL BufferedWrite(int hFile, PSTR pWrite, WORD wBytes)
  163. {
  164. static HANDLE hBuffer = NULL;
  165. static WORD wOffset;
  166. static DWORD dwSize;
  167. LPSTR lpBuffer;
  168. /* wBytes = 0 means to write out the buffer and clean up */
  169. if(!wBytes) {
  170. WORD wErrMsg = NULL;
  171. if(hBuffer) {
  172. if(lpBuffer=GlobalLock(hBuffer)) {
  173. if(_lwrite(hFile, lpBuffer, wOffset) != wOffset)
  174. wErrMsg = IDS_CANTWRITEFILE;
  175. GlobalUnlock(hBuffer);
  176. } else
  177. wErrMsg = IDS_OUTOFMEMORY;
  178. GlobalFree(hBuffer);
  179. hBuffer = NULL;
  180. }
  181. return(wErrMsg);
  182. }
  183. /* hBuffer = NULL means we need to allocate a buffer */
  184. if(!hBuffer) {
  185. if(!(hBuffer=GlobalAlloc(GMEM_MOVEABLE, dwSize=BIGBLOCK)))
  186. return(IDS_OUTOFMEMORY);
  187. wOffset = 0;
  188. }
  189. /* If the total is > 64K, flush the buffer */
  190. if((DWORD)wBytes+(DWORD)wOffset > 0xffffL) {
  191. if(lpBuffer=GlobalLock(hBuffer)) {
  192. WORD wTemp;
  193. wTemp = _lwrite(hFile, lpBuffer, wOffset);
  194. GlobalUnlock(hBuffer);
  195. if(wTemp != wOffset)
  196. return(IDS_CANTWRITEFILE);
  197. } else
  198. return(IDS_OUTOFMEMORY);
  199. wOffset = 0;
  200. }
  201. /* If the total is greater than the size we have allocated, try to
  202. * increase the buffer size to fit. If we cannot, then flush the
  203. * buffer, and if wBytes is still too big, then write it straight to
  204. * disk.
  205. */
  206. if((DWORD)(wBytes+wOffset) > dwSize) {
  207. HANDLE hTemp;
  208. DWORD dwTemp;
  209. dwTemp = (((wBytes+wOffset)/BIGBLOCK) + 1) * BIGBLOCK;
  210. if(hTemp=GlobalReAlloc(hBuffer, dwTemp, GMEM_MOVEABLE)) {
  211. hBuffer = hTemp;
  212. dwSize = dwTemp;
  213. } else {
  214. WORD wTemp;
  215. if(wOffset) {
  216. if(!(lpBuffer=GlobalLock(hBuffer)))
  217. return(IDS_OUTOFMEMORY);
  218. wTemp = _lwrite(hFile, lpBuffer, wOffset);
  219. wOffset = 0;
  220. GlobalUnlock(hBuffer);
  221. if(wTemp != wOffset)
  222. return(IDS_CANTWRITEFILE);
  223. }
  224. if(wBytes > LOWORD(dwSize)) {
  225. if(_lwrite(hFile, pWrite, wBytes) == wBytes)
  226. return(NULL);
  227. else
  228. return(IDS_CANTWRITEFILE);
  229. }
  230. }
  231. }
  232. /* If we got to here, then there is room in the buffer */
  233. if(!(lpBuffer=GlobalLock(hBuffer)))
  234. return(IDS_OUTOFMEMORY);
  235. RepeatMove(lpBuffer+wOffset, pWrite, wBytes);
  236. wOffset += wBytes;
  237. GlobalUnlock(hBuffer);
  238. return(NULL);
  239. }
  240. WORD NEAR PASCAL DoWriteFile(int nId, HANDLE hFileName)
  241. {
  242. HANDLE hHeader;
  243. PSTR pHeader;
  244. WORD wErrMsg;
  245. int *pPars;
  246. LPSTR lpFileName;
  247. int hFile, nKeys, i, j;
  248. OFSTRUCT of;
  249. WORD wRootLen = lstrlen(szHkeyClassesRoot);
  250. /* Open the file */
  251. wErrMsg = IDS_CANTOPENFILE;
  252. lpFileName = GlobalLock(hFileName);
  253. if((hFile=OpenFile(lpFileName, &of, OF_CREATE)) == -1)
  254. goto Error1;
  255. pPars = (WORD *)LocalLock(hPars);
  256. nKeys = (WORD)SendMessage(hWndIds, LB_GETCOUNT, 0, 0L);
  257. /* Find the first key that does not have nId in its parent chain */
  258. for(i=nId+1; i<nKeys; ++i) {
  259. for(j=pPars[i]; j>=0 && j!=nId; j=pPars[j])
  260. /* do nothing */ ;
  261. if(j != nId)
  262. break;
  263. }
  264. wErrMsg = IDS_OUTOFMEMORY;
  265. if(!(hHeader=MyLoadString(IDS_REGHEADER, NULL, LMEM_MOVEABLE)))
  266. goto Error2;
  267. pHeader = LocalLock(hHeader);
  268. wErrMsg = BufferedWrite(hFile, pHeader, lstrlen(pHeader));
  269. LocalUnlock(hHeader);
  270. LocalFree(hHeader);
  271. if(wErrMsg || (wErrMsg=BufferedWrite(hFile, "\r\n", 2)))
  272. goto Error2;
  273. /* Write the strings */
  274. for(j=nId, wErrMsg=NULL; j<i && !wErrMsg; ++j) {
  275. HANDLE hPath, hValue;
  276. PSTR pPath, pValue;
  277. /* Get the path and the value */
  278. wErrMsg = IDS_OUTOFMEMORY;
  279. if(!(hPath=MyGetPath(j)))
  280. goto Error2;
  281. pPath = LocalLock(hPath);
  282. if(MyGetValue(j, &hValue))
  283. goto Error3;
  284. pValue = LocalLock(hValue);
  285. /* We don't need to write this key if it has subkeys but no value */
  286. wErrMsg = NULL;
  287. if(!(*pValue) && pPars[j+1]==j)
  288. goto Error4;
  289. /* Write HKEY_CLASSES_ROOT<path> = <value>\r\n */
  290. if((wErrMsg=BufferedWrite(hFile, szHkeyClassesRoot, wRootLen)) ||
  291. (wErrMsg=BufferedWrite(hFile, pPath+1, lstrlen(pPath+1))) ||
  292. (wErrMsg=BufferedWrite(hFile, " = ", 3)))
  293. goto Error4;
  294. /* Don't write the value if it is of 0 length */
  295. if(*pValue && (wErrMsg=BufferedWrite(hFile, pValue, lstrlen(pValue))))
  296. goto Error4;
  297. wErrMsg = BufferedWrite(hFile, "\r\n", 2);
  298. Error4:
  299. LocalUnlock(hValue);
  300. LocalFree(hValue);
  301. Error3:
  302. LocalUnlock(hPath);
  303. LocalFree(hPath);
  304. Error2:
  305. ;
  306. }
  307. /* One last write with 0 length to clean up */
  308. wErrMsg = BufferedWrite(hFile, NULL, 0);
  309. LocalUnlock(hPars);
  310. _lclose(hFile);
  311. /* Delete the file if there was an error */
  312. if(wErrMsg)
  313. OpenFile(lpFileName, &of, OF_DELETE);
  314. Error1:
  315. GlobalUnlock(hFileName);
  316. return(wErrMsg);
  317. }