ప్రోహోస్టర్ > బ్లాగ్ > పరిపాలన > Windows నేటివ్ అప్లికేషన్స్ మరియు Acronis Active Restore సర్వీస్
Windows నేటివ్ అప్లికేషన్స్ మరియు Acronis Active Restore సర్వీస్
ఈ రోజు మనం ఇన్నోపోలిస్ యూనివర్సిటీకి చెందిన కుర్రాళ్లతో కలిసి, విఫలమైన తర్వాత వీలైనంత త్వరగా వారి మెషీన్లో పని చేయడం ప్రారంభించడానికి వినియోగదారుని అనుమతించడానికి యాక్టివ్ రీస్టోర్ టెక్నాలజీని ఎలా అభివృద్ధి చేస్తున్నాము అనే కథనాన్ని కొనసాగిస్తాము. మేము స్థానిక విండోస్ అప్లికేషన్ల గురించి మాట్లాడుతాము, వాటి సృష్టి మరియు లాంచ్ లక్షణాలతో సహా. కట్ క్రింద మా ప్రాజెక్ట్ గురించి కొద్దిగా, అలాగే స్థానిక అప్లికేషన్లను ఎలా వ్రాయాలనే దానిపై ఆచరణాత్మక గైడ్.
మునుపటి పోస్ట్లలో ఇది ఏమిటో మేము ఇప్పటికే మాట్లాడాము క్రియాశీల పునరుద్ధరణ, మరియు ఇన్నోపోలిస్ నుండి విద్యార్థులు ఎలా అభివృద్ధి చెందుతారు సేవ. ఈ రోజు నేను స్థానిక అప్లికేషన్లపై దృష్టి పెట్టాలనుకుంటున్నాను, మా సక్రియ పునరుద్ధరణ సేవను "బరీ" చేయాలనుకుంటున్న స్థాయికి. ప్రతిదీ పని చేస్తే, మేము వీటిని చేయగలము:
సేవను చాలా ముందుగానే ప్రారంభించండి
చాలా ముందుగా బ్యాకప్ ఉన్న క్లౌడ్ని సంప్రదించండి
సిస్టమ్ ఏ మోడ్లో ఉందో అర్థం చేసుకోవడానికి చాలా ముందుగానే - సాధారణ బూట్ లేదా రికవరీ
ముందుగానే పునరుద్ధరించడానికి చాలా తక్కువ ఫైల్లు
మరింత వేగంగా ప్రారంభించడానికి వినియోగదారుని అనుమతించండి.
ఏమైనప్పటికీ స్థానిక యాప్ అంటే ఏమిటి?
ఈ ప్రశ్నకు సమాధానమివ్వడానికి, సిస్టమ్ చేసే కాల్ల క్రమాన్ని చూద్దాం, ఉదాహరణకు, అతని అప్లికేషన్లోని ప్రోగ్రామర్ ఫైల్ను రూపొందించడానికి ప్రయత్నిస్తే.
పావెల్ యోసిఫోవిచ్ - విండోస్ కెర్నల్ ప్రోగ్రామింగ్ (2019)
ప్రోగ్రామర్ ఫంక్షన్ను ఉపయోగిస్తాడు క్రియేట్ ఫైల్, ఇది fileapi.h హెడర్ ఫైల్లో ప్రకటించబడింది మరియు Kernel32.dllలో అమలు చేయబడుతుంది. అయినప్పటికీ, ఈ ఫంక్షన్ ఫైల్ను సృష్టించదు, ఇది ఇన్పుట్ ఆర్గ్యుమెంట్లను మాత్రమే తనిఖీ చేస్తుంది మరియు ఫంక్షన్కు కాల్ చేస్తుంది NtCreateFile (Nt ఉపసర్గ కేవలం ఫంక్షన్ స్థానికంగా ఉందని సూచిస్తుంది). ఈ ఫంక్షన్ winternl.h హెడర్ ఫైల్లో ప్రకటించబడింది మరియు ntdll.dllలో అమలు చేయబడుతుంది. ఇది అణు అంతరిక్షంలోకి దూకడానికి సిద్ధమవుతుంది, ఆ తర్వాత ఫైల్ను రూపొందించడానికి సిస్టమ్ కాల్ చేస్తుంది. ఈ సందర్భంలో, Kernel32 Ntdll కోసం ఒక రేపర్ మాత్రమే అని తేలింది. మైక్రోసాఫ్ట్ స్థానిక ప్రపంచం యొక్క విధులను మార్చగల సామర్థ్యాన్ని కలిగి ఉంది, కానీ ప్రామాణిక ఇంటర్ఫేస్లను తాకదు. మైక్రోసాఫ్ట్ నేరుగా స్థానిక ఫంక్షన్లకు కాల్ చేయమని సిఫారసు చేయదు మరియు వాటిలో చాలా వరకు డాక్యుమెంట్ చేయదు. మార్గం ద్వారా, నమోదుకాని విధులు కనుగొనవచ్చు ఇక్కడ.
స్థానిక అప్లికేషన్ల యొక్క ప్రధాన ప్రయోజనం ఏమిటంటే ntdll kernel32 కంటే చాలా ముందుగానే సిస్టమ్లోకి లోడ్ చేయబడుతుంది. ఇది లాజికల్, ఎందుకంటే kernel32 పని చేయడానికి ntdll అవసరం. ఫలితంగా, స్థానిక ఫంక్షన్లను ఉపయోగించే అప్లికేషన్లు చాలా ముందుగానే పని చేయడం ప్రారంభించవచ్చు.
అందువల్ల, విండోస్ నేటివ్ అప్లికేషన్స్ అనేది విండోస్ బూట్లో ప్రారంభమయ్యే ప్రోగ్రామ్లు. వారు ntdll నుండి ఫంక్షన్లను మాత్రమే ఉపయోగిస్తారు. అటువంటి అప్లికేషన్ యొక్క ఉదాహరణ: autochk ఎవరు నిర్వహిస్తారు chkdisk యుటిలిటీ ప్రధాన సేవలను ప్రారంభించే ముందు లోపాల కోసం డిస్క్ను తనిఖీ చేయడానికి. మా యాక్టివ్ పునరుద్ధరణ సరిగ్గా ఇదే స్థాయిలో ఉండాలి.
మనకు ఏమి కావాలి?
DDK (డ్రైవర్ డెవలప్మెంట్ కిట్), ఇప్పుడు దీనిని WDK 7 (Windows డ్రైవర్ కిట్) అని కూడా పిలుస్తారు.
వర్చువల్ మిషన్ (ఉదాహరణకు, Windows 7 x64)
అవసరం లేదు, కానీ డౌన్లోడ్ చేయగల హెడర్ ఫైల్లు సహాయపడవచ్చు ఇక్కడ
కోడ్లో ఏముంది?
కొంచెం ప్రాక్టీస్ చేద్దాం మరియు ఉదాహరణకు, ఒక చిన్న అప్లికేషన్ను వ్రాస్దాం:
స్క్రీన్పై సందేశాన్ని ప్రదర్శిస్తుంది
కొంత మెమరీని కేటాయిస్తుంది
కీబోర్డ్ ఇన్పుట్ కోసం వేచి ఉంది
ఉపయోగించిన మెమరీని ఖాళీ చేస్తుంది
స్థానిక అప్లికేషన్లలో, ఎంట్రీ పాయింట్ మెయిన్ లేదా విన్మైన్ కాదు, కానీ NtProcessStartup ఫంక్షన్, ఎందుకంటే మేము సిస్టమ్లో నేరుగా కొత్త ప్రక్రియలను ప్రారంభిస్తాము.
స్క్రీన్పై సందేశాన్ని ప్రదర్శించడం ద్వారా ప్రారంభిద్దాం. దీని కోసం మాకు స్థానిక ఫంక్షన్ ఉంది NtDisplayString, ఇది UNICODE_STRING నిర్మాణ వస్తువుకు పాయింటర్ను ఆర్గ్యుమెంట్గా తీసుకుంటుంది. దీన్ని ప్రారంభించడంలో RtlInitUnicodeString మాకు సహాయం చేస్తుంది. ఫలితంగా, స్క్రీన్పై వచనాన్ని ప్రదర్శించడానికి మనం ఈ చిన్న ఫంక్షన్ను వ్రాయవచ్చు:
//usage: WriteLn(L"Here is my textn");
void WriteLn(LPWSTR Message)
{
UNICODE_STRING string;
RtlInitUnicodeString(&string, Message);
NtDisplayString(&string);
}
ntdll నుండి మాత్రమే ఫంక్షన్లు మాకు అందుబాటులో ఉన్నాయి మరియు మెమరీలో ఇంకా ఇతర లైబ్రరీలు లేవు కాబట్టి, మెమరీని ఎలా కేటాయించాలనే విషయంలో మనకు ఖచ్చితంగా సమస్యలు ఉంటాయి. కొత్త ఆపరేటర్ ఇంకా ఉనికిలో లేదు (ఎందుకంటే ఇది C++ యొక్క చాలా ఉన్నత-స్థాయి ప్రపంచం నుండి వచ్చింది), మరియు malloc ఫంక్షన్ లేదు (దీనికి రన్టైమ్ C లైబ్రరీలు అవసరం). వాస్తవానికి, మీరు స్టాక్ను మాత్రమే ఉపయోగించవచ్చు. కానీ మనం మెమరీని డైనమిక్గా కేటాయించవలసి వస్తే, మనం దానిని కుప్ప (అంటే హీప్) మీద చేయాలి. కాబట్టి మనం మన కోసం ఒక కుప్పను సృష్టించుకుందాం మరియు మనకు అవసరమైనప్పుడు దాని నుండి జ్ఞాపకశక్తిని తీసుకుందాం.
ఈ పనికి ఫంక్షన్ అనుకూలంగా ఉంటుంది RtlCreateHeap. తరువాత, RtlAllocateHeap మరియు RtlFreeHeap ఉపయోగించి, మనకు అవసరమైనప్పుడు మేము మెమరీని ఆక్రమిస్తాము మరియు ఉచిత మెమరీని చేస్తాము.
PVOID memory = NULL;
PVOID buffer = NULL;
ULONG bufferSize = 42;
// create heap in order to allocate memory later
memory = RtlCreateHeap(
HEAP_GROWABLE,
NULL,
1000,
0, NULL, NULL
);
// allocate buffer of size bufferSize
buffer = RtlAllocateHeap(
memory,
HEAP_ZERO_MEMORY,
bufferSize
);
// free buffer (actually not needed because we destroy heap in next step)
RtlFreeHeap(memory, 0, buffer);
RtlDestroyHeap(memory);
మనకు కావలసిందల్లా ఉపయోగించడం NtReadFile తెరిచిన పరికరంలో, మరియు కీబోర్డ్ ఏదైనా ప్రెస్ మాకు తిరిగి ఇచ్చే వరకు వేచి ఉండండి. ESC కీని నొక్కితే, మేము పనిని కొనసాగిస్తాము. పరికరాన్ని తెరవడానికి, మేము NtCreateFile ఫంక్షన్కి కాల్ చేయాలి (మనం DeviceKeyboardClass0ని తెరవాలి). మేము కూడా పిలుస్తాము NtCreateEventవేచి ఉండే వస్తువును ప్రారంభించేందుకు. కీబోర్డ్ డేటాను సూచించే KEYBOARD_INPUT_DATA నిర్మాణాన్ని మేమే ప్రకటిస్తాము. ఇది మన పనిని సులభతరం చేస్తుంది.
స్థానిక అప్లికేషన్ ఫంక్షన్ కాల్తో ముగుస్తుంది NtTerminateProcessఎందుకంటే మనం మన స్వంత ప్రక్రియను చంపుకుంటున్నాము.
మా చిన్న అప్లికేషన్ కోసం మొత్తం కోడ్:
#include "ntifs.h" // WinDDK7600.16385.1incddk
#include "ntdef.h"
//------------------------------------
// Following function definitions can be found in native development kit
// but I am too lazy to include `em so I declare it here
//------------------------------------
NTSYSAPI
NTSTATUS
NTAPI
NtTerminateProcess(
IN HANDLE ProcessHandle OPTIONAL,
IN NTSTATUS ExitStatus
);
NTSYSAPI
NTSTATUS
NTAPI
NtDisplayString(
IN PUNICODE_STRING String
);
NTSTATUS
NtWaitForSingleObject(
IN HANDLE Handle,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout
);
NTSYSAPI
NTSTATUS
NTAPI
NtCreateEvent(
OUT PHANDLE EventHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN EVENT_TYPE EventType,
IN BOOLEAN InitialState
);
// https://docs.microsoft.com/en-us/windows/win32/api/ntddkbd/ns-ntddkbd-keyboard_input_data
typedef struct _KEYBOARD_INPUT_DATA {
USHORT UnitId;
USHORT MakeCode;
USHORT Flags;
USHORT Reserved;
ULONG ExtraInformation;
} KEYBOARD_INPUT_DATA, *PKEYBOARD_INPUT_DATA;
//----------------------------------------------------------
// Our code goes here
//----------------------------------------------------------
// usage: WriteLn(L"Hello Native World!n");
void WriteLn(LPWSTR Message)
{
UNICODE_STRING string;
RtlInitUnicodeString(&string, Message);
NtDisplayString(&string);
}
void NtProcessStartup(void* StartupArgument)
{
// it is important to declare all variables at the beginning
HANDLE hKeyBoard, hEvent;
UNICODE_STRING skull, keyboard;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK Iosb;
LARGE_INTEGER ByteOffset;
KEYBOARD_INPUT_DATA kbData;
PVOID memory = NULL;
PVOID buffer = NULL;
ULONG bufferSize = 42;
//use it if debugger connected to break
//DbgBreakPoint();
WriteLn(L"Hello Native World!n");
// inialize variables
RtlInitUnicodeString(&keyboard, L"DeviceKeyboardClass0");
InitializeObjectAttributes(&ObjectAttributes, &keyboard, OBJ_CASE_INSENSITIVE, NULL, NULL);
// open keyboard device
NtCreateFile(&hKeyBoard,
SYNCHRONIZE | GENERIC_READ | FILE_READ_ATTRIBUTES,
&ObjectAttributes,
&Iosb,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,FILE_DIRECTORY_FILE,
NULL, 0);
// create event to wait on
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
NtCreateEvent(&hEvent, EVENT_ALL_ACCESS, &ObjectAttributes, 1, 0);
WriteLn(L"Keyboard readyn");
// create heap in order to allocate memory later
memory = RtlCreateHeap(
HEAP_GROWABLE,
NULL,
1000,
0, NULL, NULL
);
WriteLn(L"Heap readyn");
// allocate buffer of size bufferSize
buffer = RtlAllocateHeap(
memory,
HEAP_ZERO_MEMORY,
bufferSize
);
WriteLn(L"Buffer allocatedn");
// free buffer (actually not needed because we destroy heap in next step)
RtlFreeHeap(memory, 0, buffer);
RtlDestroyHeap(memory);
WriteLn(L"Heap destroyedn");
WriteLn(L"Press ESC to continue...n");
while (TRUE)
{
NtReadFile(hKeyBoard, hEvent, NULL, NULL, &Iosb, &kbData, sizeof(KEYBOARD_INPUT_DATA), &ByteOffset, NULL);
NtWaitForSingleObject(hEvent, TRUE, NULL);
if (kbData.MakeCode == 0x01) // if ESC pressed
{
break;
}
}
NtTerminateProcess(NtCurrentProcess(), 0);
}
PS: డీబగ్గర్లో ఆపడానికి మన కోడ్లోని DbgBreakPoint() ఫంక్షన్ని సులభంగా ఉపయోగించవచ్చు. నిజమే, మీరు కెర్నల్ డీబగ్గింగ్ కోసం WinDbgని వర్చువల్ మెషీన్కి కనెక్ట్ చేయాలి. దీన్ని ఎలా చేయాలో సూచనలను కనుగొనవచ్చు ఇక్కడ లేదా కేవలం ఉపయోగించండి VirtualKD.
సంకలనం మరియు అసెంబ్లీ
స్థానిక అనువర్తనాన్ని రూపొందించడానికి సులభమైన మార్గం ఉపయోగించడం DDK (డ్రైవర్ డెవలప్మెంట్ కిట్). మాకు పురాతన ఏడవ వెర్షన్ అవసరం, ఎందుకంటే తరువాతి సంస్కరణలు కొద్దిగా భిన్నమైన విధానాన్ని కలిగి ఉంటాయి మరియు విజువల్ స్టూడియోతో కలిసి పని చేస్తాయి. మేము DDKని ఉపయోగిస్తే, మా ప్రాజెక్ట్కి మేక్ఫైల్ మరియు మూలాలు మాత్రమే అవసరం.
Makefile
!INCLUDE $(NTMAKEENV)makefile.def
వర్గాలు:
TARGETNAME = MyNative
TARGETTYPE = PROGRAM
UMTYPE = nt
BUFFER_OVERFLOW_CHECKS = 0
MINWIN_SDK_LIB_PATH = $(SDK_LIB_PATH)
SOURCES = source.c
INCLUDES = $(DDK_INC_PATH);
C:WinDDK7600.16385.1ndk;
TARGETLIBS = $(DDK_LIB_PATH)ntdll.lib
$(DDK_LIB_PATH)nt.lib
USE_NTDLL = 1
మీ Makefile సరిగ్గా అదే విధంగా ఉంటుంది, అయితే మూలాలను కొంచెం వివరంగా చూద్దాం. ఈ ఫైల్ మీ ప్రోగ్రామ్ యొక్క మూలాలను (.c ఫైల్లు), బిల్డ్ ఎంపికలు మరియు ఇతర పారామితులను నిర్దేశిస్తుంది.
TARGETNAME – ఎక్జిక్యూటబుల్ ఫైల్ పేరు చివరికి ఉత్పత్తి చేయబడాలి.
TARGETTYPE – ఎక్జిక్యూటబుల్ ఫైల్ రకం, అది డ్రైవర్ (.sys) కావచ్చు, అప్పుడు ఫీల్డ్ విలువ డ్రైవర్ అయి ఉండాలి, లైబ్రరీ (.lib) అయితే, విలువ లైబ్రరీ. మా విషయంలో, మనకు ఎక్జిక్యూటబుల్ ఫైల్ (.exe) అవసరం, కాబట్టి మేము విలువను ప్రోగ్రామ్కి సెట్ చేస్తాము.
UMTYPE – ఈ ఫీల్డ్ కోసం సాధ్యమయ్యే విలువలు: కన్సోల్ అప్లికేషన్ కోసం కన్సోల్, విండోస్ మోడ్లో పని చేయడానికి విండోస్. కానీ మనం స్థానిక అప్లికేషన్ని పొందడానికి ntని పేర్కొనాలి.
BUFFER_OVERFLOW_CHECKS – బఫర్ ఓవర్ఫ్లో కోసం స్టాక్ని తనిఖీ చేస్తోంది, దురదృష్టవశాత్తు మా విషయంలో కాదు, మేము దాన్ని ఆఫ్ చేస్తాము.
MINWIN_SDK_LIB_PATH – ఈ విలువ SDK_LIB_PATH వేరియబుల్ని సూచిస్తుంది, మీరు డిక్లేర్ చేయబడిన అటువంటి సిస్టమ్ వేరియబుల్ లేదని చింతించకండి, మేము DDK నుండి తనిఖీ చేసిన బిల్డ్ను అమలు చేసినప్పుడు, ఈ వేరియబుల్ ప్రకటించబడుతుంది మరియు అవసరమైన లైబ్రరీలను సూచిస్తుంది.
సోర్సెస్ - మీ ప్రోగ్రామ్ కోసం మూలాల జాబితా.
కలిపి - అసెంబ్లీకి అవసరమైన హెడర్ ఫైల్లు. ఇక్కడ వారు సాధారణంగా DDKతో వచ్చే ఫైల్లకు మార్గాన్ని సూచిస్తారు, కానీ మీరు అదనంగా ఏవైనా ఇతర వాటిని పేర్కొనవచ్చు.
TARGETLIBS - లింక్ చేయవలసిన లైబ్రరీల జాబితా.
USE_NTDLL అనేది స్పష్టమైన కారణాల కోసం తప్పనిసరిగా 1కి సెట్ చేయబడవలసిన ఫీల్డ్.
USER_C_FLAGS – అప్లికేషన్ కోడ్ని సిద్ధం చేసేటప్పుడు మీరు ప్రిప్రాసెసర్ ఆదేశాలలో ఉపయోగించగల ఏవైనా ఫ్లాగ్లు.
కాబట్టి నిర్మించడానికి, మేము x86 (లేదా x64) తనిఖీ చేసిన బిల్డ్ని అమలు చేయాలి, వర్కింగ్ డైరెక్టరీని ప్రాజెక్ట్ ఫోల్డర్కు మార్చండి మరియు బిల్డ్ కమాండ్ను అమలు చేయాలి. స్క్రీన్షాట్లోని ఫలితం మనకు ఒక ఎక్జిక్యూటబుల్ ఫైల్ ఉందని చూపిస్తుంది.
ఈ ఫైల్ని అంత తేలికగా ప్రారంభించడం సాధ్యం కాదు, సిస్టమ్ శపిస్తుంది మరియు క్రింది లోపంతో దాని ప్రవర్తన గురించి ఆలోచించమని మాకు పంపుతుంది:
స్థానిక అప్లికేషన్ను ఎలా ప్రారంభించాలి?
autochk ప్రారంభించినప్పుడు, ప్రోగ్రామ్ల ప్రారంభ క్రమం రిజిస్ట్రీ కీ విలువ ద్వారా నిర్ణయించబడుతుంది:
సెషన్ మేనేజర్ ఈ జాబితా నుండి ప్రోగ్రామ్లను ఒక్కొక్కటిగా అమలు చేస్తారు. సెషన్ మేనేజర్ సిస్టమ్32 డైరెక్టరీలో ఎక్జిక్యూటబుల్ ఫైల్ల కోసం చూస్తారు. రిజిస్ట్రీ కీ విలువ ఆకృతి క్రింది విధంగా ఉంది:
autocheck autochk *MyNative
విలువ తప్పనిసరిగా హెక్సాడెసిమల్ ఫార్మాట్లో ఉండాలి, సాధారణ ASCII కాదు, కాబట్టి పైన చూపిన కీ ఫార్మాట్లో ఉంటుంది:
ఇన్స్టాలేషన్ మరియు రీబూట్ తర్వాత, వినియోగదారు ఎంపిక స్క్రీన్ కనిపించకముందే, మేము ఈ క్రింది చిత్రాన్ని పొందుతాము:
ఫలితం
అటువంటి చిన్న అప్లికేషన్ యొక్క ఉదాహరణను ఉపయోగించి, Windows Native స్థాయిలో అప్లికేషన్ను అమలు చేయడం చాలా సాధ్యమేనని మేము ఒప్పించాము. తరువాత, ఇన్నోపోలిస్ విశ్వవిద్యాలయం నుండి వచ్చిన అబ్బాయిలు మరియు నేను మా ప్రాజెక్ట్ యొక్క మునుపటి సంస్కరణ కంటే చాలా ముందుగానే డ్రైవర్తో పరస్పర చర్య ప్రక్రియను ప్రారంభించే సేవను నిర్మించడం కొనసాగిస్తాము. మరియు win32 షెల్ రావడంతో, ఇప్పటికే అభివృద్ధి చేయబడిన పూర్తి స్థాయి సేవకు నియంత్రణను బదిలీ చేయడం తార్కికంగా ఉంటుంది (దీనిపై మరింత ఇక్కడ).
తదుపరి కథనంలో మేము యాక్టివ్ పునరుద్ధరణ సేవ యొక్క మరొక భాగాన్ని తాకుతాము, అవి UEFI డ్రైవర్. మీరు తదుపరి పోస్ట్ను కోల్పోకుండా మా బ్లాగ్కు సభ్యత్వాన్ని పొందండి.