windows-nt/Source/XPSP1/NT/base/mvdm/wow16/regedit/sdbase.c
2020-09-26 16:20:57 +08:00

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);
}