CreateDCA、CreateDCWのパラメータ指定法とエラーの原因

このQ&Aのポイント
  • CreateDCA、CreateDCWのパラメータ指定法について説明します。具体的には、Unicode版とANSI版が実装されており、それぞれの呼び出し方が異なることに注意が必要です。
  • また、CreateDCではなくCreateDCAとCreateDCWを直接呼び出す理由として、APIフックでCreateDCを引っ掛けたいからです。しかし、正しい呼び出し方ができずにエラーが発生しています。
  • 現在、CreateDCA、CreateDCWのパラメータ指定法に関する資料は見当たらないため、解決策が見つかっていません。資料を探し続けるか、他の方法を検討する必要があります。
回答を見る
  • ベストアンサー

CreateDCA、CreateDCWのパラメータ

HDC CreateDC(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutPut, CONST DEVMODE *lpInitData)にはUnicode版とANSI版が実装されます よってCreateDCAでは HDC CreateDCA(PCTSTR lpszDriver, PCTSTR lpszDevice, PCTSTR lpszOutPut, CONST DEVMODE *lpInitData) CreateDCWでは HDC CreateDCW(LCPWSTR lpszDriver, LCPWSTR lpszDevice, LCPWSTR lpszOutPut, CONST DEVMODE *lpInitData) と定義されているのだと思い、上記の形式で呼び出しましたがエラーとなってしました Run_Time check Failure #0- The Value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling conversion with a function pointer declared with a different calling conversion. なぜCreateDCではなくCreateDCAとCrateDCWを直接呼び出すような面倒なことをしているかというと、APIフックでCreateDCを引っ掛けたいのです CreateDCはCreateDCA、CreateDCWになってしまうのでCreateDCではフック出来ません そこでCreateDCA、CreateDCWでフックして当方の処理を行い、その後で本来のCreateDCA、CreateDCWを呼び出しております ところが呼出し方が悪いらしく上記の英文エラーが出てしまいます CreateDCA、CreateDCWで検索したのですが適当な資料が見当たりません 目下のところ手も足も出ません CreateDCA、CreateDCWのパラメータ指定法(多分エラーの原因だろうと思っていますので・・・)をご存知でしたらご指導願います

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

さらに1つ補足しておくと、1~3番目の引数の型の LPCTSTR は ANSI版では LPCSTR となり(「T」が不要)、Unicode版では LPCWSTR となります。また、DEVMODE も同様にANSI版とUnicode版があり、それぞれ DEVMODEA と DEVMODEW がありますのでご注意ください。

sato-may
質問者

お礼

重ね重ねご指導を頂きありがとうございます こちらも修正して確認しておきました 誠にありがとうございました

その他の回答 (2)

回答No.2

> typedef HDC (WINAPI *PFNCREATEDCA) (PCTSTR, PCTSTR, PCTSTR, CONST DEVMODE); > typedef HDC (WINAPI *PFNCREATEDCW) (LPCWSTR, LPCWSTR, LPCWSTR, CONST DEVMODE); 最後の引数の型が変わってしまってますね。ポインタではなく構造体の値渡しになってしまっています。正しくは typedef HDC (WINAPI *PFNCREATEDCA) (PCTSTR, PCTSTR, PCTSTR, CONST DEVMODE*); typedef HDC (WINAPI *PFNCREATEDCW) (LPCWSTR, LPCWSTR, LPCWSTR, CONST DEVMODE*); で、置き換える関数の中でもアスタリスクを外して HDC nResult = ((PFNCREATEDCA)(PROC) g_CreateDCA)(lpszDriver, lpszDevice, lpzsOutput, lpInitDat); としなければいけません。

sato-may
質問者

お礼

ご指導ありがとうございます 取り敢えずご指摘頂いた箇所を修正してランして見たら、一発OKでした 見事にCreateDCA、CreateDCWの両者をフックすることが出来ました まずはご報告と御礼を申し上げます ・・・・・実のところ、お教え頂いた内容をまだ理解しておりません 後刻ゆっくりと勉強させて頂きます・・・・・ ありがとうございました 今後も宜しくお願い申し上げます

回答No.1

もしかしたら、呼び出し規約の不一致のために、呼び出し後にスタックポインタが正しく戻っていないのでは、思うのですが。 元の関数アドレスを格納するポインタや、フックで置き換える関数の呼び出し形式は __stdcall になっていますか? 指定しない場合はデフォルトで __cdecl になるので、明示的に WINAPI または __stdcall を付ける必要があります。

