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
TECHDAYS PARIS 2010 : PLAN DE MIGRATION VERS SHAREPOINT 2010TECHDAYS PARIS 2010 : PLAN DE MIGRATION VERS SHAREPOINT 2010 par ROMELARD Fabrice
Animé par: Arnault Nouvel et Antoine Dongois Le processus à prendre : Apprendre (découvrir la plateforme) Préparer (documenter l'historique et choisir la méthode de MAJ) Test (Test de MAJ) Implémenter (Effectuer la MAJ) Valid...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice TECHDAYS PARIS 2010 : LA PLEINIèRE DU SECOND JOURTECHDAYS PARIS 2010 : LA PLEINIèRE DU SECOND JOUR par ROMELARD Fabrice
Après un retour sur l'histoire des TechDays de Paris et le fait que ce soit le plus gros event MS au monde (du fait de sa gratuité), le président de MS France (Eric Boustoullier) a fait une présentation de la vision Microsoft pour les années à venir...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice CRéATION D'UNE BASE DE DONNéE SOUS SQL AZURECRéATION D'UNE BASE DE DONNéE SOUS SQL AZURE par junarnoalg
Sans rentrer dans les détails, je me propose ici de faire un rapide tour de ce que propose SQL Azure.
SQL Azure est avant tout un service d'hébergement de base de données relationnelles construit sur SQL Server. Il permet aux entreprises d...
Cliquez pour lire la suite de l'article par junarnoalg TECHDAYS PARIS 2010 : LES SERVICES D'APPLICATIONS DANS SHAREPOINT 2010TECHDAYS PARIS 2010 : LES SERVICES D'APPLICATIONS DANS SHAREPOINT 2010 par ROMELARD Fabrice
Animé par: Xavier Moreels et Julien Bakmezdjian Ce sujet est lié au partage des applications comme services dans SharePoint 2010, ceci représente la possibilité de créer sa propre application qui sera utilisable comme ceux en standard : Search...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Logiciels
DB-MAIN (9.1.0)DB-MAIN (9.1.0)DB-MAIN is a data-modeling and data-architecture tool. It is designed to help developers and anal... Cliquez pour télécharger DB-MAIN Xilisoft DPG Convertisseur (5.1.37.0120)XILISOFT DPG CONVERTISSEUR (5.1.37.0120)Xilisoft DPG Convertisseur offre aux fans de Nintendo DS une bonne solution leur permettant de dé... Cliquez pour télécharger Xilisoft DPG Convertisseur GraphicsGale (2.01.01)GRAPHICSGALE (2.01.01)GraphicsGale est un logiciel de PixelArt avec de nombreuse fonctionnalités permettant de réalisé ... Cliquez pour télécharger GraphicsGale Architecte 3D (Platinum 2010)ARCHITECTE 3D (PLATINUM 2010)Architecte 3D Platinium vous permet de concevoir facilement les plans votre future maison, de l'é... Cliquez pour télécharger Architecte 3D TeamViewer 5 (TeamViewer 5)TEAMVIEWER 5 (TEAMVIEWER 5)Dépanner un ami,expliquer une manipulation devient un jeu d'enfant.
Prise en main d'un autre ord... Cliquez pour télécharger TeamViewer 5
|