#include #include "SDKRegEd.h" extern HWND hWndIds; extern HANDLE hPars; extern char szHkeyClassesRoot[]; DWORD NEAR PASCAL GetTreeMarkers(int nId) { int *pPars; int nKeys, nLevel, nTemp; DWORD dwMarkers, thisMarker; int i, j; nKeys = (WORD)SendMessage(hWndIds, LB_GETCOUNT, 0, 0L); pPars = (WORD *)LocalLock(hPars); for(i=nId, nLevel= -1; i>=0; i=pPars[i], ++nLevel) /* do nothing */ ; dwMarkers = 0L; for(thisMarker=1; nLevel>0; thisMarker<<=1, --nLevel) { for(i=nId, nTemp=nLevel; nTemp>0; i=pPars[i], --nTemp) /* do nothing */ ; for(j=nId+1; j=0; nId=pPars[nId], ++nLevel) /* do nothing */ ; LocalUnlock(hPars); return(nLevel); } HANDLE NEAR PASCAL MyGetPartialPath(int index, int nParent) { BOOL bFirst; HANDLE hPath; PSTR pPath; int nLevel, nTemp, i; DWORD dwLen; WORD wLen = 2; int *pPars; if(!hPars || !(pPars=(WORD *)LocalLock(hPars))) goto Error1; for(i=index, nLevel=0; i!=nParent; i=pPars[i], ++nLevel) { if((dwLen=SendMessage(hWndIds, LB_GETTEXTLEN, i, 0L)) == LB_ERR) goto Error2; wLen += LOWORD(dwLen) + 1; } if(!(hPath=LocalAlloc(LMEM_MOVEABLE, wLen))) goto Error2; if(!(pPath=LocalLock(hPath))) goto Error3; if(nParent == 0) *pPath++ = '\\'; *pPath = '\0'; for(--nLevel, bFirst=TRUE; nLevel>=0; --nLevel) { for(i=index, nTemp=nLevel; nTemp>0; i=pPars[i], --nTemp) /* do nothing */ ; if(bFirst) bFirst = FALSE; else *pPath++ = '\\'; dwLen = SendMessage(hWndIds, LB_GETTEXT, i, (DWORD)((LPSTR)pPath)); pPath += LOWORD(dwLen); } LocalUnlock(hPath); goto Error2; Error3: LocalFree(hPath); hPath = NULL; Error2: LocalUnlock(hPars); Error1: return(hPath); } HANDLE NEAR PASCAL MyGetPath(int i) { return(MyGetPartialPath(i, 0)); } int NEAR PASCAL FindKey(PSTR pKey) { HANDLE hPath; PSTR pLast, pTemp; int nLast, index, nCmp; pLast = pKey; if(*(pKey+1)) { for(pTemp=pKey; *pTemp; pTemp=OFFSET(AnsiNext(pTemp))) { if(*pTemp == '\\') { pLast = pTemp + 1; } } } nLast = index = -1; do { if((index=(int)SendMessage(hWndIds, LB_FINDSTRING, index, (DWORD)((LPSTR)pLast)))==LB_ERR || index<=nLast || !(hPath=MyGetPath(index))) return(-1); nLast = index; nCmp = lstrcmpi(pKey, LocalLock(hPath)); LocalUnlock(hPath); LocalFree(hPath); } while(nCmp) ; return(index); } int NEAR PASCAL FindLastExistingKey(int nParent, PSTR pPath) { HANDLE hPath, hTemp; PSTR pEnd, pLast, pFullPath; int nFound, nResult = -1; WORD wLen; if(!(hPath=MyGetPath(nParent))) goto Error1; wLen = lstrlen(LocalLock(hPath)); LocalUnlock(hPath); if(!(hTemp=LocalReAlloc(hPath, wLen+lstrlen(pPath)+2, LMEM_MOVEABLE))) goto Error2; if(!(pFullPath=LocalLock(hPath=hTemp))) goto Error2; pEnd = pFullPath + wLen; if(nParent) { *pEnd++ = '\\'; *pEnd = '\0'; } lstrcpy(pEnd, pPath); for(pLast=pEnd; *pEnd; pEnd=OFFSET(AnsiNext(pEnd))) { if(*pEnd == '\\') { *pEnd = '\0'; nFound = FindKey(pFullPath); *pEnd = '\\'; if(nFound == -1) goto FoundLast; pLast = pEnd + 1; nParent = nFound; } } /* If we got to the end of the string, try the whole thing */ if((nFound=FindKey(pFullPath)) >= 0) { /* The key already exists */ nParent = nFound; pLast = pEnd; } FoundLast: nResult = nParent; lstrcpy(pPath, pLast); LocalUnlock(hPath); Error2: LocalFree(hPath); Error1: return(nResult); } #define BIGBLOCK 1024L static WORD NEAR PASCAL BufferedWrite(int hFile, PSTR pWrite, WORD wBytes) { static HANDLE hBuffer = NULL; static WORD wOffset; static DWORD dwSize; LPSTR lpBuffer; /* wBytes = 0 means to write out the buffer and clean up */ if(!wBytes) { WORD wErrMsg = NULL; if(hBuffer) { if(lpBuffer=GlobalLock(hBuffer)) { if(_lwrite(hFile, lpBuffer, wOffset) != wOffset) wErrMsg = IDS_CANTWRITEFILE; GlobalUnlock(hBuffer); } else wErrMsg = IDS_OUTOFMEMORY; GlobalFree(hBuffer); hBuffer = NULL; } return(wErrMsg); } /* hBuffer = NULL means we need to allocate a buffer */ if(!hBuffer) { if(!(hBuffer=GlobalAlloc(GMEM_MOVEABLE, dwSize=BIGBLOCK))) return(IDS_OUTOFMEMORY); wOffset = 0; } /* If the total is > 64K, flush the buffer */ if((DWORD)wBytes+(DWORD)wOffset > 0xffffL) { if(lpBuffer=GlobalLock(hBuffer)) { WORD wTemp; wTemp = _lwrite(hFile, lpBuffer, wOffset); GlobalUnlock(hBuffer); if(wTemp != wOffset) return(IDS_CANTWRITEFILE); } else return(IDS_OUTOFMEMORY); wOffset = 0; } /* If the total is greater than the size we have allocated, try to * increase the buffer size to fit. If we cannot, then flush the * buffer, and if wBytes is still too big, then write it straight to * disk. */ if((DWORD)(wBytes+wOffset) > dwSize) { HANDLE hTemp; DWORD dwTemp; dwTemp = (((wBytes+wOffset)/BIGBLOCK) + 1) * BIGBLOCK; if(hTemp=GlobalReAlloc(hBuffer, dwTemp, GMEM_MOVEABLE)) { hBuffer = hTemp; dwSize = dwTemp; } else { WORD wTemp; if(wOffset) { if(!(lpBuffer=GlobalLock(hBuffer))) return(IDS_OUTOFMEMORY); wTemp = _lwrite(hFile, lpBuffer, wOffset); wOffset = 0; GlobalUnlock(hBuffer); if(wTemp != wOffset) return(IDS_CANTWRITEFILE); } if(wBytes > LOWORD(dwSize)) { if(_lwrite(hFile, pWrite, wBytes) == wBytes) return(NULL); else return(IDS_CANTWRITEFILE); } } } /* If we got to here, then there is room in the buffer */ if(!(lpBuffer=GlobalLock(hBuffer))) return(IDS_OUTOFMEMORY); RepeatMove(lpBuffer+wOffset, pWrite, wBytes); wOffset += wBytes; GlobalUnlock(hBuffer); return(NULL); } WORD NEAR PASCAL DoWriteFile(int nId, HANDLE hFileName) { HANDLE hHeader; PSTR pHeader; WORD wErrMsg; int *pPars; LPSTR lpFileName; int hFile, nKeys, i, j; OFSTRUCT of; WORD wRootLen = lstrlen(szHkeyClassesRoot); /* Open the file */ wErrMsg = IDS_CANTOPENFILE; lpFileName = GlobalLock(hFileName); if((hFile=OpenFile(lpFileName, &of, OF_CREATE)) == -1) goto Error1; pPars = (WORD *)LocalLock(hPars); nKeys = (WORD)SendMessage(hWndIds, LB_GETCOUNT, 0, 0L); /* Find the first key that does not have nId in its parent chain */ for(i=nId+1; i=0 && j!=nId; j=pPars[j]) /* do nothing */ ; if(j != nId) break; } wErrMsg = IDS_OUTOFMEMORY; if(!(hHeader=MyLoadString(IDS_REGHEADER, NULL, LMEM_MOVEABLE))) goto Error2; pHeader = LocalLock(hHeader); wErrMsg = BufferedWrite(hFile, pHeader, lstrlen(pHeader)); LocalUnlock(hHeader); LocalFree(hHeader); if(wErrMsg || (wErrMsg=BufferedWrite(hFile, "\r\n", 2))) goto Error2; /* Write the strings */ for(j=nId, wErrMsg=NULL; j = \r\n */ if((wErrMsg=BufferedWrite(hFile, szHkeyClassesRoot, wRootLen)) || (wErrMsg=BufferedWrite(hFile, pPath+1, lstrlen(pPath+1))) || (wErrMsg=BufferedWrite(hFile, " = ", 3))) goto Error4; /* Don't write the value if it is of 0 length */ if(*pValue && (wErrMsg=BufferedWrite(hFile, pValue, lstrlen(pValue)))) goto Error4; wErrMsg = BufferedWrite(hFile, "\r\n", 2); Error4: LocalUnlock(hValue); LocalFree(hValue); Error3: LocalUnlock(hPath); LocalFree(hPath); Error2: ; } /* One last write with 0 length to clean up */ wErrMsg = BufferedWrite(hFile, NULL, 0); LocalUnlock(hPars); _lclose(hFile); /* Delete the file if there was an error */ if(wErrMsg) OpenFile(lpFileName, &of, OF_DELETE); Error1: GlobalUnlock(hFileName); return(wErrMsg); }