2010-05-03 10 views
6

मेरे पास एक ऐसा प्रोग्राम है जिसमें मैं पूर्णस्क्रीन पोस्ट-प्रोसेसिंग प्रभाव जोड़ रहा हूं। मेरे पास प्रोग्राम के लिए स्रोत नहीं है (यह मालिकाना है, हालांकि एक डेवलपर ने मुझे डीबग प्रतीकों की एक प्रति भेज दी है, .मैप प्रारूप)। मेरे पास लिखित और काम करने वाले प्रभावों के लिए कोड है, कोई समस्या नहीं है।रैपर DLLs में स्टैक ओवरफ़्लो से बचें

मेरी समस्या अब दोनों को जोड़ रही है। मूल कार्यक्रम के आयात तालिका को संशोधित करने के

उपयोग चक्करदार मार्ग:

मैं दो तरीकों अब तक की कोशिश की है। यह बहुत अच्छा काम करता है और स्थिर होने की गारंटी है, लेकिन जिस उपयोगकर्ता के साथ मैंने बात की है, वह इसके साथ सहज नहीं है, इसे इंस्टॉलेशन की आवश्यकता है (एक संग्रह निकालने से परे), और कुछ प्रश्न हैं यदि डेटोरस के साथ प्रोग्राम को पैच करना शर्तों के तहत मान्य है ईयूएलए का। तो, वह विकल्प बाहर है।

दूसरा विकल्प पारंपरिक डीएलएल-प्रतिस्थापन है। मैंने OpenGL (opengl32.dll) को लपेट लिया है, और मुझे सिस्टम प्रतिलिपि के बजाय अपना डीएलएल लोड करने के लिए प्रोग्राम की आवश्यकता है (बस इसे सही नाम से प्रोग्राम फ़ोल्डर में छोड़ दें, यह आसान है)।

