//------------------------------------------------------------------------------
void GetUserGroupFromRegFile(DWORD rid, char *group, DWORD group_size_max, HK_F_OPEN *hks, char *reg_path)
{
  HBIN_CELL_NK_HEADER *nk_h = GetRegistryNK(hks->buffer, hks->taille_fic, (hks->pos_fhbin)+HBIN_HEADER_SIZE, hks->position, reg_path);
  if (nk_h == NULL)return;

  HBIN_CELL_NK_HEADER *nk_h_tmp;
  char cbuffer[MAX_LINE_SIZE], buffer[MAX_LINE_SIZE];
  DWORD valueSize,i,nbSubKey = GetSubNK(hks->buffer, hks->taille_fic, nk_h, hks->position, 0, NULL, 0);
  for (i=0;i<nbSubKey;i++)
  {
    //get nk of key :)
    nk_h_tmp = GetSubNKtonk(hks->buffer, hks->taille_fic, nk_h, hks->position, i);
    if (nk_h_tmp == NULL)continue;

    //C
    buffer[0]  = 0;
    cbuffer[0] = 0;
    valueSize  = MAX_LINE_SIZE;
    if(ReadBinarynk_Value(hks->buffer, hks->taille_fic, (hks->pos_fhbin)+HBIN_HEADER_SIZE, hks->position, NULL, nk_h_tmp,"C", buffer, &valueSize))
    {
      DataToHexaChar(buffer, valueSize, cbuffer, MAX_LINE_SIZE);
      TraiterGroupDataFromSAM_C(cbuffer, rid,  group,  group_size_max);
    }
  }
}
//------------------------------------------------------------------------------
void GetUserGroupInfos(unsigned int rid, char *group, unsigned int group_size_max, char *reg_path)
{
  int ret = set_sam_tree_access(HKEY_LOCAL_MACHINE,reg_path);
  if (ret == 0)
  {
    //read all groups
    HKEY CleTmp;
    if (RegOpenKey(HKEY_LOCAL_MACHINE,reg_path,&CleTmp)==ERROR_SUCCESS)
    {
      DWORD i,nbSubKey = 0, SubKeysize, valueSize;
      char NomSubKey[MAX_PATH], path[MAX_PATH],buffer[MAX_LINE_SIZE],cbuffer[MAX_LINE_SIZE];
      RegQueryInfoKey (CleTmp,0,0,0,&nbSubKey,0,0,0,0,0,0,0);
      for(i=0;i<nbSubKey;i++)
      {
        NomSubKey[0]=0;
        SubKeysize = MAX_PATH;
        if (RegEnumKeyEx(CleTmp,i,NomSubKey,&SubKeysize,0,0,0,0)==ERROR_SUCCESS)
        {
          //génération du path group
          buffer[0] = 0;
          cbuffer[0] = 0;
          snprintf(path,MAX_PATH,"%s\\%s",reg_path,NomSubKey);
          if((valueSize = ReadValue(HKEY_LOCAL_MACHINE, path, "C", buffer, MAX_LINE_SIZE)))
          {
            DataToHexaChar(buffer, valueSize, cbuffer, MAX_LINE_SIZE);
            TraiterGroupDataFromSAM_C(cbuffer, rid,  group,  group_size_max);
          }
        }
      }
      RegCloseKey(CleTmp);
    }
  }
  restore_sam_tree_access(HKEY_LOCAL_MACHINE,reg_path);
}
//------------------------------------------------------------------------------
void Scan_registry_user_file(HK_F_OPEN *hks, sqlite3 *db, unsigned int session_id, char *computer_name)
{
  DWORD userRID = 0;
  USERS_INFOS User_infos;
  #ifdef CMD_LINE_ONLY_NO_DB
  printf("\"RegistryUser\";\"source\";\"name\";\"RID\";\"SID\";\"grp\";\"description\";\"last_logon\";\"last_password_change\";"
         "\"nb_connexion\";\"type\";\"state_id\";\"session_id\";\r\n");
  #endif
  //get ref key for hashs
  BYTE b_f[MAX_LINE_SIZE];
  Readnk_Value(hks->buffer, hks->taille_fic, (hks->pos_fhbin)+HBIN_HEADER_SIZE, hks->position, "SAM\\Domains\\Account", NULL,"F", b_f, MAX_LINE_SIZE);

  //enum all users
  //exist or not in the file ?
  HBIN_CELL_NK_HEADER *nk_h = GetRegistryNK(hks->buffer, hks->taille_fic, (hks->pos_fhbin)+HBIN_HEADER_SIZE, hks->position, "SAM\\Domains\\Account\\Users");
  if (nk_h == NULL)return;

  HBIN_CELL_NK_HEADER *nk_h_tmp;
  DWORD valueSize;
  BOOL ok_test;
  char SubKeyName[MAX_PATH];
  char cbuffer[MAX_LINE_SIZE], buffer[MAX_LINE_SIZE];
  DWORD i,nbSubKey = GetSubNK(hks->buffer, hks->taille_fic, nk_h, hks->position, 0, NULL, 0);
  for (i=0;i<nbSubKey;i++)
  {
    ok_test = FALSE;
    //for each subkey
    if(GetSubNK(hks->buffer, hks->taille_fic, nk_h, hks->position, i, SubKeyName, MAX_PATH))
    {
      //get nk of key :)
      nk_h_tmp = GetSubNKtonk(hks->buffer, hks->taille_fic, nk_h, hks->position, i);
      if (nk_h_tmp == NULL)continue;

      //F
      buffer[0]  = 0;
      cbuffer[0] = 0;
      valueSize  = MAX_LINE_SIZE;
      if(ReadBinarynk_Value(hks->buffer, hks->taille_fic, (hks->pos_fhbin)+HBIN_HEADER_SIZE, hks->position, NULL, nk_h_tmp,"F", buffer, &valueSize))
      {
        DataToHexaChar(buffer, valueSize, cbuffer, MAX_LINE_SIZE);
        userRID = TestUserDataFromSAM_F(&User_infos,cbuffer);
        ok_test = TRUE;
      }

      //V
      buffer[0]  = 0;
      cbuffer[0] = 0;
      valueSize  = MAX_LINE_SIZE;
      if(ReadBinarynk_Value(hks->buffer, hks->taille_fic, (hks->pos_fhbin)+HBIN_HEADER_SIZE, hks->position, NULL, nk_h_tmp,"V", buffer, &valueSize))
      {
        DataToHexaChar(buffer, valueSize, cbuffer, MAX_LINE_SIZE);
        if(TestUserDataFromSAM_V(&User_infos,cbuffer,computer_name))
        {
          //test if rid and sid ok
          userRID = HTDF(SubKeyName,8);
          if(User_infos.RID[0] == 0)snprintf(User_infos.RID,MAX_PATH,"%05lu",userRID);
          if(User_infos.SID[0] == 0)snprintf(User_infos.SID,MAX_PATH,"S-1-5-?-?-?-?-%lu",userRID);
        }else
        {
          if(User_infos.RID[0] == 0 && userRID)snprintf(User_infos.RID,MAX_PATH,"%05lu",userRID);
          if(User_infos.SID[0] == 0 && userRID)snprintf(User_infos.SID,MAX_PATH,"S-1-5-?-?-?-?-%lu",userRID);
        }
        ok_test = TRUE;
      }else
      {
        if(User_infos.RID[0] == 0 && userRID)snprintf(User_infos.RID,MAX_PATH,"%05lu",userRID);
        if(User_infos.SID[0] == 0 && userRID)snprintf(User_infos.SID,MAX_PATH,"S-1-5-?-?-?-?-%lu",userRID);
      }

      if (!ok_test)continue;

      //get groups
      if (userRID) GetUserGroupFRF(userRID, User_infos.group, MAX_PATH);

      //get hashs
      if(b_f[0] != 0 && _SYSKEY[0] != 0)
      {
        DecodeSAMHashXP(_SYSKEY,User_infos.pwdump_pwd_raw_format,userRID,User_infos.name,b_f);
      }

      //add user
      convertStringToSQL(User_infos.description, MAX_PATH);
      addRegistryUsertoDB(hks->file,User_infos.name, User_infos.RID, User_infos.SID, User_infos.group,
                          User_infos.description, User_infos.last_logon, User_infos.last_password_change,
                          User_infos.nb_connexion, User_infos.type, User_infos.state_id,session_id, db);

      //add password
      if (TEST_REG_PASSWORD_ENABLE)
        addPasswordtoDB(hks->file, User_infos.name, User_infos.pwdump_pwd_format, User_infos.pwdump_pwd_raw_format, REG_PASSWORD_STRING_LOCAL_USER, session_id, db);
    }
  }
}
//------------------------------------------------------------------------------
BOOL registry_users_extract(sqlite3 *db, unsigned int session_id)
{
  BOOL ok = FALSE;
  DWORD userRID;
  USERS_INFOS User_infos;

  //import syskey
  char sk[MAX_PATH]="";
  BOOL syskeyok = registry_syskey_local(sk, MAX_PATH);

  //get current computer name
  char computer_name[COMPUTER_NAME_SIZE_MAX]="";
  DWORD taille = COMPUTER_NAME_SIZE_MAX;
  GetComputerName(computer_name,&taille);

  //Set ACL in registry
  int ret = set_sam_tree_access(HKEY_LOCAL_MACHINE,"SECURITY\\SAM\\Domains\\Account\\Users");
  if (ret == 0)
  {
    //get reference key for users hashs
    HKEY CleTmp;
    BOOL ok_test;
    BYTE b_f[MAX_LINE_SIZE];
    if(ReadValue(HKEY_LOCAL_MACHINE, "SAM\\SAM\\Domains\\Account", "F", (char*)b_f, MAX_LINE_SIZE)<= 0x80)b_f[0] = 0;

    //get users
    if (RegOpenKey(HKEY_LOCAL_MACHINE,"SAM\\SAM\\Domains\\Account\\Users\\",&CleTmp)==ERROR_SUCCESS)
    {
      DWORD i, valueSize, SizeSubKeyName, nbSubKey = 0;
      if (RegQueryInfoKey (CleTmp,0,0,0,&nbSubKey,0,0,0,0,0,0,0)==ERROR_SUCCESS)
      {
        char SubKeyName[MAX_PATH], path[MAX_PATH], buffer[MAX_LINE_SIZE], cbuffer[MAX_LINE_SIZE];

        for (i=0;i<nbSubKey;i++)
        {
          ok_test       = FALSE;
          SizeSubKeyName=MAX_PATH;// on reinitialise la taille a chaque fois sinon il ne lit pas la valeur suivant
          SubKeyName[0] = 0;
          if(RegEnumKeyEx (CleTmp,i,SubKeyName,&SizeSubKeyName,0,0,0,0)!=ERROR_SUCCESS)continue;

          //read value
          snprintf(path,MAX_PATH,"SAM\\SAM\\Domains\\Account\\Users\\%s",SubKeyName);

          //F value
          cbuffer[0]= 0;
          buffer[0] = 0;
          userRID   = 0;
          valueSize = ReadValue(HKEY_LOCAL_MACHINE, path, "F", buffer, MAX_LINE_SIZE);
          if (valueSize)
          {
            DataToHexaChar(buffer, valueSize, cbuffer, MAX_LINE_SIZE);
            userRID = TestUserDataFromSAM_F(&User_infos,cbuffer);
            ok_test = TRUE;
         }

          //V value
          cbuffer[0]= 0;
          buffer[0] = 0;
          valueSize = ReadValue(HKEY_LOCAL_MACHINE, path, "V", buffer, MAX_LINE_SIZE);
          if (valueSize)
          {
            //read datas
            DataToHexaChar(buffer, valueSize, cbuffer, MAX_LINE_SIZE);
            if(TestUserDataFromSAM_V(&User_infos,cbuffer,computer_name))
            {
              //test if rid and sid ok
              userRID = HTDF(SubKeyName,8);
              if(User_infos.RID[0] == 0)snprintf(User_infos.RID,MAX_PATH,"%05lu",userRID);
              if(User_infos.SID[0] == 0)snprintf(User_infos.SID,MAX_PATH,"S-1-5-?-?-?-?-%lu",userRID);
           }else
            {
              if((User_infos.RID[0] == 0) && userRID)snprintf(User_infos.RID,MAX_PATH,"%05lu",userRID);
              if((User_infos.SID[0] == 0) && userRID)snprintf(User_infos.SID,MAX_PATH,"S-1-5-?-?-?-?-%lu",userRID);
            }
            ok_test = TRUE;
          }else
          {
            if((User_infos.RID[0] == 0) && userRID)snprintf(User_infos.RID,MAX_PATH,"%05lu",userRID);
            if((User_infos.SID[0] == 0) && userRID)snprintf(User_infos.SID,MAX_PATH,"S-1-5-?-?-?-?-%lu",userRID);
         }

          if (!ok_test)continue;

          //get groups
          if (userRID) GetUserGroup(userRID, User_infos.group, MAX_PATH);

          //get hashs
          if((b_f[0] != 0) && syskeyok)
          {
            DecodeSAMHashXP(sk,User_infos.pwdump_pwd_raw_format,userRID,User_infos.name,b_f);
          }

          //add user
          convertStringToSQL(User_infos.description, MAX_PATH);
          addRegistryUsertoDB("HKEY_LOCAL_MACHINE\\SAM",User_infos.name, User_infos.RID, User_infos.SID, User_infos.group,
                              User_infos.description, User_infos.last_logon, User_infos.last_password_change,
                              User_infos.nb_connexion, User_infos.type, User_infos.state_id,session_id, db);

          //add password
          if (TEST_REG_PASSWORD_ENABLE)
            addPasswordtoDB("HKEY_LOCAL_MACHINE\\SAM", User_infos.name, User_infos.pwdump_pwd_format, User_infos.pwdump_pwd_raw_format, REG_PASSWORD_STRING_LOCAL_USER, session_id, db);
          ok = TRUE;
        }
      }
      RegCloseKey(CleTmp);
    }
  }

  //Restore ACL in registry
  restore_sam_tree_access(HKEY_LOCAL_MACHINE,"SECURITY\\SAM\\Domains\\Account\\Users");

  return ok;
}