diff --git a/trunk/registryhive.cpp b/trunk/registryhive.cpp index 2f9362a..7d1a734 100644 --- a/trunk/registryhive.cpp +++ b/trunk/registryhive.cpp @@ -1,962 +1,1104 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #include "registryhive.h" #include #include #include #include #include // TODO: __WORDSIZE is not defined under mingw and I currently have no idea how // to identify a 64bit windows #ifndef __WORDSIZE #define __WORDSIZE 32 #endif #if __WORDSIZE == 64 #define EPOCH_DIFF 0x19DB1DED53E8000 #else #define EPOCH_DIFF 0x19DB1DED53E8000LL #endif /******************************************************************************* * Public ******************************************************************************/ /* * RegistryHive */ RegistryHive::RegistryHive(QObject *p_parent) : QObject(p_parent) { this->erro_msg=""; this->is_error=false; this->hive_file=""; this->p_hive=NULL; this->is_hive_open=false; this->is_hive_writable=false; this->has_changes_to_commit=false; } /* * ~RegistryHive */ RegistryHive::~RegistryHive() { if(this->is_hive_open) this->Close(); } /* * Error */ bool RegistryHive::Error() { return this->is_error; } /* * GetErrorMsg */ QString RegistryHive::GetErrorMsg() { QString msg=this->erro_msg; this->erro_msg=""; this->is_error=false; return msg; } /* * Open */ bool RegistryHive::Open(QString file, bool read_only) { if(this->is_hive_open) return false; // Open hive file this->p_hive=hivex_open(file.toAscii().constData(), read_only ? 0 : HIVEX_OPEN_WRITE); if(this->p_hive==NULL) return false; // Set local vars this->hive_file=file; this->is_hive_open=true; this->is_hive_writable=!read_only; return true; } /* * Reopen */ bool RegistryHive::Reopen(bool read_only) { if(!this->is_hive_open) return false; // Close hive first if(hivex_close(this->p_hive)!=0) { // According to the docs, even if hivex_close fails, it frees all handles. // So we consider this fatal and final! this->hive_file=""; this->is_hive_open=false; this->is_hive_writable=false; this->has_changes_to_commit=false; return false; } // Reopen same hive this->p_hive=hivex_open(this->hive_file.toAscii().constData(), read_only ? 0 : HIVEX_OPEN_WRITE); if(this->p_hive==NULL) { this->hive_file=""; this->is_hive_open=false; this->is_hive_writable=false; this->has_changes_to_commit=false; return false; } // Update local vars this->is_hive_writable=!read_only; this->has_changes_to_commit=false; return true; } /* * CommitChanges */ bool RegistryHive::CommitChanges() { if(!this->is_hive_open || !this->is_hive_writable) return false; if(!this->has_changes_to_commit) return true; // TODO: Maybe it would be more secure to commit changes to a new file and // then move it over the original one. if(hivex_commit(this->p_hive,NULL,0)!=0) { return false; } return true; } /* * Close */ bool RegistryHive::Close() { if(this->is_hive_open) { // As hivex_close will _ALWAYS_ free the handle, we don't need the following // values anymore this->hive_file=""; this->is_hive_open=false; this->is_hive_writable=false; this->has_changes_to_commit=false; // Close hive if(hivex_close(this->p_hive)!=0) return false; } return true; } /* * Filename */ QString RegistryHive::Filename() { if(this->is_hive_open) return this->hive_file; return QString(); } /* * HiveType */ RegistryHive::teHiveType RegistryHive::HiveType() { // Check for SYSTEM hive if(this->PathExists("\\Select") && this->PathExists("\\MountedDevices")) return RegistryHive::eHiveType_SYSTEM; // Check for SOFTWARE hive if(this->PathExists("\\Microsoft\\Windows\\CurrentVersion") && this->PathExists("\\Microsoft\\Windows NT\\CurrentVersion")) return RegistryHive::eHiveType_SOFTWARE; // Check for SAM if(this->PathExists("SAM\\Domains\\Account\\Users")) return RegistryHive::eHiveType_SAM; // Check for SECURITY if(this->PathExists("\\Policy\\Accounts") && this->PathExists("\\Policy\\PolAdtEv")) return RegistryHive::eHiveType_SECURITY; // Check for NTUSER.DAT if(this->PathExists("\\Software\\Microsoft\\Windows\\CurrentVersion")) return RegistryHive::eHiveType_NTUSER; // Unknown hive return RegistryHive::eHiveType_UNKNOWN; } /* * HiveTypeToString */ QString RegistryHive::HiveTypeToString(teHiveType hive_type) { switch(hive_type) { case RegistryHive::eHiveType_SYSTEM: return "SYSTEM"; break; case RegistryHive::eHiveType_SOFTWARE: return "SOFTWARE"; break; case RegistryHive::eHiveType_SAM: return "SAM"; break; case RegistryHive::eHiveType_SECURITY: return "SECURITY"; break; case RegistryHive::eHiveType_NTUSER: return "NTUSER"; break; default: return "UNKNOWN"; } } /* * HasChangesToCommit */ bool RegistryHive::HasChangesToCommit() { return this->has_changes_to_commit; } /* * GetNodes */ QMap RegistryHive::GetNodes(QString path) { hive_node_h parent_node; // Get handle to last node in path if(!this->GetNodeHandle(path,&parent_node)) return QMap(); // Get and return nodes return this->GetNodesHelper(parent_node); } /* * GetNodes */ QMap RegistryHive::GetNodes(int parent_node) { if(parent_node==0) { this->SetError(tr("Invalid parent node handle specified!")); return QMap(); } // Get and return nodes return this->GetNodesHelper(parent_node); } /* * GetKeys */ QMap RegistryHive::GetKeys(QString path) { hive_node_h parent_node; // Get handle to last node in path if(!this->GetNodeHandle(path,&parent_node)) return QMap(); // Get and return keys return this->GetKeysHelper(parent_node); } /* * GetKeys */ QMap RegistryHive::GetKeys(int parent_node) { if(parent_node==0) { this->SetError(tr("Invalid parent node handle specified!")); return QMap(); } // Get and return keys return this->GetKeysHelper(parent_node); } /* * GetKeyValue */ QByteArray RegistryHive::GetKeyValue(QString path, QString key, int *p_value_type, size_t *p_value_len) { hive_node_h parent_node; hive_value_h hive_key; // Get handle to last node in path if(!this->GetNodeHandle(path,&parent_node)) return QByteArray(); // Get key handle hive_key=hivex_node_get_value(this->p_hive, parent_node,key.toAscii().constData()); if(hive_key==0) { this->SetError(tr("Unable to get key handle!")); *p_value_len=-1; return QByteArray(); } // Get and return key value return this->GetKeyValueHelper(hive_key,p_value_type,p_value_len); } /* * GetKeyValue */ QByteArray RegistryHive::GetKeyValue(int hive_key, int *p_value_type, size_t *p_value_len) { if(hive_key==0) { this->SetError(tr("Invalid key handle specified!")); *p_value_type=-1; return QByteArray(); } // Get and return key value return this->GetKeyValueHelper(hive_key,p_value_type,p_value_len); } /* * GetKeyModTime */ int64_t RegistryHive::GetNodeModTime(QString path) { hive_node_h node; // Get handle to last node in path if(!this->GetNodeHandle(path,&node)) { this->SetError(tr("Unable to get node handle!")); return 0; } // Get and return node's last modification timestamp return this->GetNodeModTime(node); } /* * GetKeyModTime */ int64_t RegistryHive::GetNodeModTime(int node) { if(node==0) { this->SetError(tr("Invalid node handle specified!")); return 0; } // Get and return key's last modification timestamp return hivex_node_timestamp(this->p_hive,node); } /* * KeyValueToString */ QString RegistryHive::KeyValueToString(QByteArray value, int value_type) { QString ret=""; int i=0; #define ToHexStr() { \ for(i=0;i0) { // Nothing to show return QString(); } // Get pointer to data at specified offset p_data=key_value.constData(); p_data+=offset; // TODO: This will fail on platforms with different endianness! #define bswap_16(value) ((((value) & 0xff) << 8) | ((value) >> 8)) #define bswap_32(value) \ (((uint32_t)bswap_16((uint16_t)((value) & 0xffff)) << 16) | \ (uint32_t)bswap_16((uint16_t)((value) >> 16))) #define bswap_64(value) \ (((uint64_t)bswap_32((uint32_t)((value) & 0xffffffff)) << 32) | \ (uint64_t)bswap_32((uint32_t)((value) >> 32))) \ // Convert full name if(format=="int8" && remaining_data_len>=1) { ret=QString().sprintf("%d",*(int8_t*)p_data); } else if(format=="uint8" && remaining_data_len>=1) { ret=QString().sprintf("%u",*(uint8_t*)p_data); } else if(format=="int16" && remaining_data_len>=2) { int16_t val=*(int16_t*)p_data; if(little_endian) ret=QString().sprintf("%d",val); else ret=QString().sprintf("%d",bswap_16(val)); } else if(format=="uint16" && remaining_data_len>=2) { uint16_t val=*(uint16_t*)p_data; if(little_endian) ret=QString().sprintf("%u",val); else ret=QString().sprintf("%u",bswap_16(val)); } else if(format=="int32" && remaining_data_len>=4) { int32_t val=*(int32_t*)p_data; if(little_endian) ret=QString().sprintf("%d",val); else ret=QString().sprintf("%d",bswap_32(val)); } else if(format=="uint32" && remaining_data_len>=4) { uint32_t val=*(uint32_t*)p_data; if(little_endian) ret=QString().sprintf("%u",val); else ret=QString().sprintf("%u",bswap_32(val)); } else if(format=="unixtime" && remaining_data_len>=4) { uint32_t val=*(uint32_t*)p_data; if(!little_endian) val=bswap_32(val); if(val==0) { ret="n/a"; } else { QDateTime date_time; date_time.setTimeSpec(Qt::UTC); date_time.setTime_t(val); ret=date_time.toString("yyyy/MM/dd hh:mm:ss"); } } else if(format=="int64" && remaining_data_len>=8) { int64_t val=*(int64_t*)p_data; if(little_endian) ret=QString("%1").arg(val); else ret=QString("%1").arg((int64_t)bswap_64(val)); } else if(format=="uint64" && remaining_data_len>=8) { uint64_t val=*(uint64_t*)p_data; if(little_endian) ret=QString("%1").arg(val); else ret=QString("%1").arg(bswap_64(val)); /* // TODO: Check how one could implement this } else if(format=="unixtime64" && remaining_data_len>=8) { if(*(uint64_t*)p_data==0) { ret="n/a"; } else { uint64_t secs=*(uint64_t*)p_data; QDateTime date_time; date_time.setTimeSpec(Qt::UTC); // Set 32bit part of date/time date_time.setTime_t(secs&0xFFFFFFFF); // Now add high 32bit part of date/time date_time.addSecs(secs>>32); ret=date_time.toString("yyyy/MM/dd hh:mm:ss"); } */ } else if(format=="filetime" && remaining_data_len>=8) { uint64_t val=*(uint64_t*)p_data; if(!little_endian) val=bswap_64(val); if(val==0) { ret="n/a"; } else { // TODO: Warn if >32bit QDateTime date_time; date_time.setTimeSpec(Qt::UTC); date_time.setTime_t(RegistryHive::FiletimeToUnixtime(val)); ret=date_time.toString("yyyy/MM/dd hh:mm:ss"); } } else if(format=="ascii") { // TODO: This fails bad if the string is not null terminated!! It might be // wise checking for a null char here ret=QString().fromAscii((char*)p_data,length); } else if(format=="utf16" && remaining_data_len>=2) { ret=QString().fromUtf16((ushort*)p_data,length); } else { // Unknown variant type or another error return QString(); } return ret; } /* * KeyValueToStringList */ QStringList RegistryHive::KeyValueToStringList(QByteArray value, int value_type) { QStringList result; const char str_sep[2]={0x00,0x00}; int last_pos=0,cur_pos=0; // Only supported on REG_MULTI_SZ values!! if(value_type!=hive_t_REG_MULTI_SZ) return QStringList(); while(last_posis_hive_writable) return 0; // Get node handle to the parent where the new node should be created hive_node_h parent_node; if(!this->GetNodeHandle(parent_node_path,&parent_node)) { // TODO: Set error return 0; } // Make sure there is no other node with same name QMap child_nodes=this->GetNodes(parent_node); if(child_nodes.contains(node_name.toAscii())) { // TODO: Set error return 0; } // Add new node hive_node_h new_node=hivex_node_add_child(this->p_hive, parent_node, node_name.toAscii().constData()); if(new_node==0) { // TODO: Set error return 0; } this->has_changes_to_commit=true; return new_node; } /* * DeleteNode */ bool RegistryHive::DeleteNode(QString node_path) { if(!this->is_hive_writable) return false; // Get node handle to the node that should be deleted hive_node_h node; if(!this->GetNodeHandle(node_path,&node)) { // TODO: Set error return false; } // Delete node if(hivex_node_delete_child(this->p_hive,node)==-1) { // TODO: Set error return false; } this->has_changes_to_commit=true; return true; } /* * AddKey */ -int RegistryHive::AddKey(QString parent_node_path, - QString key_name, - QString key_type, - QByteArray key_value) +bool RegistryHive::AddKey(QString parent_node_path, + QString key_name, + QString key_type, + QByteArray key_value, + ptsRegistryKey resulting_key) { - // TODO + if(!this->is_hive_open || !this->is_hive_writable) { + // TODO: Set error + return false; + } + + return this->SetKey(parent_node_path, + key_name, + key_type, + key_value, + resulting_key, + true); } /* * UpdateKey */ -int RegistryHive::UpdateKey(QString parent_node_path, - QString key_name, - QString key_type, - QByteArray key_value) +bool RegistryHive::UpdateKey(QString parent_node_path, + QString key_name, + QString key_type, + QByteArray key_value, + ptsRegistryKey resulting_key) { - if(!this->is_hive_writable) return 0; - - // TODO - + if(!this->is_hive_open || !this->is_hive_writable) { + // TODO: Set error + return false; + } + return this->SetKey(parent_node_path, + key_name, + key_type, + key_value, + resulting_key, + false); } /* * DeleteKey */ bool RegistryHive::DeleteKey(QString parent_node_path, QString key_name) { - // TODO + if(!this->is_hive_open || !this->is_hive_writable) { + // TODO: Set error + return false; + } + + // libhivex offers no possibility to delete a single key :-( + // As a work around, this function temporarly stores all keys of the specified + // node, then deletes them all an re-creates all but the one that should be + // deleted. + + // Get handle to parent node + hive_node_h parent_node; + if(!this->GetNodeHandle(parent_node_path,&parent_node)) { + // TODO: Set error + return false; + } + + // Get all keys + QMap node_keys; + node_keys=this->GetKeys(parent_node); + if(node_keys.empty()) { + // TODO: Set error + return false; + } + + // Get all key values + QList node_key_values; + QMapIterator node_keys_it(node_keys); + while(node_keys_it.hasNext()) { + node_keys_it.next(); + node_key_values.append(this->GetKeyValue()); + } } /******************************************************************************* * Private ******************************************************************************/ /* * SetError */ void RegistryHive::SetError(QString msg) { this->erro_msg=msg; this->is_error=true; } /* * GetNodeHandle */ bool RegistryHive::GetNodeHandle(QString &path, hive_node_h *p_node) { QStringList nodes; int i=0; // Get root node handle *p_node=hivex_root(this->p_hive); if(*p_node==0) { this->SetError(tr("Unable to get root node!")); return false; } if(path!="\\") { // If we aren't listing the root node, we have to get a handle to the // last node in the path. Split path into nodes nodes=path.split('\\',QString::SkipEmptyParts); // Iterate to the correct parent node for(i=0;ip_hive, *p_node, nodes.value(i).toAscii().constData()); if(*p_node==0) { this->SetError(tr("Unable to find node '%1'!").arg(nodes.value(i))); return false; } } } return true; } /* * GetNodesHelper */ QMap RegistryHive::GetNodesHelper(hive_node_h parent_node) { QMap keys; char *p_name; int i=0; // Get child nodes hive_node_h *child_nodes=hivex_node_children(this->p_hive,parent_node); if(child_nodes==NULL) { this->SetError( tr("Unable to enumerate child nodes!")); return QMap(); } // Build result keys.clear(); i=0; while(child_nodes[i]) { p_name=hivex_node_name(this->p_hive,child_nodes[i]); if(p_name==NULL) { this->SetError(tr("Unable to get node name!")); free(child_nodes); return QMap(); } keys.insert(QString(p_name),(int)child_nodes[i]); free(p_name); i++; } free(child_nodes); return keys; } /* * GetKeysHelper */ QMap RegistryHive::GetKeysHelper(hive_node_h parent_node) { QMap keys; char *p_name; int i=0; // Get child keys hive_value_h *p_keys=hivex_node_values(this->p_hive,parent_node); if(p_keys==NULL) { this->SetError( tr("Unable to enumerate child keys!")); return QMap(); } // Build result list keys.clear(); i=0; while(p_keys[i]) { p_name=hivex_value_key(this->p_hive,p_keys[i]); if(p_name==NULL) { this->SetError(tr("Unable to get key name!")); return QMap(); } keys.insert(QString(p_name),p_keys[i]); free(p_name); i++; } free(p_keys); return keys; } /* * GetKeyValueHelper */ QByteArray RegistryHive::GetKeyValueHelper(hive_value_h hive_key, int *p_value_type, size_t *p_value_len) { QByteArray key_value; char *p_key_value; p_key_value=hivex_value_value(this->p_hive, hive_key, (hive_type*)p_value_type, p_value_len); if(p_key_value==NULL) { this->SetError(tr("Unable to get key value!")); *p_value_type=-1; return QByteArray(); } // Feed QByteArray and free p_key_value key_value=QByteArray(p_key_value,*p_value_len); free(p_key_value); return key_value; } /* * PathExists */ bool RegistryHive::PathExists(QString path) { bool ret; hive_node_h node; ret=this->GetNodeHandle(path,&node); if(!ret || this->Error()) { // Clear error and return false this->GetErrorMsg(); return false; } return true; } +/* + * StringToKeyValueType + */ int RegistryHive::StringToKeyValueType(QString value_type) { if(value_type=="REG_NONE") return hive_t_REG_NONE; if(value_type=="REG_SZ") return hive_t_REG_SZ; if(value_type=="REG_EXPAND_SZ") return hive_t_REG_EXPAND_SZ; if(value_type=="REG_BINARY") return hive_t_REG_BINARY; if(value_type=="REG_DWORD") return hive_t_REG_DWORD; if(value_type=="REG_DWORD_BIG_ENDIAN") return hive_t_REG_DWORD_BIG_ENDIAN; if(value_type=="REG_LINK") return hive_t_REG_LINK; if(value_type=="REG_MULTI_SZ") return hive_t_REG_MULTI_SZ; if(value_type=="REG_RESOURCE_LIST") return hive_t_REG_RESOURCE_LIST; if(value_type=="REG_FULL_RESOURCE_DESC") return hive_t_REG_FULL_RESOURCE_DESCRIPTOR; if(value_type=="REG_RESOURCE_REQ_LIST") return hive_t_REG_RESOURCE_REQUIREMENTS_LIST; if(value_type=="REG_QWORD") return hive_t_REG_QWORD; // I think this might be a good default :-) return hive_t_REG_BINARY; } +/* + * GetKey + */ +bool RegistryHive::GetKey(QString &parent_node_path, + QString &key_name, + ptsRegistryKey *key_value) +{ + // Get handle to parent node + hive_node_h parent_node; + if(!this->GetNodeHandle(parent_node_path,&parent_node)) { + // TODO: Set error + return false; + } + + // Get handle to key + hive_value_h key=hivex_node_get_value(this->p_hive, + parent_node, + key_name.toAscii().constData()); + if(new_key==0) { + // TODO: Set error + return false; + } + + // Alloc memory for the ptsRegistryKey struct + *key_value=(ptsRegistryKey)malloc(sizeof(tsRegistryKey)); + if(*key_value==NULL) { + // TODO: Set error + return false; + } + + // Get key name from hive (We could also simply use the specified name, but + // this allows to us to get the actual upper/lowercase name from hive. + char *buf; + buf=hivex_value_key(this->p_hive,key); + if(buf==NULL) { + // TODO: Set error + return false; + } + // Store name in ptsRegistryKey struct + *key_value->name=QString().fromLocal8Bit(buf); + free(buf); + + // Get key value + buf=hivex_value_value(this->p_hive, + key, + (hive_type*)&(*key_value->type), + &(*key_value->value_len)); + if(buf==NULL) { + // TODO: Set error + return false; + } + // Store value in ptsRegistryKey struct + *key_value->value=QByteArray(buf,*key_value->value_len); + free(buf); + + return true; +} + +/* + * GetKeys + */ +bool RegistryHive::GetKeys(QString &parent_node_path, + QList *p_key_values) +{ + // Get handle to parent node + hive_node_h parent_node; + if(!this->GetNodeHandle(parent_node_path,&parent_node)) { + // TODO: Set error + return false; + } + + // TODO: Check if this is really needed + // hive_value_h *hivex_node_values (hive_h *h, hive_node_h node); + return false; +} + /* * SetKey */ -int RegistryHive::SetKey(QString &parent_node_path, - QString &key_name, - QString &key_type, - QByteArray &key_value) +bool RegistryHive::SetKey(QString &parent_node_path, + QString &key_name, + QString &key_type, + QByteArray &key_value, + ptsRegistryKey *resulting_key, + bool create_key) { // Get node handle to the node that holds the key to create/update hive_node_h parent_node; if(!this->GetNodeHandle(parent_node_path,&parent_node)) { // TODO: Set error - return 0; + return false; + } + + // Make sure key exists if we should update it + if(!create_key) { + hive_value_h temp_key=hivex_node_get_value(this->p_hive, + parent_node, + key_name.toAscii().constData()); + if(temp_key==0) { + // TODO: Set error + return false; + } } // Create and populate hive_set_value structure hive_set_value key_val; key_val.key=(char*)malloc((sizeof(char)*key_name.toAscii().count())+1); key_val.value=(char*)malloc(sizeof(char)*key_value.size()); if(key_val.key==NULL || key_val.value==NULL) { // TODO: Set error - return 0; + return false; } strcpy(key_val.key,key_name.toAscii().constData()); key_val.t=(hive_type)this->StringToKeyValueType(key_type); key_val.len=key_value.size(); strncpy(key_val.value,key_value.constData(),key_value.size()); // Create/Update key if(hivex_node_set_value(this->p_hive,parent_node,&key_val,0)!=0) { // TODO: Set error - return 0; + return false; } // Free the hive_set_value structure free(key_val.key); free(key_val.value); - // TODO: Get handle to key and return whatever is ok (Probably QMap) - return 0; + // To make sure everything worked, the key is now requeried from hive and then + // returned in the ptsRegistryKey struct + return this->GetKey(parent_node_path,key_name,resulting_key); } diff --git a/trunk/registryhive.h b/trunk/registryhive.h index f6fd956..3b85255 100644 --- a/trunk/registryhive.h +++ b/trunk/registryhive.h @@ -1,121 +1,137 @@ /******************************************************************************* * fred Copyright (c) 2011-2013 by Gillen Daniel * * * * Forensic Registry EDitor (fred) is a cross-platform M$ registry hive editor * * with special feautures useful during forensic analysis. * * * * This program is free software: you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the Free * * Software Foundation, either version 3 of the License, or (at your option) * * any later version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * * more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see . * *******************************************************************************/ #ifndef REGISTRYHIVE_H #define REGISTRYHIVE_H #include #include #include class RegistryHive : public QObject { Q_OBJECT public: + typedef struct sRegistryKey { + QString name; + int type; + size_t value_len; + QByteArray value; + } tsRegistryKey, *ptsRegistryKey; + typedef enum eHiveType { eHiveType_UNKNOWN=0, eHiveType_SYSTEM, eHiveType_SOFTWARE, eHiveType_SAM, eHiveType_SECURITY, eHiveType_NTUSER } teHiveType; explicit RegistryHive(QObject *p_parent=0); ~RegistryHive(); bool Error(); QString GetErrorMsg(); bool Open(QString file, bool read_only=true); bool Reopen(bool read_only=true); bool CommitChanges(); bool Close(); QString Filename(); teHiveType HiveType(); QString HiveTypeToString(teHiveType hive_type); bool HasChangesToCommit(); QMap GetNodes(QString path="\\"); QMap GetNodes(int parent_node=0); QMap GetKeys(QString path="\\"); QMap GetKeys(int parent_node=0); QByteArray GetKeyValue(QString path, QString key, int *p_value_type, size_t *p_value_len); QByteArray GetKeyValue(int hive_key, int *p_value_type, size_t *p_value_len); int64_t GetNodeModTime(QString path); int64_t GetNodeModTime(int node); static QString KeyValueToString(QByteArray value, int value_type); static QString KeyValueToString(QByteArray value, QString format, int offset=0, int length=0, bool little_endian=true); static QStringList KeyValueToStringList(QByteArray value, int value_type); static QStringList GetKeyValueTypes(); // TODO: Rename KeyTypeToString to KeyValueTypeToString static QString KeyTypeToString(int value_type); static uint64_t FiletimeToUnixtime(int64_t filetime); int AddNode(QString parent_node_path, QString node_name); bool DeleteNode(QString node_path); - int AddKey(QString parent_node_path, - QString key_name, - QString key_type, - QByteArray key_value); - int UpdateKey(QString parent_node_path, - QString key_name, - QString key_type, - QByteArray key_value); + bool AddKey(QString parent_node_path, + QString key_name, + QString key_type, + QByteArray key_value, + ptsRegistryKey resulting_key); + bool UpdateKey(QString parent_node_path, + QString key_name, + QString key_type, + QByteArray key_value, + ptsRegistryKey resulting_key); bool DeleteKey(QString parent_node_path, QString key_name); private: QString erro_msg; bool is_error; QString hive_file; hive_h *p_hive; bool is_hive_open; bool is_hive_writable; bool has_changes_to_commit; void SetError(QString msg); bool GetNodeHandle(QString &path, hive_node_h *p_node); QMap GetNodesHelper(hive_node_h parent_node); QMap GetKeysHelper(hive_node_h parent_node); QByteArray GetKeyValueHelper(hive_value_h hive_key, int *p_value_type, size_t *p_value_len); bool PathExists(QString path); int StringToKeyValueType(QString value_type); - int SetKey(QString &parent_node_path, - QString &key_name, - QString &key_type, - QByteArray &key_value); + bool GetKey(QString &parent_node_path, + QString &key_name, + ptsRegistryKey *key_value); + bool GetKeys(QString &parent_node_path, + QList *p_key_values); + bool SetKey(QString &parent_node_path, + QString &key_name, + QString &key_type, + QByteArray &key_value, + ptsRegistryKey *resulting_key, + bool create_key); }; #endif // REGISTRYHIVE_H