मुझे सीजी फ्रेमवर्क और रनटाइम (जो ओपनजीएल पर निर्भर करता है) लोड करने के लिए मेरे डीएलएल की आवश्यकता है और कुछ अन्य चीजें हैं। जब सीजी लोड होता है, तो यह मेरे कुछ कार्यों को कॉल करता है, जो सीजी कार्यों को कॉल करते हैं, और मुझे स्टैक ओवरफ्लो और अनंत लूप मिलते हैं। मुझे या तो उपनिर्देशिका में सीजी डीएलएल को शामिल करने में सक्षम होना चाहिए और अभी भी अपने कार्यों का उपयोग करना चाहिए (सुनिश्चित नहीं है कि मेरे डीएलएल आयात तालिका को एक उपनिर्देशिका में एक डीएलएल में इंगित करना संभव है) या मुझे गतिशील रूप से उनसे लिंक करना होगा (जो मैं ' डी न करें, केवल निर्माण प्रक्रिया को सरल बनाने के लिए), कुछ उन्हें सिस्टम की फ़ाइल (मेरे कस्टम प्रतिस्थापन नहीं) के संदर्भ में मजबूर करने के लिए मजबूर करें।

पूरी श्रृंखला है: प्रोग्राम DLL ए (opengl32.dll नामित) लोड करता है। डीएलएल एक sysdir/opengl32.dll को cg.dll लोड करता है और गतिशील रूप से लिंक (GetProcAddress)। अब मुझे cs.dll की आवश्यकता है sysdir/opengl32.dll, डीएलएल ए

यह कैसे किया जाएगा? संपादित करें: यह कैसे किया जाएगा आसानी से GetProcAddress का उपयोग किये बिना? यदि कुछ और काम नहीं करता है, तो मैं उस पर वापस आने के लिए तैयार हूं, लेकिन यदि संभव हो तो मैं नहीं चाहूंगा।

संपादित 2: मैं बस एमएसडीएन दस्तावेज़ों (पूरी तरह से असंबंधित खोज पर) में SetDllDirectory फ़ंक्शन में ठोकर खाई। पहली नज़र में, ऐसा लगता है कि मुझे क्या चाहिए। क्या यह सही है, या मैं गलतफहमी कर रहा हूँ? (अब इसे जांचने के लिए बंद करें)

संपादित 3: मैंने इस समस्या को थोड़ा अलग तरीके से हल कर लिया है। OpenGL32.dll को छोड़ने के बजाय, मैंने अपना डीएलएल बदलकर DInput.dll कर दिया है। 120 से अधिक (प्रोग्राम, सीजी, और जीएलईडब्ल्यू) के बजाय एक समारोह को निर्यात करने का लाभ न केवल मुझे है, मुझे वापस चलने वाले कार्यों के बारे में चिंता करने की ज़रूरत नहीं है (मैं ओपनजीएल को सामान्य रूप से लिंक कर सकता हूं) । कॉल में शामिल होने के लिए मुझे अवरोध करने की आवश्यकता है, मैं डेटोर का उपयोग कर रहा हूं। सब कुछ, यह बहुत बेहतर काम करता है। यह सवाल, हालांकि, अभी भी एक दिलचस्प समस्या है (और उम्मीद है कि भविष्य में पागल चीजें करने की कोशिश कर रहे किसी और के लिए उपयोगी होगा)। दोनों जवाब अच्छे हैं, इसलिए मुझे यकीन नहीं है कि अभी तक कौन सा चुनना है ...

+0

भविष्य में इस प्रश्न को पूरा करने वाले किसी भी व्यक्ति के लिए, सर्वोत्तम विकल्प (जो मैंने बाद में कुछ समय बाद समाप्त किया) ** ** डेटोर ** का उपयोग नहीं करते हैं। यह छोटी है, विशेष रूप से WoW64 में, और रिकर्सन-रोकथाम जैसी मूलभूत सुविधाओं को याद कर रहा है। [EasyHook] (http://easyhook.codeplex.com/) सुविधाओं, स्थिरता/प्रदर्शन, और सामान्य हैंडलिंग में कहीं बेहतर है। – ssube

उत्तर

1

SetDllDirectory शायद काम नहीं करेगा। Cg.dll शायद OpenGL.dll से लिंक हो सकता है। जब ओएस Cg.dll लोड करता है, तो यह देखता है कि पहले से ही उस नाम (आपका) से लोड किया गया मॉड्यूल है, इसलिए यह कुछ अन्य प्रतिलिपि खोजने के लिए इसके साथ सीजी को जोड़ता है। यही है, SetDllDirectory संशोधित खोज आदेश कभी भी खेल में नहीं आता है क्योंकि ओएस कोई खोज नहीं करता है।

मुझे संदेह है कि आपकी सर्वश्रेष्ठ शर्त वास्तव में आपकी लाइब्रेरी में पुन: प्रवेश कॉल का पता लगाने के लिए होगी। जब आप अपना कस्टम हैंडलिंग करने के बजाए एक का पता लगाते हैं, तो सीधे कॉल को वास्तविक ओपनजीएल लाइब्रेरी में अग्रेषित करें, जिसमें आपके पास लोड लाइब्रेरी को कॉल करने और फिर लाइब्रेरी के प्रत्येक फ़ंक्शन के लिए GetProcAddress के कारण संदर्भ है।

+0

क्या आपके पास इन्हें पहचानने का सबसे आसान तरीका है? मैंने पहले इस मुद्दे में भाग नहीं लिया है, इसलिए मैं इसे संभालने का सबसे अच्छा तरीका से परिचित नहीं हूं। किसी विशेष स्थिति पर असली कॉल करने के लिए प्रत्येक फ़ंक्शन की शुरुआत में स्निपेट जोड़ना कोई समस्या नहीं है, लेकिन जांच करने के लिए सबसे अच्छी चीज़ क्या है? – ssube

+1

वास्तव में, मेरे पास एक विचार था। क्या यह एक साधारण वैश्विक बूलियन मूल्य का उपयोग करने के लिए प्रभावी और कुशल होगा? मेरे फ़ंक्शन की शुरुआत में, 'if (cameBack) {real realFunc को कॉल करें; } else {cameBack = true; } ', फिर निष्पादन छोड़ने पर इसे गलत पर सेट करें। ऐसा लगता है जैसे यह काम करेगा। मेरा कोड नहीं है, जहां तक ​​मुझे पता है, थ्रेड-सुरक्षित होने की आवश्यकता है (प्रोग्राम में एक सिंगल रेंडरिंग थ्रेड है, और एक थ्रेड जो ओपनजीएल को मेरे डीबगिंग से बिल्कुल संदर्भित करता है)। – ssube

+1

एक वैश्विक चर वैसा ही है जो मैंने पहले प्रयास के लिए उपयोग किया होगा। यदि आपको एकाधिक धागे की आवश्यकता है, तो आप सादा ग्लोबल्स के बजाय थ्रेड-लोकल स्टोरेज आज़मा सकते हैं। यदि आपके द्वारा अवरुद्ध किए गए कार्यों में से एक * अलग * ओपनजीएल फ़ंक्शन को कॉल करना समाप्त करता है जिसे आप * भी अवरुद्ध करना चाहते हैं, तो आप केवल एक के बजाय फ़ंक्शन-विशिष्ट वैश्विक चर का उपयोग कर सकते हैं। –

1

आप अपनी समस्या का समाधान करने के लिए सक्रियण संदर्भों के जादू का उपयोग कर सकते हैं।

मौसम पर बहुत सारे हिस्सों में आपके सिस्टम में तीसरे पक्ष के घटक पहले से ही प्रकट हुए हैं - और उन प्रकटताओं के साथ कितना छेड़छाड़ लाइसेंस उल्लंघन का गठन कर सकती है।

डीएलएल संस्करण समस्याओं को हल करने के लिए, विंडोज एक्सपी को सक्रियण संदर्भ नामक एक तकनीक मिली। कभी-कभी साथ-पक्ष विधानसभाओं, या यहाँ तक Application Isolation

की तरह भयानक कुछ के रूप में जाना एक छोटी सी जगह में पढ़ने की बहुत सारी संक्षेप में: प्रकट होता है XML डेटा का हिस्सा है कि एक विधानसभा का वर्णन कर सकते हैं, या विधानसभाओं पर निर्भरता का वर्णन कर रहे हैं। एक असेंबली एक मैनिफेस्ट है, और इसके डीएलएल है।

इसका कारण यह है कि एक असेंबली एक साधारण डीएल ले सकती है। "comctl32.dll" और इसका संस्करण संख्या (v6), और एक बड़ा और अनूठा नाम वाला एक चीज़ बनाएं, जैसे कि सरल डीएल के कई संस्करण एक ही स्थान पर सुरक्षित रूप से स्थापित किए जा सकते हैं। असेंबली C:\Windows\WinSxS में स्थापित करने का इरादा है।

जब एक मेनिफेस्ट फ़ाइल किसी असेंबली में डीएलएस का वर्णन करती है, तो इसे एक असेंबली मैनिफेस्ट कहा जाता है। और आमतौर पर डीएलएल के लिए एक अलग नाम है।

जब एक मेनिफेस्ट फ़ाइल असेंबली का वर्णन करता है तो एक डीएलएल या एक्सई उपयोग करता है, इसे एप्लिकेशन मेनिफेस्ट कहा जाता है, और आमतौर पर एक RT_MANIFEST संसाधन के रूप में एम्बेडेड किया जाता है - EXE में 1 के रेस आईडी के साथ, डीएल में 2 के रेस आईडी के साथ - या डिस्क पर "appname.exe.manifest"/"dllname.dll.2.manifest" नाम वाली फ़ाइल के रूप में डिस्क पर। एप्लिकेशन प्रकट होता है एक सक्रियण संदर्भ नामक एक चीज़ को परिभाषित करता है - जो मूल रूप से एक नामस्थान है जो विंडोज़ चीजों के लिए खोज करेगा। प्रत्येक मेनिफेस्ट एक सक्रियण संदर्भ बनाता है। प्रत्येक सक्रियण संदर्भ में असेंबली के लिए सरल डीएलएल नामों का मैपिंग होता है।

इसलिए, यदि आप अपने opengl32.dll फ़ाइल के साथ एक विधानसभा बनाते हैं, और फ़ाइल app.exe संदर्भित करने के लिए एक सक्रियण संदर्भ (स्थानीय opengl32.dll) बनाते हैं, तो, संभावित, सभी शेष DLLs कर सकते हैं (और करेंगे) इस तथ्य के बावजूद कि सिस्टम बहुत समान हैं ताबूत

समस्या यह है कि, एप्लिकेशन मैनिफेस्ट का res-id - 1 - इसका मतलब है कि इसका उपयोग प्रक्रिया सक्रिय सक्रियण संदर्भ बनाने के लिए किया जाता है - इसलिए सभी डीएल जिनके पास अपनी स्पष्ट प्रकट नहीं होती है (सीजी?) खोज करने जा रही हैं प्रक्रिया डिफ़ॉल्ट अंतरिक्ष और उस opengl32.dll

तो तुम के लिए प्रकट होता है बनाने के लिए हर dll कि पहले से ही एक एम्बेड नहीं करता है लगता है, जिससे बस अपने opengl32.dll विधानसभा का संदर्भ नहीं है, जो करने के लिए तो अनुमति चाहिए सुनिश्चित करें डिफ़ॉल्ट खोज ऑर्डर पर वापस जाएं और इसे सामान्य सिस्टम 32 स्थान में ढूंढें।

इसका मतलब है कि आपका opengl32.dll exe के फ़ोल्डर में नहीं हो सकता है क्योंकि उस फ़ोल्डर को system32 से पहले डीएल के लिए खोजा जाता है (तथ्य यह है कि आप हुकिंग के लिए भरोसा करते हैं)।

हम असेंबली की खोज करते समय सिस्टम के बजाय सरल खोज आदेश से बचाए जाते हैं। सबसे पहले यह WinSxS में खोज करता है। आपका Opengl32।डीएलएल वहां नहीं होगा, वहां स्थापित करना एक कठिन समस्या है। फिर यह उपफोल्डर के लिए असेंबली के नाम के साथ exe के फ़ोल्डर में खोज करता है, फिर यह सीधे एन्क्रिप्शन के लिए exe के फ़ोल्डर में खोज करता है।

इसका मतलब है आप एक विधानसभा बना सकते हैं - जैसा कुछ कहा: कैसा दिखेगा "OpenGLHook" और अपने फ़ोल्डर संरचना:

\appfolder\ 
    app.exe 
    app.exe.manifest     - contains a dependentAssembly node to OpenGLHook 
    OpenGLHook\OpenGLHook.manifest - contains a file name=opengl32.dll 
    OpenGLHook\opengl32.dll   - your hook dll 
    yourimpl.dll      - your implementation dll that linkgs to cg.dll 
    cg.dll       - cg libraries 
    cg.dll.2.manifest     - a stub manifest you put together to ensure cg 
             doesnt use the app default activation ctx. 

उम, गुड लक?