/*************************************************************************** Name : REGISTRY.C Comment : INIfile handling Revision Log Date Name Description -------- ----- --------------------------------------------------------- ***************************************************************************/ #include "prep.h" #include "efaxcb.h" #include "t30.h" #include "hdlc.h" #include "debug.h" #include "glbproto.h" #ifdef USE_REGISTRY // The default database to us # define DATABASE_KEY HKEY_LOCAL_MACHINE // These are NOT localizable items. # define szKEYPREFIX "SOFTWARE\\Microsoft\\Fax\\Devices" # define szKEYCLASS "DATA" DWORD my_atoul(LPSTR lpsz); #else // !USE_REGISTRY BOOL expand_key(DWORD dwKey, LPSTR FAR *lplpszKey, LPSTR FAR *lplpszProfileName); #endif // !USE_REGISTRY ULONG_PTR ProfileOpen(DWORD dwProfileID, LPSTR lpszSection, DWORD dwFlags) { ULONG_PTR dwRet = 0; #ifdef USE_REGISTRY char rgchKey[128]; HKEY hKey=0; HKEY hBaseKey = DATABASE_KEY; LONG l; LPSTR lpszPrefix; DWORD sam=0; BG_CHK(sizeof(hKey)<=sizeof(ULONG_PTR)); if (dwProfileID==OEM_BASEKEY) { hBaseKey = HKEY_LOCAL_MACHINE; lpszPrefix= ""; // we don't prepend szKEYPREFIX if (!lpszSection) goto failure; } else if (lpszSection) { lpszPrefix= szKEYPREFIX "\\"; } else { lpszPrefix= szKEYPREFIX; lpszSection=""; } if ((lstrlen(lpszPrefix)+lstrlen(lpszSection))>=sizeof(rgchKey)) goto failure; lstrcpy(rgchKey, lpszPrefix); lstrcat(rgchKey, lpszSection); sam = 0; if (dwFlags &fREG_READ) sam |= KEY_READ; if (dwFlags &fREG_WRITE) sam |= KEY_WRITE; if (dwFlags & fREG_CREATE) { DWORD dwDisposition=0; DWORD dwOptions = (dwFlags & fREG_VOLATILE) ?REG_OPTION_VOLATILE :REG_OPTION_NON_VOLATILE; sam = KEY_READ | KEY_WRITE; // we force sam to this when creating. l = RegCreateKeyEx( hBaseKey, // handle of open key rgchKey, // address of name of subkey to open 0, // reserved szKEYCLASS, // address of class string dwOptions, // special options flag sam, // desired security access NULL, // address of key security structure &hKey, // address of buffer for opened handle &dwDisposition // address of dispostion value buffer ); } else { l = RegOpenKeyEx( hBaseKey, // handle of open key rgchKey, // address of name of subkey to open 0, // reserved sam , // desired security access &hKey // address of buffer for opened handle ); } if (l!=ERROR_SUCCESS) { //LOG((_ERR, "RegCreateKeyEx returns error %ld\n", (long) l)); goto failure; } dwRet = (ULONG_PTR) hKey; #else // !USE_REGISTRY LPSTR lpszFile= szINIFILE; ATOM aSection, aProfile; // NULL lpszSection not supported. if (!lpszSection) goto failure; if (!(aSection = GlobalAddAtom(lpszSection))) goto failure; if (!(aProfile = GlobalAddAtom(lpszFile))) {GlobalDeleteAtom(aSection); goto failure;} dwRet = MAKELONG(aSection, aProfile); #endif // !USE_REGISTRY BG_CHK(dwRet); return dwRet; failure: return 0; } UINT ProfileListGetInt( ULONG_PTR KeyList[10], LPSTR lpszValueName, UINT uDefault ) { int i; int Num=0; UINT uRet = uDefault; BOOL fExist = 0; for (i=0; i<10; i++) { if (KeyList[i] == 0) { Num = i-1; break; } } for (i=Num; i>=0; i--) { uRet = ProfileGetInt (KeyList[i], lpszValueName, uDefault, &fExist); if (fExist) { return uRet; } } return uRet; } UINT ProfileGetInt(ULONG_PTR dwKey, LPSTR lpszValueName, UINT uDefault, BOOL *fExist) { UINT uRet = uDefault; char rgchBuf[128]; DWORD dwType; DWORD dwcbSize=sizeof(rgchBuf); LONG l = RegQueryValueEx( (HKEY) dwKey, lpszValueName, 0, &dwType, rgchBuf, &dwcbSize ); if (fExist) { *fExist = 0; } if (l!=ERROR_SUCCESS) { //LOG((_ERR, "RegQueryValueEx returned error %ld\n", (long) l)); goto end; } if (fExist) { *fExist = 1; } if (dwType != REG_SZ) { //LOG((_ERR, "RegQueryValueEx value type not string:0x%lx\n", // (unsigned long) dwType)); goto end; } uRet = (UINT) my_atoul(rgchBuf); end: return uRet; } DWORD ProfileGetString(ULONG_PTR dwKey, LPSTR lpszValueName, LPSTR lpszDefault, LPSTR lpszBuf , DWORD dwcbMax) { DWORD dwRet = 0; #ifdef USE_REGISTRY DWORD dwType; LONG l = RegQueryValueEx( (HKEY) dwKey, lpszValueName, 0, &dwType, lpszBuf, &dwcbMax ); if (l!=ERROR_SUCCESS) { //LOG((_ERR, "RegQueryValueEx returned error %ld\n", (long) l)); goto copy_default; } if (dwType != REG_SZ) { //LOG((_ERR, "RegQueryValueEx value type not string:0x%lx\n", // (unsigned long) dwType)); goto copy_default; } // Make sure we null-terminate the string and return the true string // length.. if (dwcbMax) {lpszBuf[dwcbMax-1]=0; dwcbMax = (DWORD) lstrlen(lpszBuf);} dwRet = dwcbMax; goto end; #else // USE_REGISTRY LPSTR lpszKey; LPSTR lpszProfileName; if (!expand_key(dwKey, &lpszKey, &lpszProfileName)) goto copy_default; dwRet = GetPrivateProfileString(lpszKey, lpszValueName, lpszDefault, lpszBuf , (INT) dwcbMax, lpszProfileName); goto end; #endif // USE_REGISTRY BG_CHK(FALSE); copy_default: dwRet = 0; if (!lpszDefault || !*lpszDefault) { if (dwcbMax) *lpszBuf=0; } else { UINT cb = _fstrlen(lpszDefault)+1; if (cb>(UINT)dwcbMax) cb=dwcbMax; if (cb) { _fmemcpy(lpszBuf, lpszDefault, cb); lpszBuf[cb-1]=0; dwRet = cb-1; } } // fall through... end: return dwRet; } BOOL ProfileWriteString( ULONG_PTR dwKey, LPSTR lpszValueName, LPSTR lpszBuf, BOOL fRemoveCR ) { // NOTE: If lpszValueName is null, delete the key. (can't do this in, // the registry, unfortunately). // If lpszBuf is null pointer -- "delete" this value. BOOL fRet=FALSE; #ifdef USE_REGISTRY LONG l; if (!lpszValueName) goto end; if (!lpszBuf) { // delete value... l = RegDeleteValue((HKEY) dwKey, lpszValueName); if (l!=ERROR_SUCCESS) goto end; } else { if (fRemoveCR) { RemoveCR (lpszBuf); } l = RegSetValueEx((HKEY) dwKey, lpszValueName, 0, REG_SZ, lpszBuf, lstrlen(lpszBuf)+1); if (l!=ERROR_SUCCESS) { //LOG((_ERR, // "RegSetValueEx(\"%s\", \"%s\") returned error %ld\n", // (LPSTR) lpszValueName, // (LPSTR) lpszBuf, // (long) l)); goto end; } } fRet = TRUE; goto end; #else // !USE_REGISTRY LPSTR lpszKey; LPSTR lpszProfileName; if (!expand_key(dwKey, &lpszKey, &lpszProfileName)) goto end; fRet = WritePrivateProfileString(lpszKey, lpszValueName, lpszBuf, lpszProfileName); goto end; #endif // !USE_REGISTRY BG_CHK(FALSE); end: return fRet; } void ProfileClose(ULONG_PTR dwKey) { #ifdef USE_REGISTRY if (RegCloseKey((HKEY)dwKey)!=ERROR_SUCCESS) { //LOG((_WRN, "Couldn't close registry key:%lu\n\r", // (unsigned long) dwKey)); } #else BG_CHK(LOWORD(dwKey)); GlobalDeleteAtom(LOWORD(dwKey)); BG_CHK(HIWORD(dwKey)); GlobalDeleteAtom(HIWORD(dwKey)); #endif } BOOL ProfileDeleteSection(DWORD dwProfileID, LPSTR lpszSection) { #ifdef USE_REGISTRY char rgchKey[128]; LPSTR lpszPrefix= szKEYPREFIX "\\"; if (dwProfileID==OEM_BASEKEY) goto failure; // Can't delete this if ((lstrlen(lpszPrefix)+lstrlen(lpszSection))>=sizeof(rgchKey)) goto failure; lstrcpy(rgchKey, lpszPrefix); lstrcat(rgchKey, lpszSection); return (RegDeleteKey(DATABASE_KEY, rgchKey)==ERROR_SUCCESS); failure: return FALSE; #else // !USE_REGISTRY return WritePrivateProfileString(lpszSection, NULL, NULL, szINIFILE); #endif // !USE_REGISTRY } BOOL ProfileCopyTree( DWORD dwProfileIDTo, LPSTR lpszSectionTo, DWORD dwProfileIDFr, LPSTR lpszSectionFr) { BOOL fRet=TRUE; char SecTo[200]; char SecFr[200]; // // Since there is no CopyKeyWithAllSubkeys API, it is difficult to write generic tree-walking algorithm. // We will hard-code the keys here. // // copy Fax key always ProfileCopySection(dwProfileIDTo, lpszSectionTo, dwProfileIDFr, lpszSectionFr, TRUE); // copy Fax/Class1 key if exists sprintf(SecTo, "%s\\Class1", lpszSectionTo); sprintf(SecFr, "%s\\Class1", lpszSectionFr); ProfileCopySection(dwProfileIDTo, SecTo, dwProfileIDFr, SecFr, FALSE); // copy Fax/Class1/AdaptiveAnswer key if exists sprintf(SecTo, "%s\\Class1\\AdaptiveAnswer", lpszSectionTo); sprintf(SecFr, "%s\\Class1\\AdaptiveAnswer", lpszSectionFr); ProfileCopySection(dwProfileIDTo, SecTo, dwProfileIDFr, SecFr, FALSE); // copy Fax/Class1/AdaptiveAnswer/Answer key if exists sprintf(SecTo, "%s\\Class1\\AdaptiveAnswer\\AnswerCommand", lpszSectionTo); sprintf(SecFr, "%s\\Class1\\AdaptiveAnswer\\AnswerCommand", lpszSectionFr); ProfileCopySection(dwProfileIDTo, SecTo, dwProfileIDFr, SecFr, FALSE); // copy Fax/Class2 key if exists sprintf(SecTo, "%s\\Class2", lpszSectionTo); sprintf(SecFr, "%s\\Class2", lpszSectionFr); ProfileCopySection(dwProfileIDTo, SecTo, dwProfileIDFr, SecFr, FALSE); // copy Fax/Class2/AdaptiveAnswer key if exists sprintf(SecTo, "%s\\Class2\\AdaptiveAnswer", lpszSectionTo); sprintf(SecFr, "%s\\Class2\\AdaptiveAnswer", lpszSectionFr); ProfileCopySection(dwProfileIDTo, SecTo, dwProfileIDFr, SecFr, FALSE); // copy Fax/Class2/AdaptiveAnswer/Answer key if exists sprintf(SecTo, "%s\\Class2\\AdaptiveAnswer\\AnswerCommand", lpszSectionTo); sprintf(SecFr, "%s\\Class2\\AdaptiveAnswer\\AnswerCommand", lpszSectionFr); ProfileCopySection(dwProfileIDTo, SecTo, dwProfileIDFr, SecFr, FALSE); // copy Fax/Class2_0 key if exists sprintf(SecTo, "%s\\Class2_0", lpszSectionTo); sprintf(SecFr, "%s\\Class2_0", lpszSectionFr); ProfileCopySection(dwProfileIDTo, SecTo, dwProfileIDFr, SecFr, FALSE); // copy Fax/Class2_0/AdaptiveAnswer key if exists sprintf(SecTo, "%s\\Class2_0\\AdaptiveAnswer", lpszSectionTo); sprintf(SecFr, "%s\\Class2_0\\AdaptiveAnswer", lpszSectionFr); ProfileCopySection(dwProfileIDTo, SecTo, dwProfileIDFr, SecFr, FALSE); // copy Fax/Class2/AdaptiveAnswer/Answer key if exists sprintf(SecTo, "%s\\Class2_0\\AdaptiveAnswer\\AnswerCommand", lpszSectionTo); sprintf(SecFr, "%s\\Class2_0\\AdaptiveAnswer\\AnswerCommand", lpszSectionFr); ProfileCopySection(dwProfileIDTo, SecTo, dwProfileIDFr, SecFr, FALSE); return fRet; } BOOL ProfileCopySection( DWORD dwProfileIDTo, LPSTR lpszSectionTo, DWORD dwProfileIDFr, LPSTR lpszSectionFr, BOOL fCreateAlways ) { BOOL fRet=FALSE; DWORD iValue=0; DWORD cbValue, cbData, dwType; char rgchValue[60], rgchData[256]; HKEY hkFr; HKEY hkTo; hkFr = (HKEY) ProfileOpen(dwProfileIDFr, lpszSectionFr, fREG_READ); if ( (!hkFr) && (!fCreateAlways) ) { return fRet; } hkTo = (HKEY) ProfileOpen(dwProfileIDTo, lpszSectionTo, fREG_CREATE |fREG_READ|fREG_WRITE); if (!hkTo || !hkFr) goto end; iValue=0;dwType=0;cbValue=sizeof(rgchValue);cbData=sizeof(rgchData); while(RegEnumValue(hkFr, iValue, rgchValue, &cbValue, NULL, &dwType, rgchData, &cbData)==ERROR_SUCCESS) { if (RegQueryValueEx(hkFr, rgchValue, NULL, &dwType, rgchData, &cbData) ==ERROR_SUCCESS) { if (RegSetValueEx(hkTo, rgchValue, 0, dwType, rgchData, cbData) == ERROR_SUCCESS) { fRet=TRUE; } } iValue++;dwType=0;cbValue=sizeof(rgchValue);cbData=sizeof(rgchData); } end: if (hkTo) RegCloseKey(hkTo); if (hkFr) RegCloseKey(hkFr); return fRet; } DWORD ProfileGetData(ULONG_PTR dwKey, LPSTR lpszValueName, LPBYTE lpbBuf , DWORD dwcbMax) { #ifndef USE_REGISTRY return 0; #else // USE_REGISTRY DWORD dwType; LONG l = RegQueryValueEx( (HKEY) dwKey, lpszValueName, 0, &dwType, lpbBuf, &dwcbMax ); if (l!=ERROR_SUCCESS) { //LOG((_ERR, "RegQueryValueEx returned error %ld\n", (long) l)); goto copy_default; } if (dwType != REG_BINARY) { goto copy_default; } return dwcbMax; copy_default: return 0; #endif // USE_REGISTRY } BOOL ProfileWriteData(ULONG_PTR dwKey, LPSTR lpszValueName, LPBYTE lpbBuf, DWORD dwcb) { #ifndef USE_REGISTRY return 0; #else // USE_REGISTRY LONG l = ~(ERROR_SUCCESS); if (!lpszValueName) goto end; if (!lpbBuf) { // delete value... l = RegDeleteValue((HKEY) dwKey, lpszValueName); } else { l = RegSetValueEx((HKEY) dwKey, lpszValueName, 0, REG_BINARY, lpbBuf, dwcb); } end: return (l==ERROR_SUCCESS); #endif // USE_REGISTRY } #ifdef USE_REGISTRY DWORD my_atoul(LPSTR lpsz) { unsigned i=8, c; unsigned long ul=0; while(i-- && (c=*lpsz++)) { ul*=10; switch(c) { case '0': break; case '1':ul+=1; break; case '2':ul+=2; break; case '3':ul+=3; break; case '4':ul+=4; break; case '5':ul+=5; break; case '6':ul+=6; break; case '7':ul+=7; break; case '8':ul+=8; break; case '9':ul+=9; break; default: goto end; } } end: return ul; } #endif // USE_REGISTRY