الفريق العربي للهندسة العكسية

نسخة كاملة : Windows API - مقدمة
أنت حالياً تتصفح نسخة خفيفة من المنتدى . مشاهدة نسخة كاملة مع جميع الأشكال الجمالية .
(07-09-2025, 11:07 AM)SMP3 08-05-2011 كتب : [ -> ]
أتمنى أن أكون قد وفقت في الشرح .
أخوكم مهدي 



نظرا لأهمية دوال Api في حياة المبرمج, و تحت طلب أخونا الحبيب أبو ياسين , فسيكون ان شاء الله سلسلة تعليمية توضح و تشرح هذه الدوال .

مقدمة :

ماذا نعني ب Windows Api :
هي اختصار لهذه الجملة بالانجليزية :Windows Application Programming Interface
و تعني واجهة برمجة التطبيقات و التي تتعامل بالأساس مع مكتبات الربط الديناميكي أو DLL
(Dynamic Link libraries) وهذه المكتبات مخزنة جميعها في المسار التالي :
\WINDOWS\system32\



أشهر هذه المكتبات و الشائعة استخداما هي :
kernel32.dll :وهي المكتبة الأساسية للنظام ,بحيث انها قلب النظام لكونها تحتوي على جميع الدوال و الاجراءات الخاصة ب الذاكرة و ال Thread و..و..
gdi32.dll : و تحتوي على دوال التعامل مع الجرافيك و الرسومات .
user32.dll: تحتوي على كل ما يتعلق بالنوافذ و القوائم و مربعات النصوص و غيرها من الأمرور التي يحتاجها المستخدم خلال تشغيله لأي تطبيق .

و هناك مكتبات أخرى مثل advapi32,comctl32,shell32 و غيرها من المكتبات

أما بالمعنى الدقيق فهي تعني التغليف أي تغليف شيئ صعب من الداخل و جعله سهل من الخارج.
كيف ذلك ?
تخيل معي أنك برمجة برنامج للتعامل مع الرسوميات , أكيد فلقد كتبت برنامج ضخم و يحتوي على دوال و روتينات معقدة
لكن في نهاية المطاف أردت أن تنشر طريقة العمل حتى يستفيد الجميع , أكيد فأنت لن تضع كل هذه التعقيدات
بل ستقوم بتسهيل الأمر على الجميع مثل أن تكتب دوال جاهزة مثل
 
function DrawRectangle()
function DrawLine() 



الآن أصبح الأمر أسهل على المبرمج لرسم مستطيل فبمجرد أن يقوم بكتابة الدالة DrawRectangle فسيتسنى له رسم مستطيل , بدل أن يقوم بكتابة مئات الأكواد لعمل ذلك


لماذا دوال Api ?
أولا : لقد صممت هذه الدوال لتسهيل الأمور على المبرمج
ثانيا : هناك قصور في اللغة المستخدمة في البرمجة , هناك تعليمات لا يمكن أن تفعلها الا باستخدام دوال Api
ثالثا : هناك تعليمات يمكنك كتابتها بلغتك لكنها تأخذ جهدا و وقتا وغالبا ماتكون بطيئة من ناحية السرعة في التنفيذ لذلك من الأفضل استخدام دوال جاهزة لمثل هذه العمليات.

هل دوال API تخص لغة برمجة معينة؟

لا , فبامكانك استخدامها في أي لغة برمجة تدعمها مع مراعاة جانب ال Syntax الخاص باللغة المستخدمة .

مصطلحات يجب أن تعرفها :

دوال Api هي كغيرها من الدوال , لديها اسم و برامترات (Parameters )خاصة بها , و في بعض الأحيان تملك ما يسمى ب Return Value
HANDLE : و يعني المقبض , فكثير من دوال Api تستخدم Handle في تمثيل عناصرها و يختلف المقبض بحسب وظيفة الدالة فهناك مقبض من نوع HWND و الذي يمثل الوينداوز , ومقبض من نوع HBITMAP و الذي يمثل صورة و مقبض من نوع HBRUSH و الذي يمثل الفرشاة و مقبض من نوع X يمثل Y (و غيرها ..)
Parameters : و تعني الوسائط , قد تكون من نوع DWORD or RECT أو أن تكون من نوع Int أو WORD
أو LPCTSTR أو أن تكون STRUCTURES مثل PROCESS_INFORMATION
للدالة CreateProcess , وغير ذلك من المتغيرات ...

