378 lines
8.9 KiB
C
378 lines
8.9 KiB
C
|
#include <windows.h>
|
||
|
#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<nKeys; ++j) {
|
||
|
if(pPars[j] == i) {
|
||
|
dwMarkers |= thisMarker;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
nKeys = j;
|
||
|
}
|
||
|
|
||
|
LocalUnlock(hPars);
|
||
|
return(dwMarkers);
|
||
|
}
|
||
|
|
||
|
int NEAR PASCAL GetLevel(int nId)
|
||
|
{
|
||
|
int nLevel;
|
||
|
int *pPars;
|
||
|
|
||
|
if(!hPars || !(pPars=(WORD *)LocalLock(hPars)))
|
||
|
return(0);
|
||
|
for(nLevel= -1; nId>=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<nKeys; ++i) {
|
||
|
for(j=pPars[i]; j>=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<i && !wErrMsg; ++j) {
|
||
|
HANDLE hPath, hValue;
|
||
|
PSTR pPath, pValue;
|
||
|
|
||
|
/* Get the path and the value */
|
||
|
wErrMsg = IDS_OUTOFMEMORY;
|
||
|
if(!(hPath=MyGetPath(j)))
|
||
|
goto Error2;
|
||
|
pPath = LocalLock(hPath);
|
||
|
if(MyGetValue(j, &hValue))
|
||
|
goto Error3;
|
||
|
pValue = LocalLock(hValue);
|
||
|
|
||
|
/* We don't need to write this key if it has subkeys but no value */
|
||
|
wErrMsg = NULL;
|
||
|
if(!(*pValue) && pPars[j+1]==j)
|
||
|
goto Error4;
|
||
|
|
||
|
/* Write HKEY_CLASSES_ROOT<path> = <value>\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);
|
||
|
}
|
||
|
|