//-----------------------------------------------------------------------// // // File: compare.cpp // Created: April 1999 // By: Zeyong Xu // Purpose: Compare two registry key // //------------------------------------------------------------------------// #include "stdafx.h" #include "reg.h" #include "compare.h" BOOL g_bHasDifference = FALSE; //-----------------------------------------------------------------------// // // CompareRegistry() // //-----------------------------------------------------------------------// LONG CompareRegistry(PAPPVARS pAppVars, PAPPVARS pDstVars, UINT argc, TCHAR *argv[]) { LONG nResult; HKEY hLeftKey; HKEY hRightKey; // // Parse the cmd-line // nResult = ParseCompareCmdLine(pAppVars, pDstVars, 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; } nResult = RegConnectMachine(pDstVars); if (nResult != ERROR_SUCCESS) { return nResult; } // // Now implement the body of the Compare Operation // nResult = RegOpenKeyEx(pAppVars->hRootKey, pAppVars->szSubKey, 0, KEY_READ, &hLeftKey); if (nResult != ERROR_SUCCESS) { return nResult; } nResult = RegOpenKeyEx(pDstVars->hRootKey, pDstVars->szSubKey, 0, KEY_READ, &hRightKey); if (nResult != ERROR_SUCCESS) { return nResult; } // if try to compare the same keys if (pAppVars->hRootKey == pDstVars->hRootKey && _tcsicmp(pAppVars->szFullKey, pDstVars->szFullKey) == 0) { RegCloseKey(hLeftKey); RegCloseKey(hRightKey); return REG_STATUS_COMPARESELF; } // // compare a single value if pAppVars->szValueName is not NULL // if(pAppVars->szValueName) { nResult = CompareValues(hLeftKey, pAppVars->szFullKey, hRightKey, pDstVars->szFullKey, pAppVars->szValueName, pAppVars->nOutputType); } else { // // Recursively compare if pAppVars->bRecurseSubKeys is true // nResult = CompareEnumerateKey(hLeftKey, pAppVars->szFullKey, hRightKey, pDstVars->szFullKey, pAppVars->nOutputType, pAppVars->bRecurseSubKeys); } if(nResult == ERROR_SUCCESS) { pAppVars->bHasDifference = g_bHasDifference; if(g_bHasDifference) MyTPrintf(stdout,_T("\r\nResult Compared: Different\r\n")); else MyTPrintf(stdout,_T("\r\nResult Compared: Identical\r\n")); } // // lets clean up // RegCloseKey(hLeftKey); RegCloseKey(hRightKey); return nResult; } REG_STATUS ParseCompareCmdLine(PAPPVARS pAppVars, PAPPVARS pDstVars, UINT argc, TCHAR *argv[]) { UINT i; REG_STATUS nResult = ERROR_SUCCESS; BOOL bInvalidParams = FALSE; // // Do we have a *valid* number of cmd-line params // if(argc < 4) { return REG_STATUS_TOFEWPARAMS; } else if(argc > 8) { return REG_STATUS_TOMANYPARAMS; } // // Left Machine Name and Registry key // nResult = BreakDownKeyString(argv[2], pAppVars); if(nResult != ERROR_SUCCESS) return nResult; // // Right Machine Name and Registry key // nResult = BreakDownKeyString(argv[3], pDstVars); if(nResult == REG_STATUS_NOKEYNAME) { // if no keyname for right side is specified, // they are comparing the same key name nResult = CopyKeyNameFromLeftToRight(pAppVars, pDstVars); } if( nResult != ERROR_SUCCESS) return nResult; // parsing for(i=4; ibRecurseSubKeys) return REG_STATUS_INVALIDPARAMS; bInvalidParams = TRUE; i++; if(iszValueName = (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(bInvalidParams || pAppVars->bRecurseSubKeys) return REG_STATUS_INVALIDPARAMS; bInvalidParams = TRUE; pAppVars->szValueName = (TCHAR*) calloc(1, sizeof(TCHAR)); if (!pAppVars->szValueName) { return ERROR_NOT_ENOUGH_MEMORY; } } else if(!_tcsicmp(argv[i], _T("/oa"))) { if(bInvalidParams) return REG_STATUS_INVALIDPARAMS; bInvalidParams = TRUE; pAppVars->nOutputType = OUTPUTTYPE_ALL; } else if(!_tcsicmp(argv[i], _T("/od"))) { if(bInvalidParams) return REG_STATUS_INVALIDPARAMS; bInvalidParams = TRUE; pAppVars->nOutputType = OUTPUTTYPE_DIFF; } else if(!_tcsicmp(argv[i], _T("/os"))) { if(bInvalidParams) return REG_STATUS_INVALIDPARAMS; bInvalidParams = TRUE; pAppVars->nOutputType = OUTPUTTYPE_SAME; } else if(!_tcsicmp(argv[i], _T("/on"))) { if(bInvalidParams) return REG_STATUS_INVALIDPARAMS; bInvalidParams = TRUE; pAppVars->nOutputType = OUTPUTTYPE_NONE; } else if(!_tcsicmp(argv[i], _T("/s"))) { if(pAppVars->szValueName) return REG_STATUS_INVALIDPARAMS; pAppVars->bRecurseSubKeys = TRUE; } else { nResult = REG_STATUS_INVALIDPARAMS; } } return nResult; } REG_STATUS CopyKeyNameFromLeftToRight(APPVARS* pAppVars, APPVARS* pDstVars) { // check if rootkey is remotable for right side if( pDstVars->bUseRemoteMachine && !(pAppVars->hRootKey == HKEY_USERS || pAppVars->hRootKey == HKEY_LOCAL_MACHINE) ) { return REG_STATUS_NONREMOTABLEROOT; } pDstVars->szFullKey = (TCHAR*) calloc(_tcslen(pAppVars->szFullKey) + 1, sizeof(TCHAR)); if (!pDstVars->szFullKey) return ERROR_NOT_ENOUGH_MEMORY; pDstVars->szSubKey = (TCHAR*) calloc(_tcslen(pAppVars->szSubKey) + 1, sizeof(TCHAR)); if (!pDstVars->szSubKey) { free (pDstVars->szFullKey); return ERROR_NOT_ENOUGH_MEMORY; } _tcscpy(pDstVars->szFullKey, pAppVars->szFullKey); pDstVars->hRootKey = pAppVars->hRootKey; _tcscpy(pDstVars->szSubKey, pAppVars->szSubKey); return ERROR_SUCCESS; } //-----------------------------------------------------------------------// // // EnumerateKey() - Recursive // //-----------------------------------------------------------------------// LONG CompareEnumerateKey(HKEY hLeftKey, TCHAR* szLeftFullKeyName, HKEY hRightKey, TCHAR* szRightFullKeyName, int nOutputType, BOOL bRecurseSubKeys) { DWORD nResult; DWORD dwSize; TCHAR* pszLeftNameBuf; TCHAR* pszRightNameBuf; TCHAR** pLeftArray; TCHAR** pRightArray; DWORD dwIndex; DWORD dwNumOfLeftKeyName; DWORD dwLenOfLeftKeyName; DWORD dwNumOfRightKeyName; DWORD dwLenOfRightKeyName; DWORD dw; HKEY hLeftSubKey; HKEY hRightSubKey; // enumerate all values under current key nResult = CompareEnumerateValueName(hLeftKey, szLeftFullKeyName, hRightKey, szRightFullKeyName, nOutputType); if(!bRecurseSubKeys || nResult != ERROR_SUCCESS) return nResult; // enum all subkeys // query left key info nResult = RegQueryInfoKey(hLeftKey, NULL, NULL, NULL, &dwNumOfLeftKeyName, &dwLenOfLeftKeyName, NULL, NULL, NULL, NULL, NULL, NULL); if (nResult != ERROR_SUCCESS) { return nResult; } // query right key info nResult = RegQueryInfoKey(hRightKey, NULL, NULL, NULL, &dwNumOfRightKeyName, &dwLenOfRightKeyName, NULL, NULL, NULL, 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(dwLenOfLeftKeyName < MAX_PATH) dwLenOfLeftKeyName = MAX_PATH; if(dwLenOfRightKeyName < MAX_PATH) dwLenOfRightKeyName = MAX_PATH; #endif // // enumerate all of the subkeys in left key // dwLenOfLeftKeyName++; pszLeftNameBuf = (TCHAR*) calloc(dwNumOfLeftKeyName * dwLenOfLeftKeyName, sizeof(TCHAR)); if (!pszLeftNameBuf) { nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } // index array of name buffer for compare pLeftArray = (TCHAR**) calloc(dwNumOfLeftKeyName, sizeof(TCHAR*)); if (!pLeftArray) { nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } dwIndex = 0; while(dwIndex < dwNumOfLeftKeyName && nResult == ERROR_SUCCESS) { pLeftArray[dwIndex] = pszLeftNameBuf + (dwIndex * dwLenOfLeftKeyName); dwSize = dwLenOfLeftKeyName; nResult = RegEnumKeyEx(hLeftKey, dwIndex, pLeftArray[dwIndex], &dwSize, NULL, NULL, NULL, NULL); dwIndex++; } if (nResult != ERROR_SUCCESS) { if(pszLeftNameBuf) free(pszLeftNameBuf); if(pLeftArray) free(pLeftArray); return nResult; } // // enumerate all of the subkeys in right key // dwLenOfRightKeyName++; pszRightNameBuf = (TCHAR*) calloc(dwNumOfRightKeyName * dwLenOfRightKeyName, sizeof(TCHAR)); if (!pszRightNameBuf) { nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } // index array of name buffer for compare pRightArray = (TCHAR**) calloc(dwNumOfRightKeyName, sizeof(TCHAR*)); if (!pRightArray) { nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } dwIndex = 0; while(dwIndex < dwNumOfRightKeyName && nResult == ERROR_SUCCESS) { pRightArray[dwIndex] = pszRightNameBuf + (dwIndex * dwLenOfRightKeyName); dwSize = dwLenOfRightKeyName; nResult = RegEnumKeyEx(hRightKey, dwIndex, pRightArray[dwIndex], &dwSize, NULL, NULL, NULL, NULL); dwIndex++; } if (nResult != ERROR_SUCCESS) { if(pszLeftNameBuf) free(pszLeftNameBuf); if(pLeftArray) free(pLeftArray); if(pszRightNameBuf) free(pszRightNameBuf); if(pRightArray) free(pRightArray); return nResult; } // compare two subkey name array to find the same subkey for(dwIndex = 0; dwIndex < dwNumOfLeftKeyName && nResult == ERROR_SUCCESS; dwIndex++) { if(pLeftArray[dwIndex] == NULL) continue; for(dw = 0; dw < dwNumOfRightKeyName && nResult == ERROR_SUCCESS; dw++) { if(pRightArray[dw] == NULL) continue; // if same subey name, recusive if(_tcsicmp(pLeftArray[dwIndex], pRightArray[dw]) == 0) { TCHAR* szTempLeft; TCHAR* szTempRight; // print out key if( nOutputType == OUTPUTTYPE_SAME || nOutputType == OUTPUTTYPE_ALL ) { nResult = PrintKey(hLeftKey, szLeftFullKeyName, pLeftArray[dwIndex], PRINTTYPE_SAME); if(nResult != ERROR_SUCCESS) break; } // // Now implement the body of the Compare Operation // nResult = RegOpenKeyEx(hLeftKey, pLeftArray[dwIndex], 0, KEY_READ, &hLeftSubKey); if (nResult != ERROR_SUCCESS) break; nResult = RegOpenKeyEx(hRightKey, pLeftArray[dwIndex], 0, KEY_READ, &hRightSubKey); if (nResult != ERROR_SUCCESS) break; // create left full subkey szTempLeft = (TCHAR*) calloc(_tcslen(szLeftFullKeyName) + _tcslen(pLeftArray[dwIndex]) + 2, sizeof(TCHAR)); if (!szTempLeft) { nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } _tcscpy(szTempLeft, szLeftFullKeyName); _tcscat(szTempLeft, _T("\\")); _tcscat(szTempLeft, pLeftArray[dwIndex]); // create right full subkey szTempRight = (TCHAR*) calloc(_tcslen(szRightFullKeyName) + _tcslen(pLeftArray[dwIndex]) + 2, sizeof(TCHAR)); if (!szTempRight) { free (szTempLeft); nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } _tcscpy(szTempRight, szRightFullKeyName); _tcscat(szTempRight, _T("\\")); _tcscat(szTempRight, pLeftArray[dwIndex]); // recursive to compare subkeys nResult = CompareEnumerateKey(hLeftSubKey, szLeftFullKeyName, hRightSubKey, szRightFullKeyName, nOutputType, bRecurseSubKeys); if(szTempLeft) { free(szTempLeft); } if(szTempRight) { free(szTempRight); } RegCloseKey(hLeftSubKey); RegCloseKey(hRightSubKey); pLeftArray[dwIndex] = NULL; pRightArray[dw] = NULL; break; } } } // Output subkey name in left key for(dwIndex = 0; dwIndex < dwNumOfLeftKeyName && nResult == ERROR_SUCCESS; dwIndex++) { if(pLeftArray[dwIndex] == NULL) continue; if( nOutputType == OUTPUTTYPE_DIFF || nOutputType == OUTPUTTYPE_ALL ) { nResult = PrintKey(hLeftKey, szLeftFullKeyName, pLeftArray[dwIndex], PRINTTYPE_LEFT); } g_bHasDifference = TRUE; } // Output subkey name in right key for(dwIndex = 0; dwIndex < dwNumOfRightKeyName && nResult == ERROR_SUCCESS; dwIndex++) { if(pRightArray[dwIndex] == NULL) continue; if( nOutputType == OUTPUTTYPE_DIFF || nOutputType == OUTPUTTYPE_ALL ) { nResult = PrintKey(hRightKey, szRightFullKeyName, pRightArray[dwIndex], PRINTTYPE_RIGHT); } g_bHasDifference = TRUE; } Cleanup: if(pszLeftNameBuf) free(pszLeftNameBuf); if(pLeftArray) free(pLeftArray); if(pszRightNameBuf) free(pszRightNameBuf); if(pRightArray) free(pRightArray); return nResult; } LONG CompareEnumerateValueName(HKEY hLeftKey, TCHAR* szLeftFullKeyName, HKEY hRightKey, TCHAR* szRightFullKeyName, int nOutputType) { DWORD nResult = ERROR_SUCCESS; DWORD dwSize; TCHAR* pszLeftNameBuf = NULL; TCHAR* pszRightNameBuf = NULL; TCHAR** pLeftArray = NULL; TCHAR** pRightArray = NULL; DWORD dwIndex; DWORD dwNumOfRightValueName; DWORD dwLenOfRightValueName; DWORD dw; // query left key info DWORD dwNumOfLeftValueName; DWORD dwLenOfLeftValueName; nResult = RegQueryInfoKey(hLeftKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumOfLeftValueName, &dwLenOfLeftValueName, NULL, NULL, NULL); if (nResult != ERROR_SUCCESS) { return nResult; } // query right key info nResult = RegQueryInfoKey(hRightKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumOfRightValueName, &dwLenOfRightValueName, 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(dwLenOfLeftValueName < MAX_PATH) dwLenOfLeftValueName = MAX_PATH; if(dwLenOfRightValueName < MAX_PATH) dwLenOfRightValueName = MAX_PATH; #endif // // enumerate all of the values in left key // dwLenOfLeftValueName++; pszLeftNameBuf = (TCHAR*) calloc(dwNumOfLeftValueName * dwLenOfLeftValueName, sizeof(TCHAR)); if (!pszLeftNameBuf) { nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } // index array of name buffer for compare pLeftArray = (TCHAR**) calloc(dwNumOfLeftValueName, sizeof(TCHAR*)); if (!pLeftArray) { nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } dwIndex = 0; while(dwIndex < dwNumOfLeftValueName && nResult == ERROR_SUCCESS) { pLeftArray[dwIndex] = pszLeftNameBuf + (dwIndex * dwLenOfLeftValueName); dwSize = dwLenOfLeftValueName; nResult = RegEnumValue(hLeftKey, dwIndex, pLeftArray[dwIndex], &dwSize, NULL, NULL, NULL, NULL); dwIndex++; } if (nResult != ERROR_SUCCESS) { if(pszLeftNameBuf) free(pszLeftNameBuf); if(pLeftArray) free(pLeftArray); return nResult; } // // enumerate all of the values in right key // dwLenOfRightValueName++; pszRightNameBuf = (TCHAR*) calloc(dwNumOfRightValueName * dwLenOfRightValueName, sizeof(TCHAR)); if (!pszRightNameBuf) { nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } // index array of name buffer for compare pRightArray = (TCHAR**) calloc(dwNumOfRightValueName, sizeof(TCHAR*)); if (!pRightArray) { nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } dwIndex = 0; while(dwIndex < dwNumOfRightValueName && nResult == ERROR_SUCCESS) { pRightArray[dwIndex] = pszRightNameBuf + (dwIndex * dwLenOfRightValueName); dwSize = dwLenOfRightValueName; nResult = RegEnumValue(hRightKey, dwIndex, pRightArray[dwIndex], &dwSize, NULL, NULL, NULL, NULL); dwIndex++; } if (nResult != ERROR_SUCCESS) { if(pszLeftNameBuf) free(pszLeftNameBuf); if(pLeftArray) free(pLeftArray); if(pszRightNameBuf) free(pszRightNameBuf); if(pRightArray) free(pRightArray); return nResult; } // compare two valuename array to find the same valuename for(dwIndex = 0; dwIndex < dwNumOfLeftValueName && nResult == ERROR_SUCCESS; dwIndex++) { if(pLeftArray[dwIndex] == NULL) continue; for(dw = 0; dw < dwNumOfRightValueName && nResult == ERROR_SUCCESS; dw++) { if(pRightArray[dw] == NULL) continue; // same valuename if(_tcsicmp(pLeftArray[dwIndex], pRightArray[dw]) == 0) { nResult = CompareValues(hLeftKey, szLeftFullKeyName, hRightKey, szRightFullKeyName, pLeftArray[dwIndex], nOutputType); pLeftArray[dwIndex] = NULL; pRightArray[dw] = NULL; break; } } } // Output different valuename in left key for(dwIndex = 0; dwIndex < dwNumOfLeftValueName && nResult == ERROR_SUCCESS; dwIndex++) { if(pLeftArray[dwIndex] == NULL) continue; if( nOutputType == OUTPUTTYPE_DIFF || nOutputType == OUTPUTTYPE_ALL ) { nResult = OutputValue(hLeftKey, szLeftFullKeyName, pLeftArray[dwIndex], PRINTTYPE_LEFT); } g_bHasDifference = TRUE; } // Output different valuename in right key for(dwIndex = 0; dwIndex < dwNumOfRightValueName && nResult == ERROR_SUCCESS; dwIndex++) { if(pRightArray[dwIndex] == NULL) continue; if( nOutputType == OUTPUTTYPE_DIFF || nOutputType == OUTPUTTYPE_ALL ) { nResult = OutputValue(hRightKey, szRightFullKeyName, pRightArray[dwIndex], PRINTTYPE_RIGHT); } g_bHasDifference = TRUE; } Cleanup: if(pszLeftNameBuf) free(pszLeftNameBuf); if(pLeftArray) free(pLeftArray); if(pszRightNameBuf) free(pszRightNameBuf); if(pRightArray) free(pRightArray); return nResult; } //-----------------------------------------------------------------------// // // CompareValues() // //-----------------------------------------------------------------------// LONG CompareValues(HKEY hLeftKey, TCHAR* szLeftFullKeyName, HKEY hRightKey, TCHAR* szRightFullKeyName, TCHAR* szValueName, int nOutputType) { LONG nResult; DWORD dwTypeLeft; DWORD dwTypeRight; DWORD dwSizeLeft; DWORD dwSizeRight; BYTE* pDataBuffLeft = NULL; BYTE* pDataBuffRight = NULL; // // First find out how much memory to allocate // nResult = RegQueryValueEx(hLeftKey, szValueName, 0, &dwTypeLeft, NULL, &dwSizeLeft); if (nResult != ERROR_SUCCESS) { return nResult; } nResult = RegQueryValueEx(hRightKey, szValueName, 0, &dwTypeRight, NULL, &dwSizeRight); if (nResult != ERROR_SUCCESS) { return nResult; } pDataBuffLeft = (BYTE*) calloc(dwSizeLeft + 1, sizeof(BYTE)); if (!pDataBuffLeft) { nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } pDataBuffRight = (BYTE*) calloc(dwSizeRight + 1, sizeof(BYTE)); if (!pDataBuffRight) { nResult = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } // // Now get the data // nResult = RegQueryValueEx(hLeftKey, szValueName, 0, &dwTypeLeft, (LPBYTE) pDataBuffLeft, &dwSizeLeft); if (nResult == ERROR_SUCCESS) { nResult = RegQueryValueEx(hRightKey, szValueName, 0, &dwTypeRight, (LPBYTE) pDataBuffRight, &dwSizeRight); } if(nResult != ERROR_SUCCESS) { if(pDataBuffLeft) free(pDataBuffLeft); if(pDataBuffRight) free(pDataBuffRight); return nResult; } if( dwTypeLeft != dwTypeRight || dwSizeLeft != dwSizeRight || CompareByteData(pDataBuffLeft, pDataBuffRight, dwSizeLeft) ) { if( nOutputType == OUTPUTTYPE_DIFF || nOutputType == OUTPUTTYPE_ALL ) { // print left and right PrintValue(szLeftFullKeyName, szValueName, dwTypeLeft, pDataBuffLeft, dwSizeLeft, PRINTTYPE_LEFT); PrintValue(szRightFullKeyName, szValueName, dwTypeRight, pDataBuffRight, dwSizeRight, PRINTTYPE_RIGHT); } g_bHasDifference = TRUE; } else // they are the same { if( nOutputType == OUTPUTTYPE_SAME || nOutputType == OUTPUTTYPE_ALL ) { PrintValue(szLeftFullKeyName, szValueName, dwTypeLeft, pDataBuffLeft, dwSizeLeft, PRINTTYPE_SAME); } } Cleanup: if(pDataBuffLeft) free(pDataBuffLeft); if(pDataBuffRight) free(pDataBuffRight); return nResult; } LONG PrintKey(HKEY hKey, TCHAR* szFullKeyName, TCHAR* szSubKeyName, int nPrintType) { LONG nResult; HKEY hSubKey; // make sure key is there nResult = RegOpenKeyEx(hKey, szSubKeyName, 0, KEY_READ, &hSubKey); if (nResult != ERROR_SUCCESS) return nResult; RegCloseKey(hSubKey); // print type if(nPrintType == PRINTTYPE_LEFT) MyTPrintf(stdout,_T("< ")); else if(nPrintType == PRINTTYPE_RIGHT) MyTPrintf(stdout,_T("> ")); else if(nPrintType == PRINTTYPE_SAME) MyTPrintf(stdout,_T("= ")); MyTPrintf(stdout,_T("Key: %s\\%s\r\n"), szFullKeyName, szSubKeyName); return nResult; } LONG OutputValue(HKEY hKey, TCHAR* szFullKeyName, TCHAR* szValueName, int nPrintType) { LONG nResult = ERROR_SUCCESS; DWORD dwType; DWORD dwSize; BYTE* pDataBuff; // // First find out how much memory to allocate // nResult = RegQueryValueEx(hKey, szValueName, 0, &dwType, NULL, &dwSize); if (nResult != ERROR_SUCCESS) { return nResult; } pDataBuff = (BYTE*) calloc(dwSize + 1, sizeof(BYTE)); if (!pDataBuff) { return ERROR_NOT_ENOUGH_MEMORY; } // // Now get the data // nResult = RegQueryValueEx(hKey, szValueName, 0, &dwType, (LPBYTE) pDataBuff, &dwSize); if(nResult == ERROR_SUCCESS) { PrintValue(szFullKeyName, szValueName, dwType, pDataBuff, dwSize, nPrintType); } if(pDataBuff) free(pDataBuff); return nResult; } void PrintValue(TCHAR* szFullKeyName, TCHAR* szValueName, DWORD dwType, BYTE* pData, DWORD dwSize, int nPrintType) { DWORD i; TCHAR szTypeStr[25]; // print type if(nPrintType == PRINTTYPE_LEFT) MyTPrintf(stdout,_T("< ")); else if(nPrintType == PRINTTYPE_RIGHT) MyTPrintf(stdout,_T("> ")); else if(nPrintType == PRINTTYPE_SAME) MyTPrintf(stdout,_T("= ")); // first Print Key MyTPrintf(stdout,_T("Value: %s"), szFullKeyName); // then print ValueName Type Data GetTypeStrFromType(szTypeStr, dwType); if(_tcslen(szValueName) == 0) // no name { MyTPrintf(stdout,_T(" %s "), szTypeStr); } else { MyTPrintf(stdout,_T(" %s %s "), szValueName, szTypeStr); } switch (dwType) { case REG_BINARY: for(i=0; i