//-----------------------------------------------------------------------// // // File: query.cpp // Created: Jan 1997 // By: Martin Holladay (a-martih) // Purpose: Registry Query Support for REG.CPP // Modification History: // Created - Jan 1997 (a-martih) // Aug 1997 (John Whited) Implemented a Binary output function for // REG_BINARY // Oct 1997 (martinho) fixed output for REG_MULTI_SZ \0 delimited strings // April 1998 - MartinHo - Incremented to 1.05 for REG_MULTI_SZ bug fixes. // Correct support for displaying query REG_MULTI_SZ of. Fix AV. // April 1999 Zeyong Xu: re-design, revision -> version 2.0 // //------------------------------------------------------------------------// #include "stdafx.h" #include "reg.h" //-----------------------------------------------------------------------// // // QueryRegistry() // //-----------------------------------------------------------------------// LONG QueryRegistry(PAPPVARS pAppVars, UINT argc, TCHAR *argv[]) { LONG nResult; HKEY hKey; // // Parse the cmd-line // nResult = ParseQueryCmdLine(pAppVars, argc, argv); if (nResult != ERROR_SUCCESS) { return nResult; } // // Connect to the Remote Machine(s) - if applicable // nResult = RegConnectMachine(pAppVars); if (nResult != ERROR_SUCCESS) { return nResult; } // // Open the registry key // nResult = RegOpenKeyEx(pAppVars->hRootKey, pAppVars->szSubKey, 0, KEY_READ, &hKey); if(nResult != ERROR_SUCCESS) return nResult; MyTPrintf(stdout,_T("\r\n! REG.EXE VERSION %s\r\n"), REG_EXE_FILEVERSION); // // if query a single registry value // if(pAppVars->szValueName) { // first print the key name MyTPrintf(stdout,_T("\r\n%s\r\n"), pAppVars->szFullKey); nResult = QueryValue(hKey, pAppVars->szValueName); MyTPrintf(stdout,_T("\r\n")); } else // query a registry key { nResult = QueryEnumerateKey(hKey, pAppVars->szFullKey, pAppVars->bRecurseSubKeys); } RegCloseKey(hKey); return nResult; } //------------------------------------------------------------------------// // // ParseQueryCmdLine() // //------------------------------------------------------------------------// REG_STATUS ParseQueryCmdLine(PAPPVARS pAppVars, UINT argc, TCHAR *argv[]) { REG_STATUS nResult; UINT i; if(argc < 3) { return REG_STATUS_TOFEWPARAMS; } else if(argc > 5) { return REG_STATUS_TOMANYPARAMS; } // Machine Name and Registry key // nResult = BreakDownKeyString(argv[2], pAppVars); if(nResult != ERROR_SUCCESS) return nResult; // parsing for(i=3; i<argc; i++) { if(!_tcsicmp(argv[i], _T("/v"))) { if(pAppVars->szValueName || pAppVars->bRecurseSubKeys) return REG_STATUS_INVALIDPARAMS; i++; if(i<argc) { pAppVars->szValueName = (TCHAR*) calloc(_tcslen(argv[i]) + 1, sizeof(TCHAR)); if (!pAppVars->szValueName) { return ERROR_NOT_ENOUGH_MEMORY; } _tcscpy(pAppVars->szValueName, argv[i]); } else return REG_STATUS_TOFEWPARAMS; } else if(!_tcsicmp(argv[i], _T("/ve"))) { if(pAppVars->szValueName || pAppVars->bRecurseSubKeys) return REG_STATUS_INVALIDPARAMS; pAppVars->szValueName = (TCHAR*) calloc(1, sizeof(TCHAR)); if (!pAppVars->szValueName) { return ERROR_NOT_ENOUGH_MEMORY; } } else if(!_tcsicmp(argv[i], _T("/s"))) { if(pAppVars->szValueName) return REG_STATUS_INVALIDPARAMS; pAppVars->bRecurseSubKeys = TRUE; } else return REG_STATUS_INVALIDPARAMS; } return ERROR_SUCCESS; } //-----------------------------------------------------------------------// // // GetTypeStr() // //-----------------------------------------------------------------------// void GetTypeStrFromType(TCHAR *szTypeStr, DWORD dwType) { switch (dwType) { case REG_BINARY: _tcscpy(szTypeStr, STR_REG_BINARY); break; case REG_DWORD: _tcscpy(szTypeStr, STR_REG_DWORD); break; case REG_DWORD_BIG_ENDIAN: _tcscpy(szTypeStr, STR_REG_DWORD_BIG_ENDIAN); break; case REG_EXPAND_SZ: _tcscpy(szTypeStr, STR_REG_EXPAND_SZ); break; case REG_LINK: _tcscpy(szTypeStr, STR_REG_LINK); break; case REG_MULTI_SZ: _tcscpy(szTypeStr, STR_REG_MULTI_SZ); break; case REG_NONE: _tcscpy(szTypeStr, STR_REG_NONE); break; case REG_RESOURCE_LIST: _tcscpy(szTypeStr, STR_REG_RESOURCE_LIST); break; case REG_SZ: _tcscpy(szTypeStr, STR_REG_SZ); break; default: _tcscpy(szTypeStr, STR_REG_NONE); break; } } //-----------------------------------------------------------------------// // // QueryValue() // //-----------------------------------------------------------------------// LONG QueryValue(HKEY hKey, TCHAR* szValueName) { LONG nResult; TCHAR szTypeStr[25]; DWORD dwType; DWORD dwSize = 1; UINT i; BYTE* pBuff; TCHAR szEmptyString[ 2 ] = L""; if ( szValueName == NULL ) { szValueName = szEmptyString; } // // First find out how much memory to allocate. // nResult = RegQueryValueEx(hKey, szValueName, 0, &dwType, NULL, &dwSize); if (nResult != ERROR_SUCCESS) { return nResult; } // to avoid problems with corrupted registry data -- // always allocate memory of even no. of bytes dwSize += ( dwSize % 2 ); pBuff = (BYTE*) calloc(dwSize + 2, sizeof(BYTE)); if (!pBuff) { return ERROR_NOT_ENOUGH_MEMORY; } // // Now get the data // nResult = RegQueryValueEx(hKey, szValueName, 0, &dwType, (LPBYTE) pBuff, &dwSize); if (nResult != ERROR_SUCCESS) { free(pBuff); return nResult; } // // Now list the ValueName\tType\tData // GetTypeStrFromType(szTypeStr, dwType); MyTPrintf(stdout, _T(" %s\t%s\t"), (_tcslen(szValueName) == 0) // no name ? g_NoName : szValueName, szTypeStr); switch (dwType) { default: case REG_BINARY: for(i=0; i<dwSize; i++) { MyTPrintf(stdout,_T("%02X"),pBuff[i]); } break; case REG_SZ: case REG_EXPAND_SZ: MyTPrintf(stdout,_T("%s"), (LPCWSTR)pBuff ); break; case REG_DWORD: case REG_DWORD_BIG_ENDIAN: MyTPrintf(stdout,_T("0x%x"), *((DWORD*)pBuff) ); break; case REG_MULTI_SZ: { // // Replace '\0' with "\0" for MULTI_SZ // TCHAR* pEnd = (TCHAR*) pBuff; while( (BYTE*)pEnd < pBuff + dwSize ) { if(*pEnd == 0) { MyTPrintf(stdout,_T("\\0")); pEnd++; } else { MyTPrintf(stdout,_T("%s"), pEnd); pEnd += _tcslen(pEnd); } } } break; } MyTPrintf(stdout,_T("\r\n")); if(pBuff) free(pBuff); return ERROR_SUCCESS; } //-----------------------------------------------------------------------// // // EnumerateKey() - Recursive // //-----------------------------------------------------------------------// LONG QueryEnumerateKey(HKEY hKey, TCHAR* szFullKey, BOOL bRecurseSubKeys) { DWORD nResult; UINT i; DWORD dwSize; HKEY hSubKey; TCHAR* szNameBuf; TCHAR* szTempName; // query source key info DWORD dwLenOfKeyName; DWORD dwLenOfValueName; nResult = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, &dwLenOfKeyName, NULL, NULL, &dwLenOfValueName, NULL, NULL, NULL); if (nResult != ERROR_SUCCESS) { return nResult; } #ifndef REG_FOR_WIN2000 // ansi version for win98 // fix API bugs: RegQueryInfoKey() returns non-correct length values // on remote Win98 if(dwLenOfKeyName < MAX_PATH) dwLenOfKeyName = MAX_PATH; if(dwLenOfValueName < MAX_PATH) dwLenOfValueName = MAX_PATH; #endif // create buffer dwLenOfValueName++; szNameBuf = (TCHAR*) calloc(dwLenOfValueName, sizeof(TCHAR)); if (!szNameBuf) { return ERROR_NOT_ENOUGH_MEMORY; } // first print the key name MyTPrintf(stdout,_T("\r\n%s\r\n"), szFullKey); // // enumerate all of the values // i = 0; do { dwSize = dwLenOfValueName; nResult = RegEnumValue(hKey, i, szNameBuf, &dwSize, NULL, NULL, NULL, NULL); if (nResult == ERROR_SUCCESS) { nResult = QueryValue(hKey, szNameBuf); // continue to query if(nResult == ERROR_ACCESS_DENIED) { MyTPrintf(stderr, _T("Error: Access is denied in the value %s under") _T(" the key %s\r\n"), szNameBuf, szFullKey); nResult = ERROR_SUCCESS; } } i++; } while (nResult == ERROR_SUCCESS); if(szNameBuf) free(szNameBuf); if (nResult == ERROR_NO_MORE_ITEMS) nResult = ERROR_SUCCESS; if( nResult != ERROR_SUCCESS ) return nResult; // // SPECIAL CASE: // ------------- // For HKLM\SYSTEM\CONTROLSET002 it is found to be API returning value 0 for dwMaxLength // though there are subkeys underneath this -- to handle this, we are doing a workaround // by assuming the max registry key length // if ( dwLenOfKeyName == 0 ) { dwLenOfKeyName = 256; } else if ( dwLenOfKeyName < 256 ) { // always assume 100% more length than what is returned by API dwLenOfKeyName *= 2; } // // Now Enumerate all of the keys // dwLenOfKeyName++; szNameBuf = (TCHAR*) calloc(dwLenOfKeyName, sizeof(TCHAR)); if (!szNameBuf) { return ERROR_NOT_ENOUGH_MEMORY; } i = 0; do { dwSize = dwLenOfKeyName; nResult = RegEnumKeyEx(hKey, i, szNameBuf, &dwSize, NULL, NULL, NULL, NULL); if (nResult != ERROR_SUCCESS) break; // // open up the subkey, and enumerate it // nResult = RegOpenKeyEx(hKey, szNameBuf, 0, KEY_READ, &hSubKey); // // Build up the needed string and go down enumerating again // szTempName = (TCHAR*) calloc(_tcslen(szFullKey) + _tcslen(szNameBuf) + 2, sizeof(TCHAR)); if (!szTempName) { nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } _tcscpy(szTempName, szFullKey); _tcscat(szTempName, _T("\\")); _tcscat(szTempName, szNameBuf); if (bRecurseSubKeys && nResult == ERROR_SUCCESS) { // recursive query nResult = QueryEnumerateKey(hSubKey, szTempName, bRecurseSubKeys); } else { // print key MyTPrintf(stdout,_T("\r\n%s\r\n"), szTempName); if(nResult == ERROR_ACCESS_DENIED) // continue to query next key { MyTPrintf(stderr, _T("Error: Access is denied in the key %s\r\n"), szTempName); nResult = ERROR_SUCCESS; } } RegCloseKey(hSubKey); if(szTempName) free(szTempName); i++; } while (nResult == ERROR_SUCCESS); Cleanup: if(szNameBuf) free(szNameBuf); if (nResult == ERROR_NO_MORE_ITEMS) nResult = ERROR_SUCCESS; return nResult; }