Accueil > > > REMPLACER UNE FONCTION D'UNE DLL PAR N'IMPORTE QUELLE AUTRE!
REMPLACER UNE FONCTION D'UNE DLL PAR N'IMPORTE QUELLE AUTRE!
Information sur la source
Description
Ce code vous permettra de redéfinir le code d'une fonction importée statiquement par une DLL dans votre programme par une fonction quelconque définie dans votre programme. Il y a très peu à faire pour modifier le code afin qu'il fasse la même chose dans un processus extérieur. La fonction ReplaceAPI de l'unité APIRedirect.pas fait tout le travail:
-Détermination de l'adresse de base où est chargé l'exécutable.
-Exploration de la table des symboles importés jusqu'à trouver la fonction initiale à remplacer
-Recopiage de code machine à partir d'un petit morceau d'assembleur "inline" encadré par 2 nombres magiques pour retrouver le code machine correspondant
-Ce morceau de code "Launcher" est ensuite modifié pour y mettre l'adresse de la nouvelle fonction désirée
-Ajout d'une section exécutable à l'exécutable contenant le code du launcher de la nouvelle fonction
-Et ça marche!
Attention toutefois à respecter SCRUPULEUSEMENT le nombre et le format des paramètres de la nouvelle fonction à remplacer. Et ne pas oublier les conventions d'appels (stdcall, etc...) sinon ça va tout faire planter. Par exemple, si vous jugez que la fonction MessageBox de Windows ne vous convient pas, vous pouvez utiliser:
function MyMessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;
begin
<-Code personnel pour remplacer la fonction originale de Microsoft
end;
ReplaceAPI(kernel32,'MessageBox A',@MyMessageBox);
Et le tour est joué!
Je fourni un petit programme d'exemple pour montrer l'utilité d'une telle fonction: il se charge de remplacer l'API GetSysColor de Microsoft par une autre fonction qui permet de changer les couleurs systèmes. Tous les composants VCL non natifs (c'est à dire qui ne sont pas entièrement peints par Windows) sont affectés. Et pas besoin de changer leur couleur!
J'admet que le résultat est visuellement assez pauvre, mais le principe est là.
Source
- unit APIRedirect;
-
- interface
-
- uses
- SysUtils,Windows,ImageHlp,Dialogs;
-
- function GetImageBase(
- Process:THandle; // Handle to a valid process object. Current thread must have PROCESS_VM_READ | PROCESS_VM_OPERATION access to it.
-
- Thread:THandle // Handle to a valid thread object. Current thread must have THREAD_GET_CONTEXT access to it.
-
- ):Pointer; // Return the image base of the process.
-
- function ReplaceAPI(
- DllName:string; // Name of the DLL containing the procedure or function to replace
-
- ProcName:string; // Name of the procedure or function to replace
-
- NewProc:Pointer; // Pointer to the new desired procedure. The declaration of this procedure *MUST* be *EXACTLY* the same as the original API.
-
- Process:THandle=0; // Handle to a valid process object (or zero for the current process). The caller must have
- // PROCESS_SUSPEND_RESUME | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION
- // access to it.
-
- Thread:THandle=0 // Handle to a valid thread object (or zero for the current thread). The caller must have
- // THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION
- // access to it.
-
- ):Boolean;overload; // Return True if the API was successfully patched, false otherwise (for instance, if the process doesnt use the specified
- // name in his import directory, or if the API was not found in the specified DLL).
-
- type
- PPEB=^TPEB;
- TPEB=packed record
- UselessData:array[0..1] of Cardinal; // This is of course not the real definition, but only the ImageBaseAddress field is of interest in our case
- ImageBaseAddress:POINTER;
- end;
-
- PTEB=^TTEB;
- TTEB=packed record
- UselessData:array[0..11] of Cardinal; // This is of course not the real definition, but only the PEB field is of interest in our case
- PEB:PPEB;
- end;
-
- IMAGE_IMPORT_BY_NAME=packed record
- Hint:Word;
- Name:CHAR;
- end;
- TImageImportByName=IMAGE_IMPORT_BY_NAME;
- PImageImportByName=^IMAGE_IMPORT_BY_NAME;
-
- IMAGE_THUNK_DATA=packed record
- ForwarderString: PBYTE;
- Func: PDWORD;
- Ordinal: DWORD;
- AddressOfData:PImageImportByName;
- end;
- TImageThunkData=IMAGE_THUNK_DATA;
- PImageThunkData=^IMAGE_THUNK_DATA;
-
- TIIDMisc=packed record
- case Integer of
- 0:(Characteristics:DWORD); // 0 for terminating null import descriptor
- 1:(OriginalFirstThunk:DWORD); // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
- end;
-
- IMAGE_IMPORT_DESCRIPTOR=packed record
- Misc:TIIDMisc;
- TimeDateStamp:DWORD;
- ForwarderChain:DWORD;
- Name:DWORD;
- FirstThunk:DWORD;
- end;
- TImageImportDescriptor=IMAGE_IMPORT_DESCRIPTOR;
- PImageImportDescriptor=^IMAGE_IMPORT_DESCRIPTOR;
-
- const
- LOADER_START_MAGIC=$FAFAFAFA; // Magic flags arbitrary defined. These flags will allow us to retrieve
- LOADER_END_MAGIC=$FEFEFEFE; // code offsets in asm code. Anyway, let us hope the generated machine code doed not
- LOADER_PROC_MAGIC=$ABABABAB; // contain them! (I havent checked, but the probability is highliy negligible)
-
- implementation
-
- procedure Launcher; // A launcher for the new procedures. We insert flags to extract only the required code, without whatever Delphi will add
- // for initialisation and finalisation of the call
- asm
- DD LOADER_START_MAGIC; // Flag to indicate start of code
- PUSH EBP // Store EBP to API caller
- CALL @START
- @START: POP EBP
- SUB EBP, OFFSET @START // Get base EBP
- MOV EAX, [EBP+@@PROC] // Calculate new proc offset
- POP EBP // Restore EBP to API caller
- JMP EAX // JMP to new procedure address (no need to CALL)
- @@PROC: DD LOADER_PROC_MAGIC; // Flag to indicate absolute address of new proc
- DD LOADER_END_MAGIC; // Flag to indicate end of code
- end;
-
- function DataPos(Start:Pointer;Data:Cardinal):Cardinal;
- begin
- Result:=Cardinal(Start);
- while PCardinal(Result)^<>Data do
- Inc(Result);
- end;
-
- procedure GetLauncherCode(var Code:Pointer;var Size:Cardinal;Proc:Pointer);
- var
- p:Cardinal;
- begin
- p:=DataPos(@Launcher,LOADER_START_MAGIC)+4; // Retrieve position of launching code inside Launcher
- Size:=DataPos(@Launcher,LOADER_END_MAGIC)-p; // Retrieve end of launching code
- GetMem(Code,Size);
- CopyMemory(Code,Pointer(p),Size); // Duplicate launching code
- p:=DataPos(Code,LOADER_PROC_MAGIC); // Replace the absolute procedure address (which contains LOADER_PROC_MAGIC)...
- PPointer(p)^:=PPointer(@Proc)^; // ...with the new one
- end;
-
- function GetImageBase(Process:THandle;Thread:THandle):Pointer; // This function uses undocumented APIs. One can find their descriptions there:
- var // http://undocumented.ntinternals.net/
- Context:TContext; // There are other (simplier) means to obtain the image base, but this one
- SelEntry:TLDTEntry; // can extract the image base of other running processes.
- FSBase:Cardinal;
- TEB:TTEB;
- PEB:TPEB;
- n:Cardinal;
- begin
- Context.ContextFlags:=CONTEXT_FULL or CONTEXT_DEBUG_REGISTERS;
- if not GetThreadContext(Thread,Context) then // See the above link for additional informations
- RaiseLastOSError;
- if not GetThreadSelectorEntry(Thread,Context.SegFs,SelEntry) then
- RaiseLastOSError;
- with SelEntry do
- FSBase:=(BaseHi shl 24) or (BaseMid shl 16) or SelEntry.BaseLow;
- if not VirtualProtectEx(Process,Ptr(FSBase),SizeOf(TEB),PAGE_READWRITE,@n) then
- RaiseLastOSError;
- if not ReadProcessMemory(Process,Ptr(FSBase),@TEB,SizeOf(TEB),n) then
- RaiseLastOSError;
- if not VirtualProtectEx(Process,TEB.Peb,SizeOf(PEB),PAGE_READWRITE,@n) then
- RaiseLastOSError;
- if not ReadProcessMemory(Process,TEB.Peb,@PEB,SizeOf(PEB),n) then
- RaiseLastOSError;
- Result:=TEB.Peb.ImageBaseAddress; //That's it, we now have the address at which the process is loaded
- end;
-
- function RedirectAPI(DllName:string;InitialVOffset,NewVOffset,ImageBase:Cardinal;ImageDosHeader:PImageDosHeader;ImageNTHeader:PImageNtHeaders):Boolean;
- var
- ImportDirectory:Cardinal;
- ImageImportDescriptor:PImageImportDescriptor;
- ImageThunkData:PImageThunkData;
- begin
- Result:=False;
- ImportDirectory:=ImageNTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
- if ImportDirectory=0 then // Well, I think we can find cases where there are no imported libraries...
- Exit;
- ImageImportDescriptor:=Ptr(ImageBase+ImportDirectory);
- while ImageImportDescriptor.Name<>0 do begin // Enumerate imported DLL's
- if ImageImportDescriptor.Misc.OriginalFirstThunk<>0 then
- ImageThunkData:=PImageThunkData(ImageBase+ImageImportDescriptor.Misc.OriginalFirstThunk)
- else
- ImageThunkData:=PImageThunkData(ImageBase+ImageImportDescriptor.FirstThunk);
- while ImageThunkData.AddressOfData<>nil do begin // Enumerate procs imported from the DLL
- if PCardinal(ImageThunkData)^=InitialVOffset then begin // Found the imported proc!
- PCardinal(ImageThunkData)^:=NewVOffset; // Replace it and leave before Bill Gates notices anything!
- Result:=True;
- // Exit; //Apparently, there can be more than one instance of the imported proc in the table. So let's continue just in case...
- end;
- Inc(ImageThunkData);
- end;
- Inc(ImageImportDescriptor);
- end;
- end;
-
- function ReplaceAPI(DllName:string;ProcName:string;NewProc:Pointer;Process,Thread:THandle):Boolean;
- var
- ImageBase,OldProc,RedirectMem,LauncherCode:Pointer;
- ImageDosHeader:TImageDosHeader;
- ImageNTHeader:TImageNtHeaders;
- n,LauncherSize:Cardinal;
- Module:HModule;
- begin
- if Process=0 then
- Process:=GetCurrentProcess;
- if Thread=0 then
- Thread:=GetCurrentThread
- else
- SuspendThread(Thread);
- try
- ImageBase:=GetImageBase(Process,Thread);
- if not ReadProcessMemory(Process,ImageBase,@ImageDosHeader,SizeOf(ImageDosHeader),n) then // The DOS header is located at offset 0...
- RaiseLastOSError;
- if not ReadProcessMemory(Process,Ptr(Integer(ImageBase)+ImageDosHeader._lfanew),@ImageNTHeader,SizeOf(ImageNTHeader),n) then
- RaiseLastOSError; // The NT is located at offset _lfanew...
- Module:=LoadLibrary(PChar(DllName));
- OldProc:=GetProcAddress(Module,PChar(ProcName)); // Get the real API address
- if not Assigned(OldProc) then
- Assert(False,'Wrong library or procedure name'); // TODO: use Result:=False;Exit;
- GetLauncherCode(LauncherCode,LauncherSize,NewProc);
- try
- RedirectMem:=VirtualAllocEx(Process,nil,LauncherSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE); // Let's add some new code to the module ;-)
- if not WriteProcessMemory(Process,RedirectMem,LauncherCode,LauncherSize,n) then // Write the launcher code
- RaiseLastOSError;
- Result:=RedirectAPI(DllName,Cardinal(OldProc),Cardinal(RedirectMem),Cardinal(ImageBase),@ImageDosHeader,@ImageNTHeader); // OK, here we go, let's modify the headers
- finally
- FreeMem(LauncherCode);
- end;
- finally
- ResumeThread(Thread);
- end;
- end;
-
- end.
unit APIRedirect;
interface
uses
SysUtils,Windows,ImageHlp,Dialogs;
function GetImageBase(
Process:THandle; // Handle to a valid process object. Current thread must have PROCESS_VM_READ | PROCESS_VM_OPERATION access to it.
Thread:THandle // Handle to a valid thread object. Current thread must have THREAD_GET_CONTEXT access to it.
):Pointer; // Return the image base of the process.
function ReplaceAPI(
DllName:string; // Name of the DLL containing the procedure or function to replace
ProcName:string; // Name of the procedure or function to replace
NewProc:Pointer; // Pointer to the new desired procedure. The declaration of this procedure *MUST* be *EXACTLY* the same as the original API.
Process:THandle=0; // Handle to a valid process object (or zero for the current process). The caller must have
// PROCESS_SUSPEND_RESUME | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION
// access to it.
Thread:THandle=0 // Handle to a valid thread object (or zero for the current thread). The caller must have
// THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION
// access to it.
):Boolean;overload; // Return True if the API was successfully patched, false otherwise (for instance, if the process doesnt use the specified
// name in his import directory, or if the API was not found in the specified DLL).
type
PPEB=^TPEB;
TPEB=packed record
UselessData:array[0..1] of Cardinal; // This is of course not the real definition, but only the ImageBaseAddress field is of interest in our case
ImageBaseAddress:POINTER;
end;
PTEB=^TTEB;
TTEB=packed record
UselessData:array[0..11] of Cardinal; // This is of course not the real definition, but only the PEB field is of interest in our case
PEB:PPEB;
end;
IMAGE_IMPORT_BY_NAME=packed record
Hint:Word;
Name:CHAR;
end;
TImageImportByName=IMAGE_IMPORT_BY_NAME;
PImageImportByName=^IMAGE_IMPORT_BY_NAME;
IMAGE_THUNK_DATA=packed record
ForwarderString: PBYTE;
Func: PDWORD;
Ordinal: DWORD;
AddressOfData:PImageImportByName;
end;
TImageThunkData=IMAGE_THUNK_DATA;
PImageThunkData=^IMAGE_THUNK_DATA;
TIIDMisc=packed record
case Integer of
0:(Characteristics:DWORD); // 0 for terminating null import descriptor
1:(OriginalFirstThunk:DWORD); // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
end;
IMAGE_IMPORT_DESCRIPTOR=packed record
Misc:TIIDMisc;
TimeDateStamp:DWORD;
ForwarderChain:DWORD;
Name:DWORD;
FirstThunk:DWORD;
end;
TImageImportDescriptor=IMAGE_IMPORT_DESCRIPTOR;
PImageImportDescriptor=^IMAGE_IMPORT_DESCRIPTOR;
const
LOADER_START_MAGIC=$FAFAFAFA; // Magic flags arbitrary defined. These flags will allow us to retrieve
LOADER_END_MAGIC=$FEFEFEFE; // code offsets in asm code. Anyway, let us hope the generated machine code doed not
LOADER_PROC_MAGIC=$ABABABAB; // contain them! (I havent checked, but the probability is highliy negligible)
implementation
procedure Launcher; // A launcher for the new procedures. We insert flags to extract only the required code, without whatever Delphi will add
// for initialisation and finalisation of the call
asm
DD LOADER_START_MAGIC; // Flag to indicate start of code
PUSH EBP // Store EBP to API caller
CALL @START
@START: POP EBP
SUB EBP, OFFSET @START // Get base EBP
MOV EAX, [EBP+@@PROC] // Calculate new proc offset
POP EBP // Restore EBP to API caller
JMP EAX // JMP to new procedure address (no need to CALL)
@@PROC: DD LOADER_PROC_MAGIC; // Flag to indicate absolute address of new proc
DD LOADER_END_MAGIC; // Flag to indicate end of code
end;
function DataPos(Start:Pointer;Data:Cardinal):Cardinal;
begin
Result:=Cardinal(Start);
while PCardinal(Result)^<>Data do
Inc(Result);
end;
procedure GetLauncherCode(var Code:Pointer;var Size:Cardinal;Proc:Pointer);
var
p:Cardinal;
begin
p:=DataPos(@Launcher,LOADER_START_MAGIC)+4; // Retrieve position of launching code inside Launcher
Size:=DataPos(@Launcher,LOADER_END_MAGIC)-p; // Retrieve end of launching code
GetMem(Code,Size);
CopyMemory(Code,Pointer(p),Size); // Duplicate launching code
p:=DataPos(Code,LOADER_PROC_MAGIC); // Replace the absolute procedure address (which contains LOADER_PROC_MAGIC)...
PPointer(p)^:=PPointer(@Proc)^; // ...with the new one
end;
function GetImageBase(Process:THandle;Thread:THandle):Pointer; // This function uses undocumented APIs. One can find their descriptions there:
var // http://undocumented.ntinternals.net/
Context:TContext; // There are other (simplier) means to obtain the image base, but this one
SelEntry:TLDTEntry; // can extract the image base of other running processes.
FSBase:Cardinal;
TEB:TTEB;
PEB:TPEB;
n:Cardinal;
begin
Context.ContextFlags:=CONTEXT_FULL or CONTEXT_DEBUG_REGISTERS;
if not GetThreadContext(Thread,Context) then // See the above link for additional informations
RaiseLastOSError;
if not GetThreadSelectorEntry(Thread,Context.SegFs,SelEntry) then
RaiseLastOSError;
with SelEntry do
FSBase:=(BaseHi shl 24) or (BaseMid shl 16) or SelEntry.BaseLow;
if not VirtualProtectEx(Process,Ptr(FSBase),SizeOf(TEB),PAGE_READWRITE,@n) then
RaiseLastOSError;
if not ReadProcessMemory(Process,Ptr(FSBase),@TEB,SizeOf(TEB),n) then
RaiseLastOSError;
if not VirtualProtectEx(Process,TEB.Peb,SizeOf(PEB),PAGE_READWRITE,@n) then
RaiseLastOSError;
if not ReadProcessMemory(Process,TEB.Peb,@PEB,SizeOf(PEB),n) then
RaiseLastOSError;
Result:=TEB.Peb.ImageBaseAddress; //That's it, we now have the address at which the process is loaded
end;
function RedirectAPI(DllName:string;InitialVOffset,NewVOffset,ImageBase:Cardinal;ImageDosHeader:PImageDosHeader;ImageNTHeader:PImageNtHeaders):Boolean;
var
ImportDirectory:Cardinal;
ImageImportDescriptor:PImageImportDescriptor;
ImageThunkData:PImageThunkData;
begin
Result:=False;
ImportDirectory:=ImageNTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
if ImportDirectory=0 then // Well, I think we can find cases where there are no imported libraries...
Exit;
ImageImportDescriptor:=Ptr(ImageBase+ImportDirectory);
while ImageImportDescriptor.Name<>0 do begin // Enumerate imported DLL's
if ImageImportDescriptor.Misc.OriginalFirstThunk<>0 then
ImageThunkData:=PImageThunkData(ImageBase+ImageImportDescriptor.Misc.OriginalFirstThunk)
else
ImageThunkData:=PImageThunkData(ImageBase+ImageImportDescriptor.FirstThunk);
while ImageThunkData.AddressOfData<>nil do begin // Enumerate procs imported from the DLL
if PCardinal(ImageThunkData)^=InitialVOffset then begin // Found the imported proc!
PCardinal(ImageThunkData)^:=NewVOffset; // Replace it and leave before Bill Gates notices anything!
Result:=True;
// Exit; //Apparently, there can be more than one instance of the imported proc in the table. So let's continue just in case...
end;
Inc(ImageThunkData);
end;
Inc(ImageImportDescriptor);
end;
end;
function ReplaceAPI(DllName:string;ProcName:string;NewProc:Pointer;Process,Thread:THandle):Boolean;
var
ImageBase,OldProc,RedirectMem,LauncherCode:Pointer;
ImageDosHeader:TImageDosHeader;
ImageNTHeader:TImageNtHeaders;
n,LauncherSize:Cardinal;
Module:HModule;
begin
if Process=0 then
Process:=GetCurrentProcess;
if Thread=0 then
Thread:=GetCurrentThread
else
SuspendThread(Thread);
try
ImageBase:=GetImageBase(Process,Thread);
if not ReadProcessMemory(Process,ImageBase,@ImageDosHeader,SizeOf(ImageDosHeader),n) then // The DOS header is located at offset 0...
RaiseLastOSError;
if not ReadProcessMemory(Process,Ptr(Integer(ImageBase)+ImageDosHeader._lfanew),@ImageNTHeader,SizeOf(ImageNTHeader),n) then
RaiseLastOSError; // The NT is located at offset _lfanew...
Module:=LoadLibrary(PChar(DllName));
OldProc:=GetProcAddress(Module,PChar(ProcName)); // Get the real API address
if not Assigned(OldProc) then
Assert(False,'Wrong library or procedure name'); // TODO: use Result:=False;Exit;
GetLauncherCode(LauncherCode,LauncherSize,NewProc);
try
RedirectMem:=VirtualAllocEx(Process,nil,LauncherSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE); // Let's add some new code to the module ;-)
if not WriteProcessMemory(Process,RedirectMem,LauncherCode,LauncherSize,n) then // Write the launcher code
RaiseLastOSError;
Result:=RedirectAPI(DllName,Cardinal(OldProc),Cardinal(RedirectMem),Cardinal(ImageBase),@ImageDosHeader,@ImageNTHeader); // OK, here we go, let's modify the headers
finally
FreeMem(LauncherCode);
end;
finally
ResumeThread(Thread);
end;
end;
end.
Conclusion
Le code est de moi, je me suis un peu inspiré de cet article, même si ma méthode est un peu différente:
http://www.codeproject.com/useritems/ inject2it.asp
Je préfère aussi prévenir tout de suite: CE N'EST PAS UN VIRUS donc pas la peine que les admins le désactivent. De toute façon j'ai changé le code pour qu'on ne puisse pas injecter du code dans un autre processus.
Le code est de niveau expert, son utilisation de niveau débutant, donc en moyenne initié...
Sources du même auteur
Sources de la même categorie
Commentaires et avis
Discussions en rapport avec ce code source dans le forum
Hook dll : comment ca marche ? [ par Millenius ]
Bonjour, je voudrais hooker un dll.Le clavier et la souris, ca je sais faire.Ce que je voudrais, c pouvoir connaitre les flux de données entrant et so
Hook sans dll, c'est possible , mais comment ? [ par jace1975 ]
salut à tous je travaille actuellement sur une application, pour me permettre notamment de killer immédiatement le processus en c
A l'aide : utilisation d'une dll delphi par un programme visual visual C++ [ par neo_delphi ]
Dans ma DLL sous delphi, j'ai 2 fonctions definies de la facon suivante :function fct1(nb:word; var Tab1:array of word):word;stdcall;function fct2(nb:
API Windows [ par michelroc ]
Bonjour,J'ai ecris ce code et la reponse est toujours négative ?? Y a t-il une erreur dans ce code.Windows XP fam// Savoir si l'écran de vei
Espionner une dll pour récupérer un flot de données [ par gorets ]
J'ai un programme qui utilise une fonction placée dans une dll. cette dll redirige par une fonction un flux de donnée vers le port parall
Lien DLL dans un répertoire spécifique [ par dimdidi ]
Bonjour,J'utilise delphi 7 sous windowsXP.J'ai plusieurs applications developpées en delphi qui utilise des DLLs spécifiquesJe voudrais
erreur dll de fonction [ par saravana ]
bonjour a tous j'essaye d'appeler une fonction avec une dll, mais j'ai une erreur estce que quelqun peut me dire si il ya des erreurs dans le source:l
[Dll] Inclure des images dans une .Dll et les charger ensuite. [ par JulioDelphi ]
Bonjoir ! A mon tour d'avoir un problème sans solution : J'ai une form1 avec un composant TImage posé. (super !) J'ai 20mo d'images à charger dedans.
Utiliser l'API BOOL GetSystemPowerStatus pour avoir des infos sur la batterie [ par Yil2201 ]
Salut à tous! Voila, j'aimerais créer ma propore appli, capable de donner des infos sur la batterie, moins rudimentaire que la fenetre de la
( HELP ) Service de - de 300Ko en utilisant les API [ par Rudy3212 ]
Best PigBonjour voila je sais qu'il est possible de faire des application de quelque Ko enfin moins de 300Ko en utilisant les api, mais peut on faire
|
Derniers Blogs
[HS] CHROME 6 + MOI = COUP DE GUEULE ![HS] CHROME 6 + MOI = COUP DE GUEULE ! par JeremyJeanson
Attention, le poste qui suit n'est pas la complainte d'une personne : Qui n'aime pas Chrome. D'un anti Google. D'un développeur qui a un poil énorme dans la main. Ceux qui me fréquentent savent que je change de navigateur favori tous les 2 ou 3 mois afin ...
Cliquez pour lire la suite de l'article par JeremyJeanson [WP7] UTILISER UN WRAPPANEL DANS UNE APPLICATION WINDOWS PHONE 7[WP7] UTILISER UN WRAPPANEL DANS UNE APPLICATION WINDOWS PHONE 7 par Audrey
Lors de la réalisation de ma 2ème application Windows Phone 7, j'ai souhaité utiliser un WrapPanel pour afficher plusieurs photos. Mais le contrôle WrapPanel ne fait pas parti de la liste des contrôles inclus dans le SDK de la version Beta des outils pour...
Cliquez pour lire la suite de l'article par Audrey [WP7] BESOIN D'AVOIR DES DONNéES EN CACHE[WP7] BESOIN D'AVOIR DES DONNéES EN CACHE par Nicolas
Les développeurs ASP.NET ont l'habitude de mettre des données en cache pour éviter de requêter a chaque fois la base de données. Et il est toujours utilie de penser que vos utilisateurs mobiles n'ont pas troujours une super connexion 3G/WIFI et un for...
Cliquez pour lire la suite de l'article par Nicolas [TFS] COMMENT FORCER LA SAISIE D'UN AREA OU ITERATION[TFS] COMMENT FORCER LA SAISIE D'UN AREA OU ITERATION par cyril
Lorsque l'on créé un Work Item dans TFS, il est possible de le classer dans un "area" et dans une "iteration". Dans la plupart des types de projet, un "area" correspond à une catégorie, une "iteration" à un numéro de version. Il est possible de cré...
Cliquez pour lire la suite de l'article par cyril SQL : FONCTIONS D'AGRéGATION MIN/MAX ET VALEURS NULLSQL : FONCTIONS D'AGRéGATION MIN/MAX ET VALEURS NULL par coq
Les fonctions d'agrégation comme MIN et MAX ignorent les valeurs NULL présentes dans le jeu de données sur lequel porte leur calcul, d'où le fameux message d'avertissement : Warning: Null value is eliminated by an aggregate or other SET operation...
Cliquez pour lire la suite de l'article par coq
Logiciels
Bureau de Gestion - ERP Devis Facturation (2.02)BUREAU DE GESTION - ERP DEVIS FACTURATION (2.02)
- Version gratuite du 10/06/2010
Le Bureau de Gestion est un logiciel dédié à la gestion de l'en...
Cliquez pour télécharger Bureau de Gestion - ERP Devis Facturation sDEVIS-FACTURES vlPRO (3.8.0)SDEVIS-FACTURES VLPRO (3.8.0)sDEVIS-FACTURES vlPRO a été mis au point pour permettre besoins des particuliers, créateurs, entr... Cliquez pour télécharger sDEVIS-FACTURES vlPRO LettresFaciles (5.6.0)LETTRESFACILES (5.6.0)LettresFaciles est un logiciel facilitant la création et la rédaction de lettres types.
Son inte... Cliquez pour télécharger LettresFaciles MyPlanning 2010 (5.6.0)MYPLANNING 2010 (5.6.0)MyPlanning 2010 permet de créer des plannings sous la représentation de diagrammes. Plannings pré... Cliquez pour télécharger MyPlanning 2010 Emicsoft Mac DVD en iPad Convertisseur (3.1.16)EMICSOFT MAC DVD EN IPAD CONVERTISSEUR (3.1.16)Emicsoft Mac DVD en iPad Convertisseur, logiciel professionnel de convertir les fichiers DVD en i... Cliquez pour télécharger Emicsoft Mac DVD en iPad Convertisseur
|