sato-may
質問者

お礼

ご指導ありがとうございます ご指摘いただいたWINAPIは次のようにしております HDC WINAPI Hook_CreateDCA(PCTSTR lpszDriver, PCTSTR lpszDevice, PCTSTR lpzsOutput, CONST DEVMODE *lpInitData) { //ここで私の処理を行ってから(但し現在に所、何もしていない フックがOKになったら追加の予定)オリジナルCreateDCAを呼び出す HDC nResult = ((PFNCREATEDCA)(PROC) g_CreateDCA)(lpszDriver, lpszDevice, lpzsOutput, *lpInitDat); reurn nResult; } 補足】パラメータのPCTSTRを下記のようにLPSTRに変更しても結果は同じでした HDC WINAPI Hook_CreateDCA(LPSTR lpszDriver, LPSTR lpszDevice, LPSTR lpzsOutput, CONST DEVMODE *lpInitDat) //---------------------------------------------------- HDC WINAPI Hook_CreateDCW(LPCWSTR lpszDriver, LPCWSTR lpszDevice, LPCWSTR lpzsOutput, CONST DEVMODE *lpInitData) { //ここで私の処理を行ってから(但し現在に所、何もしていない フックがOKになったら追加の予定)オリジナルCreateDCAを呼び出す HDC nResult = ((PFNCREATEDCW)(PROC) g_CreateDCW)(lpszDriver, lpszDevice, lpzsOutput, *lpInitData); return nResult; } またプログラムの関連する他の部分は次の通りです extern CAPIHook g_CreateDCA; extern CAPIHook g_CreateDCW; typedef HDC (WINAPI *PFNCREATEDCA) (PCTSTR, PCTSTR, PCTSTR, CONST DEVMODE); typedef HDC (WINAPI *PFNCREATEDCW) (LPCWSTR, LPCWSTR, LPCWSTR, CONST DEVMODE); CAPIHook g_CreateDCA  ("Gdi32.dll", "CreateDCA", (PROC) Hook_CreateDCA); CAPIHook g_CreateDCW ("Gdi32.dll", "CreateDCW", (PROC) Hook_CreateDCW); お察しのようにジェフリー リッチャー氏の Advanced Windows[単行本] を参考にさせて頂いております 今日も一日悪戦苦闘致しましたが全く前進しませんでした、更に何かヒントを頂戴出来れば大変有難いです なおフックが落ちてしまうのは、このCreateDCA、CreateDCWだけであり下記のAPIは正常にフックしています MessageBoxA MessageBoxW StartDocA StartDocW StartPage EndPage EndDoc TextOutA TextOutW ExtTextOutA ExtTextOutW DrawTextA DrawTextW DrawTextExA DrawTextExW TabbedTextOutA TabbedTextOutW SetTextAlign これらのAPIとCreateDCA、CreateDCWのパラメータの差は CONST DEVMODE があるか否かです でも浅学の私には CONST DEVMODE を理解出来ず、この辺りが怪しいと思っても対応出来ないのです 宜しくお願い申し上げます

関連するQ&A

  • エラー内容について

    お世話になっております。 現在、VC++6.0にてアプリを開発中です。 そこで、下記エラーが発生し、処理がうまく行きません。 エラーの内容と、対策をお教え下さい。 [エラー内容] Debug Error! Program:xxxxxxxxx.exe Module: File:i386\chkesp.c Line:42 The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention. (Press Retry to debug the application) エラー発生の場所は、GetProcAddressで、DLLの関数のアドレスを取得し、その関数をコールした結果で起こっています。 DLL内部にログ出力を入れた結果、DLLの関数自体は正常終了しています。 DLLの関数を取得している部分は下記の通りです。 typedef int (APIENTRY *LPGetRouteList)(WORD wdIn1, WORD wdIn2, WORD wdin3);   ・   ・   ・ LPGetRouteList lpGetRouteList;   ・   ・   ・ lpGetRouteList = (LPGetRouteList)GetProcAddress(hHandle,"GetRouteList); 関数を使用している部分は、下記の通りです。 int iRet = 0;   ・   ・   ・ iRet = lpGetRouteList(wdA, wdB, wdC); <- ここでエラーが発生 DLLの関数は以下の通りです。 extern WORD APIENTRY GetRouteList(WORD wdIn1, WORD wdIn2, WORD wdIn3) { WORD wdRet = 0;   ・   ・   ・  return(wdRet); } 以上、長文で見づらいと思われますが、なにとぞ宜しくお願いします。

  • Cabの解凍プログラム

    現在Cabの解凍をするプログラムを作っています。 Cabファイル内のファイル数を取得するために、 int WINAPI CabGetFileCount(LPCSTR szArcFile); というAPIを使おうとしているのですが、 実行中に、デバッグエラーが出ます。 エラーメッセージ The value ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention pointer declared with a different calling convention. ソースは以下のものです。 typedef bool (*TFUNC)(LPCSTR); void 関数名(HWND hWnd) { HINSTANCE hCab=NULL; //cab32.dllのインスタンスハンドル TFUNC DllFunction; int FileCount; //cab32.dllのロード hCab = LoadLibrary("cab32.dll"); if(hCab == NULL) { MessageBox(hWnd,"cab32.dllがありません。","エラー",MB_OK); return; } DllFunction=(TFUNC)GetProcAddress(hCab,"CabGetFileCount"); FileCount = (*DllFunction)("test.cab"); FreeLibrary(hCab); } (DLL使用テストのソース) コンパイラーは"VC++6.0" OSはWin2Kになります。 わかるかたよろしくお願いします。

  • 自作DirectShow Filterのinterface定義

    DirectShow Filterを自作しGraphEdit上で動作することを確認しました。 しかしC++プログラム上から独自定義のメソッドを呼び出すと 呼び出し元と先で呼び出し規約が異なるというエラーが出てしまいます。 定義は DEFINE_GUID(CLSID_MyClass, <<適当なGUID1>>); DEFINE_GUID(IID_IMyClass, <<適当なGUID2>>); MIDL_INTERFACE("<<適当なGUID2>>") IMyClass : public IUnknown {  STDMETHOD(myMethod)(void) PURE; }; class CMyClass : public CTransInPlaceFilter {  CMyClass ::CMyClass (IUnknown * pOuter, HRESULT * phr, BOOL ModifiesData);  CMyClass ::~CMyClass (); public:  static CUnknown *WINAPI CMyClass::CreateInstance(LPUNKNOWN punk, HRESULT *phr);  DECLARE_IUNKNOWN;  STDMETHODIMP CMyClass::myMethod(void){return S_OK;}; } 呼び出し元では DEFINE_GUID(CLSID_MyClass, <<適当なGUID1>>); DEFINE_GUID(IID_IMyClass, <<適当なGUID2>>); MIDL_INTERFACE("<<適当なGUID2>>") IMyClass : public IUnknown {  STDMETHOD(myMethod)(void) PURE; }; int main() {  CoInitialize(NULL);  IMyClass pMyClass;  CoCreateInstance(   CLSID_MyClass,   NULL,   CLSCTX_INPROC,   IID_IMyClass,   (LPVOID *)&pMyClass  );  pMyClass->myMethod();←ここでエラー  ・  ・  (略)  ・  ・ } エラーメッセージは Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention. です。 どちらも__stdcallになってるはずなんですが… 原因が分かる方おられましたらよろしくお願いいたします。

  • HDCを他の領域にコピーするには?

    HDC hdc = CreateDC("WINSPOOL","プリンタの名前",NULL,NULL); ....(1)プリンタのHDCの作成 HDC hdcMemDC = CreateCompatibleDC(hdc); ....(2)前者と同じ仕様のメモリーHDCの作成 hdcとhdcMemDCはハンドラへのポインタだと思います hdc ....(ポインタ)....... hdcの内容 (A) hdcMemDC ....ポインタ.......hdcMemDCの内容 (B) もしBをA領域に書き写せば TextOut(hdc,0,0,"メモリーDCに書き込めると思います",100); とするとプリンタにではなくメモリ-DCに書込むと思います   ⇒ BをAに書き写さずTextOut(hdcMeMDC,0,0,"メモリーDCに書き込めると思います",100);と同じ結果になるでしょう ところが『BをAに書き写す』方法が分かりません ハンドラの構成、サイズなどの資料を探しましたが適当なものが見つかりません ご存知でしたら教えてください 【追加説明】 TextOut(hdc,0,0,"メモリーDCに書き込めると思います",100); のステートメントを TextOut(hdcMeMDC,0,0,"メモリーDCに書き込めると思います,100); にするには一般的にはAPIフックが必要になります ⇒ もちろん全ソースの手修正でも可能ですが...... APIフックも手修正も回避したいのです

  • エラーがとれません 助けてください

    エラーがとれません 助けてください http://cs.fit.edu/~mmahoney/dist/eval4.cpp をコンパイルすると eval4.cpp: In member function ‘bool Attack::read(FILE*)’: eval4.cpp:105: error: ‘strlen’ was not declared in this scope eval4.cpp:114: error: ‘strchr’ was not declared in this scope eval4.cpp: In function ‘int main(int, char**)’: eval4.cpp:132: warning: deprecated conversion from string constant to ‘char*’ eval4.cpp:133: warning: deprecated conversion from string constant to ‘char*’ eval4.cpp:134: warning: deprecated conversion from string constant to ‘char*’ eval4.cpp:183: error: ‘strlen’ was not declared in this scope のようなエラーがでてしまいます。 Ubuntuのg++でコンパイルしています。 なにがまずいのでしょうか?

  • MFC C++ と C++/CLI の文字列

    VS2008です。 Library: NativeC++ with MFC -> DLL   ↑↓ Wrapper: C++/CLI with .NET -> DLL   ↑↓ Appli: VB.NET with .NET -> EXE 元々、ActiveXコントロール(非GUI利用)だったNativeC++で書かれたLibraryを MFC DLLとしてビルドし、Wrapper 経由で Appli から使用できるよう 移植をしています。 Library から必要な関数を dllexport し、wrapper から参照し、 wrapper を Appli が参照して、使用できるようにしました。 int型を引数に取り、結果として返す関数は期待どおり動作しますが、 文字列だと上手く行きません。 Wrapper/Appli は System.CString で統一したいのですが、 Library ではどのような型として宣言すれば文字列のやり取りができるでしょうか。 ( 引数・戻値の両者 ) CString wchar_t* char* System.String ALT::CStringT basic_string _bstr_t CComBSTR LPCTSTR LPTSTR PCTSTR PTSTR LPCWSTR LPWSTR PCWSTR PWSTR BSTR… なお、Library で下記のようにエクスポートし __declspec(dllexport) BSTR test(LPCTSTR data); wrapper で BSTR hoge(LPCTSTR value){ return test(value); } と宣言すると、wrapperのビルドで下記のエラーが表示されます。 エラー 1 error LNK2028: 未解決のトークン (0A000B39) "wchar_t * __cdecl test(wchar_t const *)" (?test@@$$FYAPA_WPB_W@Z) が 関数 "public: wchar_t * __clrcall wrap::hoge(wchar_t const *)" (?hoge@C3dlib@@$$FQ$AAMPA_WPB_W@Z) で参照されました。 wrapper.obj wrapper エラー 2 error LNK2019: 未解決の外部シンボル "wchar_t * __cdecl test(wchar_t const *)" (?test@@$$FYAPA_WPB_W@Z) が 関数 "public: wchar_t * __clrcall wrap::hoge(wchar_t const *)" (?hoge@C3dlib@@$$FQ$AAMPA_WPB_W@Z) で参照されました。 wrapper.obj wrapper エラー 3 fatal error LNK1120: 外部参照 2 が未解決です。

  • wxGladeで生成したhello.cpp&hello.hファイルをコンパイルしようとするとエラーが出ます

    http://0xcc.net/pub/uu-2004-08/ や http://d.hatena.ne.jp/foral/20061224 を見て、wxGladeで生成したhello.cpp&hello.hファイルをMSYSのコンソールから g++ -c hello.cpp 'wx-config --cxxflags --libs' でコンパイルしようとしたのですが、以下のようなエラーが出てコンパイルできません。 環境はWindows XP MinGW&MSYS wxWidgets2.8.7 (パスは、C:\msys\1.0\home\owner) です。 普通のC++ファイルのコンパイルは出きるのですがwxWidetsが絡むとできないようです。 In file included from hello.cpp:3: hello.h:3:10: #include expects "FILENAME" or <FILENAME> hello.h:4:10: #include expects "FILENAME" or <FILENAME> In file included from hello.cpp:3: hello.h:13: error: expected class-name before '{' token hello.h:18: error: expected `)' before '*' token hello.h:28: error: ISO C++ forbids declaration of `wxStaticText' with no type hello.h:28: error: expected `;' before '*' token hello.h:29: error: ISO C++ forbids declaration of `wxPanel' with no type hello.h:29: error: expected `;' before '*' token hello.cpp:6: error: expected `)' before '*' token hello.cpp: In member function `void MyFrame::set_properties()': hello.cpp:22: error: `wxT' was not declared in this scope hello.cpp:22: error: `SetTitle' was not declared in this scope hello.cpp: In member function `void MyFrame::do_layout()': hello.cpp:30: error: `wxBoxSizer' was not declared in this scope hello.cpp:30: error: `sizer_1' was not declared in this scope hello.cpp:30: error: `wxBoxSizer' is not a type hello.cpp:30: error: `wxVERTICAL' was not declared in this scope hello.cpp:31: error: `sizer_2' was not declared in this scope hello.cpp:31: error: `wxBoxSizer' is not a type hello.cpp:31: error: `wxHORIZONTAL' was not declared in this scope hello.cpp:32: error: `label_1' was not declared in this scope hello.cpp:32: error: `wxFIXED_MINSIZE' was not declared in this scope hello.cpp:33: error: `panel_1' was not declared in this scope hello.cpp:37: error: `wxEXPAND' was not declared in this scope hello.cpp:38: error: `SetAutoLayout' was not declared in this scope hello.cpp:39: error: `SetSizer' was not declared in this scope hello.cpp:42: error: `Layout' was not declared in this scope hello.cpp: At global scope: hello.cpp:48: error: expected class-name before '{' token hello.cpp:55: error: expected constructor, destructor, or type conversion before "bool" g++.exe: wx-config --cxxflags --libs: No such file or directory 解決方法が分かる方いらっしゃしましたらご教示頂けると幸いです。

  • テンプレートクラス中のフレンドクラス

    下記をg++(fedora core1)でコンパイルしたところ、 #include <iostream> using namespace std; template< typename T > class A {   T a; public:   A(T aa ) : a(aa) { }   friend ostream& operator<<( ostream &os, const A &a ); //9行目 }; template< typename T > ostream& operator<<( ostream &os, const A<T> &a ) { return os << a.a; } int main( ) {   A<int>  a(5);   cout << a << '\n';   return 0; } 9行目にこのような警告・エラーが出てコンパイルできませんでした。(下記のオプションも試してみましたがダメでした) friend declaration 'std::ostream& operator<<(std::ostream&, const A<T>&)' declares a non-template function (if this is not what you intended, make sure the function template has already been declared and add<> after the function name here) -Wno-non-template-friend disables this warning. :undefined reference to 'operator<<(std::basic_ostream <char, std::char_traits<char> >&, A<int> const&)' なぜ、コンパイルできないのかが分かりません。ちなみに、bcc32(borland c++ compiler5.5.1)では同様のエラーが出てコンパイルできず、cl(VC++6.0)ではコンパイル・実行可能でした。 ご存知の方いらっしゃったらご教授お願いします。(bccとclはWinXPです)

  • 【GAS】 ~is not a function

    GoogleのAppsScriptに関する質問です。function test実行時に生じるErrorの原因が特定できず困っています。誤っている箇所を教えていただけませんか(sheet name : aiueo)。 よろしくお願いします。 function getName(sheetName) { const aaa = SpreadsheetApp.getActiveSpreadsheet().getId();//✓console.log(aaa) const iii = aaa.getSheetByName(sheetName);//✖TypeError: aaa.getSheetByName is not a function } function test(){ getName("aiueo");//✖TypeError: aaa.getSheetByName is not a function }

  • makeについて

    quasar media playerと言うソフトをインストールしようと思いmakeの手前まではうまくいったのですがmakeで                ・                ・                ・                 省略 ../../../include/qt4/QtCore/qvector.h:321: instantiated from ‘const T& QVector<T>::operator[](int) const [with T = Skin]’ skinmanager.h:171: instantiated from here ../../../include/qt4/QtCore/qvector.h:92: error: ‘QVectorTypedData<T>::array’ has incomplete type skinmanager.h:37: error: forward declaration of ‘struct Skin’ ../../../include/qt4/QtCore/qvector.h: In member function ‘const T& QVector<T>::operator[](int) const [with T = Skin]’: skinmanager.h:171: instantiated from here ../../../include/qt4/QtCore/qvector.h:322: error: ‘struct QVectorTypedData<Skin>’ has no member named ‘array’ make: *** [configuration.o] エラー 1 root@ubuntu:/usr/local/src/v0.9_beta3# というエラーが出てきて先へ進めません。 このエラーを解決するには具体的にどうしたらいいのでしょうか。わかる方いらしたらどうかご教授よろしくお願いします。              

専門家に質問してみよう