//------------------------------------------------------------------------------
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);
    }
  }
}
//------------------------------------------------------------------------------
int callback_sqlite_registry_file(void *datas, int argc, char **argv, char **azColName)
{
  FORMAT_CALBAK_TYPE *type = datas;
  unsigned int session_id = current_session_id;
  char tmp[MAX_LINE_SIZE];
  switch(type->type)
  {
    case SQLITE_REGISTRY_TYPE_SETTINGS:
    {
      switch(atoi(argv[3]))//value_type
      {
        case TYPE_VALUE_STRING:
        case TYPE_VALUE_DWORD:
        case TYPE_VALUE_MULTI_STRING:
          if (Readnk_Value(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, local_hks.position,
                           argv[1], NULL, argv[2], tmp, MAX_LINE_SIZE))
          {
            //key update
            char parent_key_update[DATE_SIZE_MAX];
            Readnk_Infos(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin), local_hks.position,
                         argv[1], NULL, parent_key_update, DATE_SIZE_MAX, NULL, 0,NULL, 0);

            //save
            convertStringToSQL(tmp, MAX_LINE_SIZE);
            addRegistrySettingstoDB(local_hks.file, "", argv[1], argv[2], tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
          }
        break;
        case TYPE_VALUE_MULTI_WSTRING:
        {
          char data_read[MAX_LINE_SIZE];
          DWORD pos=0, data_size_read = MAX_LINE_SIZE;
          if (ReadBinarynk_Value(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, local_hks.position,
                                 argv[1], NULL, argv[2], tmp, &data_size_read))
          {
            if (data_size_read)
            {
              //data_read
              while ((pos-1)*2<data_size_read)
              {
                snprintf(data_read+pos,MAX_LINE_SIZE,"%S;",tmp+(pos*2-1));
                pos = strlen(data_read);
              }

              //key update
              char parent_key_update[DATE_SIZE_MAX];
              Readnk_Infos(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin), local_hks.position,
                           argv[1], NULL, parent_key_update, DATE_SIZE_MAX, NULL, 0,NULL, 0);

              //save
              convertStringToSQL(data_read, MAX_LINE_SIZE);
              addRegistrySettingstoDB(local_hks.file, "", argv[1], argv[2], data_read, argv[4], argv[5], parent_key_update, session_id, db_scan);
            }
          }
        }
        break;
        case TYPE_VALUE_FILETIME:
        {
          DWORD data_size = sizeof(FILETIME)+1;
          FILETIME f_date;
          if (ReadBinarynk_Value(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, local_hks.position,
                           argv[1], NULL, argv[2], (void*)&f_date, &data_size))
          {
            //key update
            char parent_key_update[DATE_SIZE_MAX];
            Readnk_Infos(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin), local_hks.position,
                         argv[1], NULL, parent_key_update, DATE_SIZE_MAX, NULL, 0,NULL, 0);

            //convert date
            tmp[0] = 0;
            filetimeToString_GMT(f_date, tmp, DATE_SIZE_MAX);

            //save
            convertStringToSQL(tmp, MAX_LINE_SIZE);
            addRegistrySettingstoDB(local_hks.file, "", argv[1], argv[2], tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
          }
        }
        break;
        case TYPE_VALUE_WIN_SERIAL:
        {
          HBIN_CELL_NK_HEADER *nk_h = GetRegistryNK(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, local_hks.position,argv[1]);
          if (nk_h!=NULL)
          {
            //key update
            char parent_key_update[DATE_SIZE_MAX];
            Readnk_Infos(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin), local_hks.position,
                         NULL, nk_h, parent_key_update, DATE_SIZE_MAX, NULL, 0,NULL, 0);



            //get value
            DWORD test_size = MAX_LINE_SIZE;
            DWORD serial_size;
            ReadBinarynk_Value(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, local_hks.position,
                                                         NULL, nk_h, argv[2], (void*)tmp, &test_size);
            if (test_size>65)
            {
              char result[MAX_PATH]="";

              char key[25] = "BCDFGHJKMPQRTVWXY2346789";
              BYTE enc[MAX_PATH];
              char lpszSerial[MAX_PATH];
              int i,c=0,nCur=0;

              for(i=52;i<=66;i++)enc[i-52] = tmp[i];
              for(i=24;i>=0;i--)
              {
                nCur = 0;
                for(c=14;c>-1;c--)
                {
                  nCur = nCur * 256;
                  nCur ^= enc[c];
                  enc[c] = nCur / 24;
                  nCur %= 24;
                }
                lpszSerial[i] = key[nCur];
              }

              serial_size = 0;
              for(i=0;lpszSerial[i] && (i+i/5) < 30 && MAX_PATH>serial_size;i++)
              {
                if(i % 5 == 0 && i>0)snprintf(result+serial_size,MAX_PATH-serial_size,"-%c",lpszSerial[i]);
                else snprintf(result+serial_size,MAX_PATH-serial_size,"%c",lpszSerial[i]);
                serial_size = strlen(result);
              }

              //save
              convertStringToSQL(result, MAX_LINE_SIZE);
              addRegistrySettingstoDB(local_hks.file, "", argv[1], argv[2], result, argv[4], argv[5], parent_key_update, session_id, db_scan);
            }
          }
        }
        break;
        case TYPE_ENUM_STRING_VALUE:
        {
          HBIN_CELL_NK_HEADER *nk_h = GetRegistryNK(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, local_hks.position,argv[1]);
          if (nk_h!=NULL)
          {
            //key update
            char parent_key_update[DATE_SIZE_MAX];
            Readnk_Infos(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin), local_hks.position,
                         NULL, nk_h, parent_key_update, DATE_SIZE_MAX, NULL, 0,NULL, 0);

            //get values
            char value[MAX_PATH];
            DWORD i, nbSubValue = GetValueData(local_hks.buffer,local_hks.taille_fic, nk_h, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, 0, NULL, 0, NULL, 0);
            for (i=0;i<nbSubValue;i++)
            {
              if (GetValueData(local_hks.buffer,local_hks.taille_fic, nk_h, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, i,value,MAX_PATH,tmp,MAX_LINE_SIZE))
              {
                //save
                convertStringToSQL(value, MAX_PATH);
                convertStringToSQL(tmp, MAX_LINE_SIZE);
                addRegistrySettingstoDB(local_hks.file, "", argv[1], value, tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
              }
            }
          }
        }
        break;
      }
    }
  }
  return 0;
}
//------------------------------------------------------------------------------
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);
    }
  }
}