बहुत सारे Win32 एपीआई विशिष्ट लेआउट के साथ structs पर पॉइंटर्स लेते हैं। इनमें से, एक बड़ा सबसेट एक सामान्य पैटर्न का पालन करता है जहां पहले डीडब्ल्यूओआर को शुरू करने से पहले संरचना का आकार रखने के लिए प्रारंभ किया जाना चाहिए। कभी-कभी उन्हें पास करने के लिए स्मृति की एक ब्लॉक की आवश्यकता होती है, जिसमें वे एक संरचना लिखेंगे, और मेमोरी ब्लॉक एक आकार का होना चाहिए जो पहले एक ही एपीआई को एक नल पॉइंटर के साथ कॉल करके निर्धारित किया जाता है और सही मूल्य खोजने के लिए वापसी मूल्य पढ़ता है आकार। कुछ एपीआई एक संरचना आवंटित करते हैं और इसमें एक सूचक लौटाते हैं, जैसे कि पॉइंटर को दूसरे कॉल के साथ हटा दिया जाना चाहिए।
मैं आश्चर्यचकित नहीं होगा अगर एपीआई का सेट जिसे एक शॉट में उपयोगी रूप से बुलाया जा सकता है, व्यक्तिगत तर्क एक साधारण स्ट्रिंग प्रस्तुति से परिवर्तनीय है, काफी छोटा है।
इस विचार आम तौर पर लागू करने के लिए, हम काफी एक चरम पर जाने के लिए होगा:
typedef void DynamicFunction(size_t argumentCount, const wchar_t *arguments[],
size_t maxReturnValueSize, wchar_t *returnValue);
DynamicFunction *GenerateDynamicFunction(const wchar_t *code);
आप GenerateDynamicFunction करने के लिए कोड का एक सरल टुकड़ा से होकर गुजरेगा, और यह कुछ मानक बॉयलरप्लेट में उस कोड लपेटो जाएगा और उसके बाद एक डीएलएल बनाने के लिए एक सी संकलक/लिंकर का आह्वान करें (इसमें कुछ मुफ्त विकल्प उपलब्ध हैं), जिसमें फ़ंक्शन शामिल है। यह LoadLibrary
होगा कि DLL और फ़ंक्शन खोजने के लिए GetProcAddress
का उपयोग करें, और फिर इसे वापस करें। यह महंगा होगा, लेकिन आप इसे बार-बार उपयोग करेंगे और परिणामी DynamicFunctionPtr को बार-बार उपयोग के लिए कैश करेंगे। आप पॉइंटर्स को हैशटेबल में रखकर गतिशील रूप से ऐसा कर सकते हैं, जो कि कोड स्निपेट्स द्वारा स्वयं की कुंजी है।
बॉयलरप्लेट हो सकता है:
#include <windows.h>
// and anything else that might be handy
void DynamicFunctionWrapper(size_t argumentCount, const wchar_t *arguments[],
size_t maxReturnValueSize, wchar_t *returnValue)
{
// --- insert code snipped here
}
तो इस प्रणाली का एक उदाहरण उपयोग होगा:
DynamicFunction *getUserName = GenerateDynamicFunction(
"GetUserNameW(returnValue, (LPDWORD)(&maxReturnValueSize))");
wchar_t userName[100];
getUserName(0, NULL, sizeof(userName)/sizeof(wchar_t), userName);
आप GenerateDynamicFunction
बनाने तर्क गणना स्वीकार करके इस में वृद्धि कर सकता है, इसलिए यह एक उत्पन्न कर सकता है रैपर की शुरुआत में जांच करें कि सही संख्या में तर्क पारित किए गए हैं। और यदि आप प्रत्येक सामना कोडपिपेट के लिए फ़ंक्शंस को कैश करने के लिए वहां हैशटेबल डालते हैं, तो आप अपने मूल उदाहरण के करीब आ सकते हैं। कॉल फ़ंक्शन केवल एक एपीआई नाम की बजाय कोड स्निपेट लेगा, लेकिन अन्यथा वही होगा। यह हैशटेबल में कोड स्निपेट को देखेगा, और यदि मौजूद नहीं है, तो यह जेनरेट डायनामिक फ़ंक्शन को कॉल करेगा और परिणाम को अगली बार हैशटेबल में संग्रहीत करेगा। फिर यह समारोह पर कॉल करेगा। उदाहरण उपयोग:
wchar_t userName[100];
Call("GetUserNameW(returnValue, (LPDWORD)(&maxReturnValueSize))",
0, NULL, sizeof(userName)/sizeof(wchar_t), userName);
बेशक वहाँ इस के किसी भी कर ज्यादा बात जब तक विचार सामान्य सुरक्षा छेद के कुछ प्रकार को खोलने के लिए था नहीं होगा। जैसे एक webservice के रूप में Call
का पर्दाफाश करने के लिए। आपके मूल विचार के लिए सुरक्षा प्रभाव मौजूद हैं, लेकिन केवल इसलिए स्पष्ट नहीं हैं क्योंकि आपके द्वारा सुझाए गए मूल दृष्टिकोण प्रभावी नहीं होंगे। जितना अधिक शक्तिशाली हम इसे बनाते हैं, उतना ही अधिक सुरक्षा समस्या होगी।
अद्यतन टिप्पणी के आधार पर:
.NET फ़्रेमवर्क एक विशेषता पी बुलाया/आह्वान है, जो वास्तव में मौजूद है अपनी समस्या को हल करने के लिए है। तो यदि आप इसे सामान के बारे में जानने के लिए एक परियोजना के रूप में कर रहे हैं, तो आप यह समझने के लिए पी/आवेक देख सकते हैं कि यह कितना जटिल है। आप संभवतः अपनी स्क्रिप्टिंग भाषा के साथ .NET ढांचे को लक्षित कर सकते हैं - वास्तविक समय में स्क्रिप्ट को समझने के बजाय, या उन्हें अपने बाइटकोड में संकलित करने के बजाय, आप उन्हें आईएल में संकलित कर सकते हैं। या आप .NET पर पहले से उपलब्ध कई लोगों से मौजूदा स्क्रिप्टिंग भाषा होस्ट कर सकते हैं।
मैं स्ट्रिंग के बजाए बाइट्स की सरणी के रूप में char * का उपयोग कर रहा हूं। धारणा यह है कि मैं 'कॉल' फ़ंक्शन में मेटाडेटा उपलब्ध कराता हूं जो वास्तविक प्रकारों (यानी बाइट्स की संख्या) के आकारों का वर्णन करता है जो आवश्यक हैं। उस अर्थ में * प्रकार * ज्ञात हैं - वे बाइट्स की एक ज्ञात संख्या हैं। –
सामान्य रूप से आपको कॉल करने के लिए बाइट्स की संख्या से अधिक की आवश्यकता होती है, क्योंकि उत्तीर्ण सम्मेलन विभिन्न प्रकार के डेटा (विशेष रूप से फ़्लोटिंग-पॉइंट तर्कों के लिए) के लिए भिन्न हो सकता है। लेकिन मैं सही हो सकता हूं कि win32 __stdcall बस सबकुछ ढेर पर रखता है, मैं इसे विस्तार से नहीं जानता। – puetzk