مثال على تعريف دالة ببرامترات عادية :
 
function GetWindowRect(hWnd: HWND; var lpRect: TRect): BOOL; stdcall;external user32 name 'GetWindowRect'; 



لاحظ أن البرامترات الممرة للدالة هي برامترات عادية و لا نحتاج الى تعريفها في بيئة الدلفي.

مثال على تعريف دالة ببرامترات من نوع STRUCTURES :
 
function CreateProcess(lpApplicationName: PChar; lpCommandLine: PChar;
  lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
  bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
  lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
  var lpProcessInformation: _PROCESS_INFORMATION): BOOL; stdcall;external kernel32 name 'CreateProcessA'; 



لاحظ أن البرامتر lpProcessInformation من نوع
PROCESS_INFORMATION_
لذلك سنحتاج الى تعريفه في بيئة الدلفي .(سنتكلم عن هذا الأمر في الفقرات القادمة)

ملاحظة : هناك بعض نسخ من دلفي تحتوي على بعض هذه الفئات STRUCTURES , لكن على الأرجح ليس جميعها .

Return Value : و هو الناتج الذي تعود به الدالة و يختلف من دالة الى أخرى على حسب الوظيفة .

لنفهم هذه الأمور جيدا, تابع هذا المثال :
تخيل معي هذه الدالة
 
 function Add(Number1,Number2:integer):string ;
 begin
   result:=IntToStr(Number1+Number2);
 end; 




واضح عملها أليس كذلك ?
اسم الدالة : Add
البرامتر: للدالة برامترين من نوع integer
وظيفة الدالة : الدالة تقوم بجمع رقمين ثم تقوم بارجاع الناتج على أساس أنه String
تماما مثل دوال Api فهي تستقبل بعض الوسائط (Parameters) ثم تقوم بمعاجة هذه الوسائط و في الأخير تقوم بارجاع الناتج على حسب الوظيفة .
الآن لنلقي نظرة على طريقة تعريف دوال Api في بيئة دلفي
نختار أبسط الدوال , الدالة MessageBox
 
function MessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall; external user32 name 'MessageBoxA'; 



لنشرح طريقة التعريف
أولا تكتب دوال Api كغيرها من الدوال في الجزء المخصص للدوال في محرر الدلفي
بداية التعريف نجد الكلمة المحجوزة function و تعني أنها دالة
ثم اسم الدالة MessageBox
ثم قوسين يحملان البرامتر الخاصة بهذه الدالة
البرامتر الأول اسمه hWnd من نوع مقبض للوينداوز HWND
البرامتر الثاني lpText و الثالث lpCaption من نوع PChar (سلسة نصية)

ملاحظة : الحرف P قبل النوع (PChar) يدل على أنه مؤشر .
البرامتر الأخير uType من نوع UINT
أما ناتج الدالة فهو من نوع Integer و يتضح هذا من خلال نهاية القوس
اذا تم استدعاء الدالة وقام المستخدم مثلا بالضغط على زر Ok فسنرجع الدالة بالقيمة IDOK=1
أما اذا ضغط المستخدم على زر Cancel فسترجع الدالة بالقيمة IDCANCEL=2
جرب هذا الكود في دلفي و ستفهم قصدي :
 
var MsgResult:integer;
begin
   MsgResult:=MessageBox(0,'Do you want to exit','Exit..',1)  ;
   if MsgResult=IDOK then
   Application.Terminate
   else if MsgResult= IDCANCEL then ShowMessage('Thank you');
end; 



لنكمل
الكلمة Stdcall تخبر المترجم بأن يعاملها على أنها Calling Convention
Calling Convention هي الطرق القياسية التي تجعل الإجراءات و الدوال في الوندوز تعاملها كما هي بالضبط .
الكلمة external و تستعمل لتحديد المكان الذي تتواجد به المكتبة
user32 وهي المكتبة التي تتواجد بها الدالة وهي قيمة ثابتة تساوي user32.dll

ملاحظة: هنالك بعض المكتبات الغير مصرح بها في الدلفي لذا انتبه حينما تقوم بتعريفها
نفس التعريف السابق بصبغة أخرى
 
function MessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall; external 'user32.dll' name 'MessageBoxA'; 


name و تعني اسم الدالة
MessageBoxA اسم الدالة بترميز Unicode and ANSI

التعريفات القياسية لمايكروسوفت :

في الحقيقة فان التعريف السابق للدالة MessageBox ليس بتعريف قياسي , فهذا التعريف خاص فقط بلغة الدلفي و تختلف التعريفات من لغة الى أخرى
فمثلا تعريف الدالة السابقة بالفيجوال بيسك :
 
Private Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long 




فلو لاحظت فان التعريف يختلف من لغة الى أخرى
أما التعريف القياسي للدالة MessageBox
 
int WINAPI MessageBox(
  __in_opt  HWND hWnd,
  __in_opt  LPCTSTR lpText,
  __in_opt  LPCTSTR lpCaption,
  __in      UINT uType
); 



لنشرح التعريف القياسي لهذه الدالة

int :وهي ناتج الدالة وهي من نوع int وتعني integer وهي كلمة محجوزة في عائلة السي و مشتقاتها
WINAPI : للدلالة على أنها دالة من دوال الوينداوز API
MessageBox : اسم الدالة
hWnd : وهو البرامتر الأول من الدالة وهو من نوع HWND
lpText : البرامتر الثاني للدالة وهو من نوع LPCTSTR مؤشر لسلسة نصية ويوافق String في لغة الفيجوال بيسك, ويحمل هذا البرامتر الرسالة المراد عرضها
lpCaption:البرامتر الثالث للدالة وهو من نوع LPCTSTR , ويحمل عنوان الرسالة
uType: البرامتر الأخير للدالة ويحمل شكل الرسالة من أزرار و أيقونات

__in_opt : و تعني optional input parameter أي أن هذا البرامتر يمكن أن يكون اختياري أي بامكانك أن تجعله NULL=0
__in : و تعني input parameter وتستعمل للدلالة على الادخال
__out : وتعني output parameter وتستعمل للدلالة على الاخراج

From C to Delphi :


ملاحظة: بيئة الدلفي لا تحتوي على جميع التعريفات الخاصة بالدوال لذا من الأفضل أن تتطلع دائما على تعريف الدالة في موقع مايكروسوفت MSDN
فهو بكل صراحة يحتوي على كل صغيرة و كبيرة بأي دالة تريدها من تعريف و برامترات و STRUCTURES و المكتبة التي تتواجد بها الدالة مع مثال بسيط لاستعمال الدالة
أنصحكم بالاطلاع على الموقع .
وكما قلنا سابقا فان جميع التعريفات للدوال على موقع MSDN تعرف على أساس التعريفات القياسة .اذا هل لابد أن تكون مبرمج C أو مبرمج ++C , حتى تتمكن من كتابة التعريف الخاص بدالة معينة على بيئة دلفي ؟ الجواب : لا, فهذا ليس بشرط

اليك عزيزي القارئ هذا الجدول الذي يلخص تعريفات لغة السي و ما يقابلها في دلفي



لكن ماذا عن ال STRUCTURES ?
تستطيع تحويل أي STRUCTURES الى بيئة الدلفي
الطريقة سهلة جدا
لنأخذ مثال حتى نستوعب الفكرة
 
 
typedef struct _PROCESS_INFORMATION {
  HANDLE hProcess;
  HANDLE hThread;
  DWORD  dwProcessId;
  DWORD  dwThreadId;
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION; 


 
ملاحظة :علامة * تعني أن المتغير LPPROCESS_INFORMATION عبارة عن مؤشر ل PROCESS_INFORMATION

* في لغة السي = ^ في لغة دلفي و تستعمل لجعل المتغير أو STRUCTURES على أنه مؤشر

و هذا مايقابله في دلفي :
 
type
  _PROCESS_INFORMATION = record
    hProcess: THandle;
    hThread: THandle;
    dwProcessId: DWORD;
    dwThreadId: DWORD;
  end;
    PProcessInformation = ^_PROCESS_INFORMATION; 



لاحظ أن :

LPPROCESS_INFORMATION=PProcessInformation

الآن صار بامكانك تحويل أي دالة تحت التعريفات القياسية الى لغة الباسكال (دلفي) .