WIP: SV_DLL_WIN #17
94
clego/src/CPS.rs
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
pub fn decode_zone_memoire( ZDonneesSortie: *mut std::ffi::c_void,TTailleDonneesSortie: usize){
|
||||||
|
|
||||||
|
println!("Taille sortie SSV_LireCartePS : {}", TTailleDonneesSortie);
|
||||||
|
println!("ZDonneesSortie: {:?}", ZDonneesSortie);
|
||||||
|
|
||||||
|
// Convertir le pointeur en tranche de bytes
|
||||||
|
let bytes: &[u8] = unsafe {
|
||||||
|
std::slice::from_raw_parts(ZDonneesSortie as *const u8, TTailleDonneesSortie)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Maintenant, vous pouvez accéder aux octets individuels dans `donnees`
|
||||||
|
for &octet in bytes {
|
||||||
|
println!("Octet: {}", octet);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut current_pos_general = 0;
|
||||||
|
let mut current_groupe = 0;
|
||||||
|
let mut num_champ = 0;
|
||||||
|
|
||||||
|
while current_pos_general < bytes.len() - 1 {
|
||||||
|
num_champ = 0;
|
||||||
|
current_groupe = 256 * bytes[current_pos_general] as i32 + bytes[current_pos_general + 1] as i32;
|
||||||
|
|||||||
|
current_pos_general += 2;
|
||||||
|
|
||||||
|
let longueur_groupe: usize;
|
||||||
|
if bytes[current_pos_general] < 128 {
|
||||||
|
longueur_groupe = bytes[current_pos_general] as usize;
|
||||||
|
} else {
|
||||||
|
let nbre_octets_longueur = bytes[current_pos_general] - 128;
|
||||||
|
longueur_groupe = (0..nbre_octets_longueur)
|
||||||
|
.fold(0, |acc, i| {
|
||||||
|
current_pos_general += 1;
|
||||||
|
acc + (256_i32.pow(i as u32) * bytes[current_pos_general] as i32) as usize
|
||||||
|
});
|
||||||
|
}
|
||||||
florian_briand
commented
Idem ici, on peut extraire tout ce bloc dans une fonction dédiée, pour clarifier le code :
Idem ici, on peut extraire tout ce bloc dans une fonction dédiée, pour clarifier le code :
```
/// Calcule la longueur du groupe à partir de la position actuelle dans la tranche de bytes.
///
/// Arguments:
/// * `bytes`: La tranche de bytes à analyser.
/// * `current_pos_general`: La position actuelle dans la tranche de bytes.
///
/// Retourne:
/// * La longueur du groupe calculée.
/// * La nouvelle position actuelle après calcul.
fn calculer_longueur_groupe(bytes: &[u8], mut current_pos_general: usize) -> (usize, usize) {
let longueur_groupe: usize;
if bytes[current_pos_general] < 128 {
longueur_groupe = bytes[current_pos_general] as usize;
} else {
let nbre_octets_longueur = bytes[current_pos_general] - 128;
longueur_groupe = (0..nbre_octets_longueur).fold(0, |acc, i| {
current_pos_general += 1;
acc + (256_i32.pow(i as u32) * bytes[current_pos_general] as i32) as usize
});
}
current_pos_general += 1;
(longueur_groupe, current_pos_general)
}
```
```
let (longueur_groupe, nouvelle_position) = calculer_longueur_groupe(&bytes, current_pos_general);
current_pos_general = nouvelle_position;
```
|
|||||||
|
current_pos_general += 1;
|
||||||
|
|
||||||
|
let mut current_pos_groupe = 0;
|
||||||
|
while current_pos_groupe < longueur_groupe {
|
||||||
|
num_champ += 1;
|
||||||
|
let longueur_champs: usize;
|
||||||
|
let nbre_octets_longueur: usize;
|
||||||
|
if bytes[current_pos_general] < 128 {
|
||||||
|
longueur_champs = bytes[current_pos_general] as usize;
|
||||||
|
nbre_octets_longueur = 1;
|
||||||
|
} else {
|
||||||
|
nbre_octets_longueur = bytes[current_pos_general] as usize - 128;
|
||||||
|
longueur_champs = (0..nbre_octets_longueur)
|
||||||
|
.fold(0, |acc, i| {
|
||||||
|
current_pos_general += 1;
|
||||||
|
current_pos_groupe += 1;
|
||||||
|
acc + (256_i32.pow(i as u32) * bytes[current_pos_general] as i32) as usize
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut bytes_champ = vec![0; longueur_champs];
|
||||||
|
if longueur_champs > 0 {
|
||||||
|
bytes_champ.copy_from_slice(&bytes[current_pos_general + nbre_octets_longueur..current_pos_general + nbre_octets_longueur + longueur_champs]);
|
||||||
|
|
||||||
|
match current_groupe {
|
||||||
|
1 => match num_champ {
|
||||||
|
1 => println!("Groupe1.Champ1: {}", String::from_utf8_lossy(&bytes_champ)),
|
||||||
|
2 => println!("Groupe1.Champ2: {}", String::from_utf8_lossy(&bytes_champ)),
|
||||||
|
3 => println!("Groupe1.Champ3: {}", String::from_utf8_lossy(&bytes_champ)),
|
||||||
|
4 => println!("Groupe1.Champ4: {}", String::from_utf8_lossy(&bytes_champ)),
|
||||||
|
5 => println!("Groupe1.Champ5: {}", String::from_utf8_lossy(&bytes_champ)),
|
||||||
|
6 => println!("Groupe1.Champ6: {}", String::from_utf8_lossy(&bytes_champ)),
|
||||||
|
7 => println!("Groupe1.Champ7: {}", String::from_utf8_lossy(&bytes_champ)),
|
||||||
|
8 => println!("Groupe1.Champ8: {}", String::from_utf8_lossy(&bytes_champ)),
|
||||||
|
_ => (),
|
||||||
florian_briand
commented
Et l'idéal, ici, serait de stocker ces valeurs dans une structure appropriée, en nommant + explicitement les champs, et éventuellement en les typant de manière + appropriée que juste un String ?
Et l'idéal, ici, serait de stocker ces valeurs dans une structure appropriée, en nommant + explicitement les champs, et éventuellement en les typant de manière + appropriée que juste un String ?
```
struct Groupe1 {
champ1: String,
champ2: String,
champ3: String,
champ4: String,
champ5: String,
champ6: String,
Prenom: String,
champ8: String,
}
```
julien.misiak
commented
des que tu es dispo je te montrerai ce que j'avais fait en vb. le set de l'un fixe la valeur de l'autre (et c'est là que Rust qui ne gère pas les classes me parait limite, pour une programmation orientée objet la gestion de classes serait à mon sens bien plus importante que la gestion optimale de la mémoire dont on ne manquera pas, alors certes on trouvera des solutions avec des struct et des impl et des trait, mais quelle galère.... ) des que tu es dispo je te montrerai ce que j'avais fait en vb.
J'avais déclaré des classes avec des properties qui permettaient de bien "jouer" avec tous les éléments. (et même d'avoir des displayName)
exemple pour une date
Public Property Champ1 As String (Date mise au format « AAAAMMJJ0000)
Public Property Date_de_début_droits_AMO As Nullable(Of Date)
le set de l'un fixe la valeur de l'autre
(et c'est là que Rust qui ne gère pas les classes me parait limite, pour une programmation orientée objet la gestion de classes serait à mon sens bien plus importante que la gestion optimale de la mémoire dont on ne manquera pas, alors certes on trouvera des solutions avec des struct et des impl et des trait, mais quelle galère.... )
florian_briand
commented
Pas de soucis pour faire ce genre de chose en Rust, car on peut faire des choses de type Programmation objet Dans la doc & formation Rust c'est les concepts de Structure, de Templates et de Traits On peut se faire une session de pair programming pour implémenter ça :) Pas de soucis pour faire ce genre de chose en Rust, car on peut faire des choses de type Programmation objet
Dans la doc & formation Rust c'est les concepts de Structure, de Templates et de Traits
On peut se faire une session de pair programming pour implémenter ça :)
julien.misiak
commented
j'aurais bien besoin d'une session formation sur l'environnement de dev qui est bien plus compliqué que ce que j'ai l'habitude de mettre en place. Pour les concepts de Structure, de Templates et de Traits, je crois que je devrais m'en sortir quand on se sera mis d'accord sur la méthode. On pourrait commencer ensemble pour que je sois sûr que je vais dans la bonne direction et je voudrais bien voire avec toi si tu valides les concepts que j'avais mis en place dans ma programmation .Net Donc pour se faire, on pourrait se faire du pair programming des que tu es dispo j'aurais bien besoin d'une session formation sur l'environnement de dev qui est bien plus compliqué que ce que j'ai l'habitude de mettre en place.
par exemple là, je ne sais pas tester wip-debug-libc...
Pour les concepts de Structure, de Templates et de Traits, je crois que je devrais m'en sortir quand on se sera mis d'accord sur la méthode. On pourrait commencer ensemble pour que je sois sûr que je vais dans la bonne direction et je voudrais bien voire avec toi si tu valides les concepts que j'avais mis en place dans ma programmation .Net
Donc pour se faire, on pourrait se faire du pair programming des que tu es dispo
(mais si besoin je pourrais aussi me déplacer d'ici dix à quinze jours)
florian_briand
commented
Ça roule ; par contre, possible que j'ai pas trop de temps avant la semaine prochaine
Ça roule ; par contre, possible que j'ai pas trop de temps avant la semaine prochaine
- [ ] Faire une session de pair programming sur la structuration des données CPS
|
|||||||
|
},
|
||||||
|
2 => match num_champ {
|
||||||
|
1 => {
|
||||||
|
// Ajoutez votre logique pour Groupe2 ici
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
// Ajoutez votre logique pour Groupe2 ici
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
// Ajoutez votre logique pour Groupe2 ici
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current_pos_general += longueur_champs + nbre_octets_longueur;
|
||||||
|
current_pos_groupe += longueur_champs + nbre_octets_longueur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
35
clego/src/INSi.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// use std::ffi::CString;
|
||||||
florian_briand
commented
- [ ] Ne pas inclure ce fichier dans la PR
|
|||||||
|
// use std::ptr::null_mut;
|
||||||
|
// use winapi::um::libloaderapi::{LoadLibraryA, GetProcAddress, FreeLibrary};
|
||||||
|
// use winapi::shared::minwindef::HMODULE;
|
||||||
|
// // use winapi::shared::winerror::ERROR_SUCCESS;
|
||||||
|
// // use winapi::um::errhandlingapi::GetLastError;
|
||||||
|
// use winapi::um::winnt::LPCSTR;
|
||||||
|
// use std::os::raw::c_void;
|
||||||
|
|
||||||
|
// pub fn test() {
|
||||||
|
// unsafe {
|
||||||
|
// let dll_path = CString::new("F:/PAPILLON/Sources/CLEGO/CLEGO/bin/Debug/CLEGO.dll").expect("Échec de la création de CString");
|
||||||
|
// let dll_handle: HMODULE = LoadLibraryA(dll_path.as_ptr());
|
||||||
|
|
||||||
|
// if dll_handle.is_null() {
|
||||||
|
// //let error_code = GetLastError();
|
||||||
|
// println!("Erreur lors du chargement de la DLL.");// Code d'erreur : {}", error_code);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let class_name = CString::new("PS_Class").expect("Échec de la création de CString");
|
||||||
|
// let class_ptr: *mut c_void = GetProcAddress(dll_handle, class_name.as_ptr()) as *mut c_void;
|
||||||
|
|
||||||
|
// if class_ptr.is_null() {
|
||||||
|
// // let error_code = GetLastError();
|
||||||
|
// println!("Classe non trouvée.");// Code d'erreur : {}", error_code);
|
||||||
|
// FreeLibrary(dll_handle);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Convertissez class_ptr en une instance de classe Rust et appelez ses méthodes ici
|
||||||
|
|
||||||
|
// FreeLibrary(dll_handle);
|
||||||
|
// }
|
||||||
|
// }
|
@ -36,8 +36,8 @@ result
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
//SSV_LireCartePS
|
//SSV_LireCartePS
|
||||||
pub fn ssv_lirecarteps(dll_handle:*mut winapi::shared::minwindef::HINSTANCE__ , NomRessourcePS :String , NomRessourceLecteur :String , CodePorteurPS :String,
|
pub fn ssv_lirecarteps(dll_handle:*mut winapi::shared::minwindef::HINSTANCE__ , NomRessourcePS :&str , NomRessourceLecteur :&str , CodePorteurPS :&str,
|
||||||
mut ZDonneesSortie: *mut c_void , mut TTailleDonneesSortie: usize)->i32{
|
ZDonneesSortie: &mut *mut c_void , TTailleDonneesSortie: &mut usize)->i32{// mut ZDonneesSortie: *mut c_void , mut TTailleDonneesSortie: usize)->i32{
|
||||||
// Résolution d'une fonction exportée ("SSV_LireCartePS")
|
// Résolution d'une fonction exportée ("SSV_LireCartePS")
|
||||||
let symbol_name = CString::new("SSV_LireCartePS").expect("Nom de symbole invalide");
|
let symbol_name = CString::new("SSV_LireCartePS").expect("Nom de symbole invalide");
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -51,13 +51,18 @@ pub fn ssv_lirecarteps(dll_handle:*mut winapi::shared::minwindef::HINSTANCE__ ,
|
|||||||
let my_function: MyFunctionType = std::mem::transmute(function_ptr);
|
let my_function: MyFunctionType = std::mem::transmute(function_ptr);
|
||||||
|
|
||||||
// appel de la fonction
|
// appel de la fonction
|
||||||
ZDonneesSortie= std::ptr::null_mut();
|
//*ZDonneesSortie= std::ptr::null_mut();//ZDonneesSortie= std::ptr::null_mut();
|
||||||
TTailleDonneesSortie=0;
|
*TTailleDonneesSortie=0;
|
||||||
|
|
||||||
|
println!("ZDonneesSortie: {:?}", ZDonneesSortie);
|
||||||
|
|
||||||
let result = my_function(CString::new(NomRessourcePS).unwrap().as_ptr(),
|
let result = my_function(CString::new(NomRessourcePS).unwrap().as_ptr(),
|
||||||
CString::new(NomRessourceLecteur).unwrap().as_ptr(),
|
CString::new(NomRessourceLecteur).unwrap().as_ptr(),
|
||||||
CString::new(CodePorteurPS).unwrap().as_ptr(),
|
CString::new(CodePorteurPS).unwrap().as_ptr(),
|
||||||
&mut ZDonneesSortie,
|
ZDonneesSortie, TTailleDonneesSortie);
|
||||||
&mut TTailleDonneesSortie);
|
// &mut TTailleDonneesSortie);
|
||||||
|
|
||||||
|
println!("ZDonneesSortie: {:?}", ZDonneesSortie);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,13 +1,27 @@
|
|||||||
mod SV_DLL_Win;
|
mod SV_DLL_Win;
|
||||||
|
mod INSi;
|
||||||
|
mod CPS;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// let my_handle:*mut winapi::shared::minwindef::HINSTANCE__ ;
|
|
||||||
let my_handle = SV_DLL_Win::load_library("C:/Program Files/santesocial/fsv/1.40.14/lib/ssvw64.dll");
|
// INSi::test;
|
||||||
|
|
||||||
|
let my_handle = SV_DLL_Win::load_library("C:/Program Files/santesocial/fsv/1.40.14/lib/ssvw64.dll");
|
||||||
if my_handle.is_null() {
|
if my_handle.is_null() {
|
||||||
panic!("Échec du chargement de la DLL");
|
panic!("Échec du chargement de la DLL");
|
||||||
}
|
}
|
||||||
|
|
||||||
let result_ssv_initlib2=SV_DLL_Win::ssv_initlib2(my_handle,"C:/CLEGO_Files/SanteSociale/sesam.ini");
|
let result_ssv_initlib2=SV_DLL_Win::ssv_initlib2(my_handle,"C:/CLEGO_Files/SanteSociale/sesam.ini");
|
||||||
println!("Résultat SSV_InitLIB2 : {}", result_ssv_initlib2);
|
println!("Résultat SSV_InitLIB2 : {}", result_ssv_initlib2);
|
||||||
|
|
||||||
|
let mut ZDonneesSortie: *mut std::ffi::c_void= std::ptr::null_mut();
|
||||||
|
let mut TTailleDonneesSortie: usize=55;
|
||||||
|
|
||||||
|
let result_ssv_lirecps = SV_DLL_Win::ssv_lirecarteps(my_handle, "HID Global OMNIKEY 3x21 Smart Card Reader 0","", "1234",
|
||||||
|
&mut ZDonneesSortie, &mut TTailleDonneesSortie);
|
||||||
|
println!("Résultat SSV_LireCartePS : {}", result_ssv_lirecps);
|
||||||
|
println!("Taille sortie SSV_LireCartePS : {}", TTailleDonneesSortie);
|
||||||
|
println!("ZDonneesSortie: {:?}", ZDonneesSortie);
|
||||||
|
|
||||||
|
CPS::decode_zone_memoire(ZDonneesSortie,TTailleDonneesSortie)
|
||||||
florian_briand
commented
Est-ce que tu pourrais fournir, dans un fichier d'exemple, un exemple de ZDonneesSortie et TTailleDonneesSortie ? Comme ça on pourrait travailler sur le code, même sans avoir le lecteur de carte Est-ce que tu pourrais fournir, dans un fichier d'exemple, un exemple de ZDonneesSortie et TTailleDonneesSortie ? Comme ça on pourrait travailler sur le code, même sans avoir le lecteur de carte
julien.misiak
commented
Est-ce que tu peux faire avec ça? Taille sortie SSV_LireCartePS : 140 Est-ce que tu peux faire avec ça?
les valeurs sont en decimale
Taille sortie SSV_LireCartePS : 140
ZDonneesSortie: 0x1e75ad4cc40
Octet: 0
Octet: 1
Octet: 51
Octet: 1
Octet: 48
Octet: 1
Octet: 56
Octet: 11
Octet: 57
Octet: 57
Octet: 55
Octet: 48
Octet: 48
Octet: 53
Octet: 50
Octet: 52
Octet: 49
Octet: 57
Octet: 52
Octet: 1
Octet: 52
Octet: 2
Octet: 50
Octet: 50
Octet: 17
Octet: 80
Octet: 72
Octet: 65
Octet: 82
Octet: 77
Octet: 65
Octet: 67
Octet: 73
Octet: 69
Octet: 78
Octet: 48
Octet: 48
Octet: 53
Octet: 50
Octet: 52
Octet: 49
Octet: 57
Octet: 9
Octet: 70
Octet: 82
Octet: 65
Octet: 78
Octet: 67
Octet: 79
Octet: 73
Octet: 83
Octet: 69
Octet: 1
Octet: 84
Octet: 0
Octet: 2
Octet: 83
Octet: 1
Octet: 1
Octet: 1
Octet: 48
Octet: 1
Octet: 49
Octet: 2
Octet: 56
Octet: 54
Octet: 1
Octet: 49
Octet: 9
Octet: 48
Octet: 66
Octet: 48
Octet: 50
Octet: 50
Octet: 49
Octet: 57
Octet: 53
Octet: 56
Octet: 1
Octet: 56
Octet: 24
Octet: 80
Octet: 72
Octet: 65
Octet: 82
Octet: 77
Octet: 65
Octet: 67
Octet: 73
Octet: 69
Octet: 32
Octet: 68
Octet: 85
Octet: 32
Octet: 67
Octet: 69
Octet: 78
Octet: 84
Octet: 82
Octet: 69
Octet: 50
Octet: 50
Octet: 49
Octet: 57
Octet: 53
Octet: 8
Octet: 48
Octet: 48
Octet: 50
Octet: 48
Octet: 50
Octet: 52
Octet: 49
Octet: 57
Octet: 1
Octet: 56
Octet: 0
Octet: 1
Octet: 48
Octet: 1
Octet: 49
Octet: 2
Octet: 53
Octet: 48
Octet: 2
Octet: 49
Octet: 48
Octet: 2
Octet: 48
Octet: 48
Octet: 1
Octet: 48
Octet: 1
Octet: 48
Octet: 1
Octet: 48
Octet: 1
Octet: 49
Octet: 1
Octet: 49
florian_briand
commented
Oui, ça va le faire :)
Oui, ça va le faire :)
Je pousserais un bout de code intégrant ça
- [ ] Intégrer un mock du vecteur d'octets, pour le debug
|
|||||||
}
|
}
|
Je te conseille de sortir tous les bouts de codes "un peu compliqué", comme cette ligne par exemple, dans des fonctions, pour gagner en lisibilité :
Par exemple :
ça m'est égal, il me parait un peu too much de faire des fonctions pour remplacer une ligne de code
L'enjeu, c'est d'avoir une bonne lisibilité du code, à long terme, pour l'ensemble des dev.
Donc ça peut s'obtenir autrement que par le découpage ; à minima par des commentaires
Mais ici, je crois qu'on gagnerait à découper certaines fonctions, car on pourrait leur mettre des tests unitaires et car on aura sans doute besoin y nouveau de décalage de bits?
oui je crois des commentaires pourrait suffire dans ce cas,
C'est une traduction du code VB.Net bien aidé par l'IA, d'où l'absence de commentaire.
Je ferai le nécessaire pour rendre le code lisible. J'ai plutôt pour habitude de copier coller des parties de code lorsque c'est juste quelques fois,
Pour info, lorsqu'on aura programmer les quelques décodage de zone mémoire nécessaires, je garanti qu'on n'y reviendra pas.