# Native Code > برنامه نویسی با C > برنامه نویسی با MFC و ++Visual C > سوال: برنامه نویسی در ویندوز cryptography

## bizmit

سلام
من توی کامپایل یه برنامه تحت عنوان CSP که مخفف Cryptograohic Service Provider هستش،دچار مشکل شدم!
یه بسته ای به نام cspdk با حجم 1.4 مگ توی سایت مایکروسافت هست که شامل کد نمونه و قالب csp میشه ،اینم لینکش:
http://www.microsoft.com/downloads/details.aspx?FamilyID=0F436C75-2304-42BB-
B81A-BA0C2C47BAC2&displaylang=en
csp به صورت یه اینترفیس میتونه با توابع CryptoAPI ارتباط برقرار کنه و از طرفی میتونه برای کاربردهای رمزنگاری توی کارت هوشمند بکار بره!
توضیحات کاملش در سایت MSDN موجوده...
من باید یه CSP نمونه که بصورت DLL پیاده سازی میشه بنویسم،ولی با کامپایل و کار با این بسته مشکل پیدا کردم!
از کسایی که تو این زمینه کار کردن و یا اینکه میتونن این CSP نمونه رو به صورت DLL کامپایل کنن و یا اینکه کسی رو که در این زمینه وارد هستش سراغ دارن ،عاجزانه خواهش می کنم کمکم کنن،خیلی نیاز به کمک دارم!
در ضمن کسی تو نوشتن wrapper برای تبدیل دستورات رمزنگاری به دستورات کارت هوشمند تجربه داره؟
لطفا اگه می تونید،هر چه زودتر کمکم کنید،وقتم خیلی کمه
با تشکر از شما

----------


## Nima_NF

چرا از نمونه dll ساخته شده در این بسته استفاده نمی کنید، سر راست هست. سورس کد نمونه ساخت  dll در فولدر csp قرار دارد.

می توانید به آن توابع مورد نیاز خود را اضافه کنید و کامپایل کنید تا dll ساخته شود (یک پروژه win32 project در ++Visual C بسازید و همه فایل ها را به پروژه وارد کنید). اسامی توابع در فایل DEF تعریف شده اند و قالب هر تابع نیز در csp که می توانید همانند آن سایر توابع را اضافه کنید.

در مورد مباحث اولیه dll هم در همین بخش و همین طور بخش ++Visual C جستجو کنید، توضیحات اولیه ساختن dll داده شده است.

----------


## bizmit

سلام

راستش من توی ویژوال ++C ورژن 6 ،یه پروژه dll ایجاد کردم و کد فایل csp.c رو توش کپی کردم (هم چنین دو تا هدر فایل csp.h و cspdk.h رو هم توی فولدر include در جایی که ویژوال ++C نصب شده،کپی کردم)و کامپایل کردم ولی 102 تا ارور داد که اکثرا از cspdk.h می گرفت که فلان متغیر undeclared identifier هستش و ...
بعد تصمیم گرفتم که فایل نوت پد csptest رو در یه پروژه win32 console application وارد کنم و فایل csp.dll موجود در بسته cspdk رو در فولدر مربوط به اون کپی کنم و بعد کامپایل کنم که در این حالت هم 38 تا ارور می داد!
الآن واقعا نمی دونم که چه طور باید اونو کامپایل کنم که یه نتیجه معقول ببینم؟!
لطفا اگه این فایل رو به درستی کامپایل کردین و طرز استفاده از 3 تافایل exe موجود در بسته رو می دونین،راهنماییم کنین!
شدیدا نیاز به کمک فوری دارم
ممنون

----------


## Nima_NF

به چند نکته باید توجه کنید تا پروژه درست انجام شود:

1- کامپایلر VC++‎6 قدیمی شده و بهتر هست از نسخه 2005 یا 2008 کنید.

2- یک پروزه win32 project و حتما از نوع dll باید بسازید و تمامی فایل ها در فولدر csp را به آن اضافه کنید، حتی فایل sip را.

3- خوشحالم که readme  پروژه را مطالعه کردید، بله اگر در SDK وجود ندارد باید دو فایل هدر را از فولدر sdkinc به برنامه اضافه کنید و cspdk.h به جای <> با " " مشخص کنید.(یا بهتر و علمی تر اینکه می توانید مسیر فولدر sdkinc را از طریق تنظیمات option به Include های کلی VC اضافه کنید)

4- حال قسمت مهم، باید با توجه به API هایی که استفاده می کنید فایل lib آن ها را نیز به linker اضافه کنید، در غیر این صورت ده ها خطا دریافت می کنید.

برای این پروژه به منوی project رفته در properties به linker و سپس Input بروید، در فیلد Additional dependency دو مورد زیر را وارد کنید:

Advapi32.lib  Crypt32.lib
حتما در هر دو حالت release و debug این موارد را وارد کنید.

5- پروژه کامپایل می شود.

پروژه کامل و قابل کامپایل در VC++‎2008 را در زیر ضمیمه کردم، برای سایر sample ها هم باید به همین شکل عمل کنید.

ضمنا چون بحث بر سر API ها است این تاپیک را به بخش ++VC منتقل می کنم.

----------


## bizmit

سلام
باز هم ممنون از پاسخ کاملتون
چند تا سوال داشتم،البته ببخشید سوالاتم خیلی ابتدائیه،دلیلش هم اینه که خیلی کم با ویژوال کار کردم!
من ویژوال ++C ورژن 6 رو دارم،نمی دونم ورژن کامپایلرش چنده؟!
در ضمن برای دانلود کامپایلر  نسخه 2005 یا 2008 باید به کدوم آدرس برم؟
اصلا منظورتون از 2005 یا 2008 چیه؟ یعنی Visual Studio 2005/8 ؟
آیا میشه کامپایلر رو جدا از محیط برنامه نویسی دانلود کرد و به محیط اون اضافه کرد؟


در فولدر wince هم یک فولدر بنام csp هست،حالا من که قصد دارم یک custom csp بنویسم و سیستم عاملم هم ویندوز XP هست،باید به کدام دستورالعمل موجود در readme عمل کنم و با محتویات کدوم فولدر csp کار کنم(csp موجود در wince یا csp موجود در cspdk )؟
اصلا ویندوز ce چیه و چه کاربردی داره؟

برای اضافه کردن فایل ها به برنامه،از منوی project ،گزینه add to project و بعد files رو انتخاب می کنم و همه فایل های موجود رو اضافه می کنم. درسته؟

در مورد API ،من از CryptoAPI باید استفاده کنم،یعنی API های مربوط به رمز نگاری!
ممکن است بفرمایید چند نوع API داریم و در کجای ویندوز قرار دارند(اگر سوالم درست نیست،تصحیح بفرمایید!)
در ضمن آیا هر API ای، یک فایل lib دارد؟

سوال بعد،در مورد این دو فایل:
Advapi32.lib  Crypt32.libاینها در کجا قرار دارند؟
و اینکه چرا باید در هر دو حالت release و debug آنها را وارد کرد؟
این دو حالت چه فرقی با هم دارند؟

در نهایت اینکه آیا بحث API ها فقط در Visual ++C مطرح است که این تاپیک را به این بخش منتقل کردید؟
در ضمن از فولدری که آماده کردید بسیار ممنونم ولی چون من کامپایلر 2005 یا 2008 ندارم،نتوانستم آن را کامپایل کنم،ولی چون شما توانستید کامپایل کنید،فایل csp-dll.dll تولید شد!
ولی من با اجرای تمام دستورالعمل هایی که در پستتان نوشته بودید،باز هم پس از کامپایل csp.c نه تنها نتوانستم فایل csp.dll را خودم تولید کنم، بلکه با 102 تا ارور و 32 تا وارنینگ مواجه شدم!!!
در این مدت هر چقدر در فروم های msdn و discussion های مایکروسافت و group های گوگل سوالاتم را مطرح کردم،هیچ جوابی نگرفتم تا اینکه با اینجا آشنا شدم!
خواهش می کنم تا حد توان کمکم کنید
باز هم صمیمانه از زحماتتان و وقتی که برای پاسخ می گذارید،متشکرم

----------


## Nima_NF

پاسخ ها:

- شما باید از بازار Visual studio 2005 یا 2008 را تهیه کنید که داخلش ++Visual C نیز هست (جهت اطلاع نسخه 2005  همان ورژن 8 هست و 2009 ورژن 9)، از اینترنت می توانید نسخه express آن ها رایگان دانلود کنید اما با توجه به کامل نبودن آن مشکلات شما بیشتر می شود، پس نسخه تجاری را تهیه کنید.

- Windows CE نسخه کوچکی از ویندوز هست که برای سیستم های تعبیه شده، تلفن های همراه یا PDA ها (تحت نام windows mobile) و سخت افرارهای مختلف استفاده می شود، کدنویسی های آن مانند سایر ویندوزها هست اما با کمی محدودیت ها. که شما به آن احتیاجی ندارید.

- در مورد VC++‎6 دقیق یادم نمی آید، ولی بله همین هست. بعد از اضافه شدن باید تمامی فایل ها را در پنجره solution explorer ببینید.

- وقتی نسخه های جدید کامپایلر  را نصب کردید همراه آن MSDN را نیز نصب کنید، این مرجع شماست و بدون آن برنامه نویسی تقریبا غیر ممکن است.
هرگاه از تابعی می خواهید استفاده کنید، مثلا یکی از توابع CryptoAPI در زیر آن صفحه در MSDN نوشته شده است که هدر فایل آن چیست و چه lib را باید به linker اضافه کنید.
اکثر توابع مرسوم به طورخودکار lib آن ها متصل می شود و نیازی به وارد کردن دستی نیست، در سایر موارد نیاز به اضافه کردن هست (هر دسته ای از توابع که یک dll در ویندوز دارد یک lib هم دارد).

-دو فایل lib در کامپایلر شما (اینجا ++Visual C) در فولدر include داخل محل نصب کامپایلر وجود دارد، از همانجا بر می دارد.

- release زمانی هست که می خواهید فایل اجرایی یا dll نهایی خود را کامپایل کنید و سپس از آن در سایر سیستم ها نیز استفاده کنید.
debug فقط برای یافتن خطا هاست و نسخه ای است که در کامپیوتر شما کار می کند.




> در نهایت اینکه آیا بحث API ها فقط در Visual ++C مطرح است که این تاپیک را به این بخش منتقل کردید؟


خیر
معمولا مباحث Win32 API را به این بخش منتقل می کنم تا مطالب مفیدتر در این بخش جمع شود، نه لزوما به خاطر ++VC .
ضمنا برای ویندوز بهترین کامپایلر مخصوصا برای این کارها همین ++Visual C هست، در سایر کامپایلرها دردسرهای زیادتری خواهید داشت.




> ولی من با اجرای تمام دستورالعمل هایی که در پستتان نوشته بودید،باز هم پس از کامپایل csp.c نه تنها نتوانستم فایل csp.dll را خودم تولید کنم، بلکه با 102 تا ارور و 32 تا وارنینگ مواجه شدم!!!


همه موارد را انجام دادید، به جز اولین آن را، یعنی تهیه نکردن نسخه جدید کامپایلر VC.
هر وقت تهیه کردید پروژه را که انجام دادید فایل های اضافی را پاک کنید تا حجم پروژه کم شود (در این لینک توضیح داده شده است) و zip شده آن را upload کنید تا اشتباهات شما را بگم(اگر حل نشده باشد).

----------


## bizmit

ضمن عرض سلام و تشکر مجدد
سوالام این دفعه هم زیاده،باید ببخشید!
ولی از طرفی این تاپیک میتونه برای کسایی که می خوان یه csp رو develop کنن یا یه custom csp بنویسن،مرجع مفیدی باشه،چون استفاده از CSP خیلی میتونه کاربردی باشه!


پروژه ام رو شرح می دم:
من اول باید یه برنامه کاربردی بنویسم که مثلا یه داده ای رو از کاربر بگیره(که اینو با mfc می خوام بنوسیم) و اونو بده به custom csp (همون csp که من قراره بنویسم که در واقع قالبش همونیه که تو csp.c هست فقط من باید الگوریتم رمزنگاری رو انتخاب و با استفاده از توابع cryptoAPI به CSPاضافه کنم) یعنی در واقع با فراخونی custom csp داده رو رمز گذاری کرده و جفت کلید و کانتینرها رو تولید کنه و بعد اونها رو بده به یه wrapper و این wrapperکه یه برنامه کاربردی هستش،بتونه دستورات رمزنگاری مثل key Gen ،Enc و Dec رو بگیره و هر کدوم رو به یه APDU (که قالب داده های کارت هوشمند هستش)تبدیل کنه و بعد اونها رو بده به مینی درایور کارت(Card  Module ) و این مینی درایور داده های رمزی رو به کارت بفرسته و مثلا با استفاده از کلید خصوصی اونها رو رمز گشایی کنه و جواب رو در قالب APDU بده به Wrapper و بعد از اینکه تبدیل عکس صورت گرفت،از طریق برنامه کاربردی (همون mfc ) نتیجه رو به کاربر نشون بده.

-حالا بعد از اینکه custom CSP نوشته شد،باید  Entry های اون رو به رجیستری وارد کرد یعنی در واقع اون رو به رجیستری شناسوند که این کار با نمونه برنامه CSPinstal که در بسته cspdk موجوده باید صورت بگیره و بعد با استفاده از برنامه testcsp یه جوری csp رو موقتا امضا کرد که ویندوز اونو قبول کنه و در واقع یه جوری بشه که این csp رو کنار csp های دیگه که در ویندوز xp موجوده و در رجیستری(HLOCAL-MACHINE ....) قرار دارن،دید.
نمی دونم شما تونستین بعد از کامپایل  CSP ، اون رو در رجیستری ببینین یا نه؟ البته تو readme گفته که فایل csp.dll و چند تا فایل دیگه رو در پوشه windows/system32 کپی کنیم تا برنامه testcsp اون کار کنه!
حالا من فکر می کنم برنامه cspinstal اونو به طور کامل به رجیستری میشناسونه،مثل اینکه وقتی برنامه ای مثلا آکروبات ریدر رو در ویندوز نصب می کنیم،باید بعضی از مشخصات و پارامترهای اون در رجیستری ویندوز وارد بشه تا برنامه کار کنه.
در ضمن آیا خود برنامه کارت ماژول که اون هم باید بصورت dll باشه،بصورت آماده هستش که دیگه نیازی نباشه برنامه اون رو هم بنویسم چون نوشتن برنامه ی اون خیلی کار می بره و اشکال زداییش هم مشکله و تازه بعد از اینها ممکنه کاملا استاندارد در نیاد که بتونه با کارت،درست ارتباط برقرار کنه؟(منظورم اینه که نمونه کدش به زیان ++C جایی موجود هست؟)

البته یه بسته به عنوان آپدیت ویندوز با شماره KB909520 با نام Base Smart Card CSP در سایت مایکروسافت موجوده با حجم 600 کیلو بایت،اینم آدرسش:
http://www.microsoft.com/downloads/details.aspx?familyid=e8095fd5-c7e5-4bee-9577-2ea6b45b41c6&displaylang=en
ولی وقتی اون رو نصب می کنم،نمی دونم که کجا نصب میشه و نتیجه رو کجا میشه دید؟!
چون انتظار دارم که تو این بسته یه برنامه با نام Base smartcard CSP باشه که قالب یه CSP ی سخت افزاری(یا CSP  کارت هوشمند) رو داشته باشه که من بتونم الگوریتم رمزنگاری مورد نظرم رو توش وارد کنم و دیگه نیازی به نوشتن اون Wrapper نباشه،یعنی مستقیما بعد از اینکه اون برنامه کاربردی صداش کرد،داده رو رمز کنه و به قالب APDU تبدیل کنه و بده به کارت ماژول(یا همون درایور کارت هوشمند) و بقیه عملیات انجام بشه... ولی محتویات این فایل EXE رو نمی دونم کجا باید ببینم که دیگر محتویاتش هم باید PIN Tool.exe و فایل هدر cardmod.h و ... باشه!(لطفا در این مورد هم راهنمایی بفرمایید که محتویاتش بعد از نصب کجا می ره؟)

و در نهایت اینکه من اون برنامه کاربردی رو که با mfc نوشتم( به صورت یه GUI  که داده رو از کاربر بگیره و بعد از رمزگذاری و رمز گشایی اون به کاربر برگردونه) چون می خوام تو کامپیوترهای دیگه اجرا بشه،از اول release mode رو باید انتخاب کنم دیگه؟
خوب در این صورت برای اشکال زدایی یا debug برنامه مشکلی پیش نمی یاد یا اینکه باید در هر دو حالت کامپایل کنم و فقط نسخه release رو بردارم تا در کامپیوترهای دیگه هم اجرا بشه؟

و خواهش پایانیم اینه که اگر نمونه کدهای آماده ای در این زمینه ها مثل wrapper ،کارت ماژول و ... به زبان ++C سراغ داشتین،لطفا معرفی کنید(البته لازم به ذکر است که من به قوانین اینجا واقفم و اصلا قصدم درخواست کد آماده و انجام پروژه نیست فقط نیاز شدیدی به کمک و راهنمایی دارم و اگر نمونه کد آماده ای باشد،فقط بخشی ازکارم راحتتر می شه و الا آن کدهای آماده را باید خودم customize کنم و چیزهای دیگری به آنها اضافه کنم)

امیدوارم حوصله کنید و پس از خواندن این مطالب،تا حد ممکن کمک کنید
طبق فرمایش شما فردا قصد تهیه visual studio 2008 +MSDN را دارم که بعد از کامپایل نتیجه را به شما اعلام می کنم!

نهایتا از صمیم قلب آرزوی موفقیت روز افزون رو از پروردگار برای شما مدیر محترم  دارم و امیدوارم همیشه اینطور منشاء خیر و کمک برای دیگران باشید
با تشکر

----------


## Nima_NF

تا جایی که در دانش من باشد به سوالات پاسخ می دهم:



> البته تو readme گفته که فایل csp.dll و چند تا فایل دیگه رو در پوشه windows/system32 کپی کنیم تا برنامه testcsp اون کار کنه!


فکر نمی کنم برای ویندوز XP به بالا به جز csp.dll نیاز به جایگزین کردن فایل های Dll دیگر در system32 باشد.
وقتی csp.dll کپی شد با regsvr32.exe باید بتوان آن را از طریق cmd رجیستر کرد. 




> اگر نمونه کدهای آماده ای در این زمینه ها مثل wrapper ،کارت ماژول و ... به زبان ++C سراغ داشتین،لطفا معرفی کنید





> منظورم اینه که نمونه کدش به زیان ++C جایی موجود هست؟


اطلاع ندارم، ضمن اینکه آشنایی چندانی نیز با smart card ها ندارم.
در هر حال با توجه به تعداد کاربران کم آن در دنیا، حتی در مراجع فوق معتبر منابع کمی وجود دارد.




> ولی وقتی اون رو نصب می کنم،نمی دونم که کجا نصب میشه و نتیجه رو کجا میشه دید؟!


چند dll در ویندوز را که برای کار با smart card هستند به همراه رجیستری آن ها را update می کند مانند Basecsp.dll و Basecsp.dll و ... کلا بسته ای تولید نمی کند.
http://support.microsoft.com/kb/909520




> خوب در این صورت برای اشکال زدایی یا debug برنامه مشکلی پیش نمی یاد یا اینکه باید در هر دو حالت کامپایل کنم و فقط نسخه release رو بردارم تا در کامپیوترهای دیگه هم اجرا بشه؟


تا زمانی که در حال تست و تکمیل برنامه هستید از همان debug استفاده کنید و هرگاه برنامه تکمیل شد فایل نهایی را با حالت release (یعنی همان نسخه نهایی) کامپایل کنید.

----------


## bizmit

سلام و تشکر
ببخشید در مورد رجیستر کردن آن با regsvr32.exe   از cmd ،تونستم csp.dll موجود در بسته cspdk رو رجیستر کنم،یعنی پیغام داد که رجیستر شد. 
حالا می خوام ببینم آیا بعد از اجرای کد cspinstl  موجود در بسته، یک registery entry تولید میشه یا نه،منظورم از رجیستری entry ، یه هم چین فایلیه:


و آیا بعد از وارد کردن csp.dll به رجیستری، میشه اون رو در لیست رجیستری (H-LOCAL-MACHINE ....) دید؟
در مورد اون Base csp هم من فکر می کردم سورس کدشو در اختیارمون میذاره که بتونیم customize  اش کنیم!
به هر حال.... 
میشه بفرمایین شما بعد از نصب kb909520 ، فایل base csp تون update شد؟
و اینکه آیا قبل از نصب این فایل exe ، هم چین dll ای در system32 موجود است یا بعد از نصب ایجاد میشه؟
ممنون میشم تا امشب پاسخ بدین

----------


## Nima_NF

در مورد سوال اول درباره  cspinstl،شرمنده اخیرا شدیدا سرم شلوغ هست و وقت ندارم مراحل  را انجام بدم یا تست کنم.




> و آیا بعد از وارد کردن csp.dll به رجیستری، میشه اون رو در لیست رجیستری (H-LOCAL-MACHINE ....) دید؟


بله در مسیر زیر :
SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provi  der
 

- در مورد kb909520 من اصلا آن را دانلود نکردم یا نصب نکردم، چون ویندوز من update شده است (XP sp3 و update روز) و این Update قبلا انجام شده و فایل های آن هم جدید هستند. پس بلکه وجود دارند. این موارد که با K و سپس شماره مشخص می شوند فقط برای رفع مشکلات و update کردن هستند.

- ضمنا من یک اشتباهی در پروژه ای که در پست 4 گذاشتم کرده بودم، که آن را دوباره upload کردم و از آن استفاده کنید که رجیستر هم می شود، فلگ DEF/ را تعریف نکرده بودم، به همین خاطر هیج تابعی export نشده بود.
شما باید فلگ DEF/ را در بخش linker تعریف کنید (با نام dll مورد نظر)

- نکته ای که امروز دیدم این بود که در فایل autoreg.cpp یک فلگ شرطی تعریف شده است با نام SCARD_CSP که اگر در بالای فایل آن را تعریف کنید (deF#‎)، رجیستر dll برای smart card کامپایل می شود.

----------


## bizmit

سلام
- ببخشید اگه ممکنه بفرمایید فرق load-time dynamic linking با run-time dynamic linking چیه؟
توضیحات موجود در msdn رو دیدم،ولی ظاهرا توی همین برنامه csp ، از load-time linking استفاده شده!
می خواستم ببینم مزیت کدوم یکی بیشتره؟
(البته می دونم که این سوال مربوط به بحث یا تاپیک dll ها میشه ولی چون در راستای این پروژه است و یکی از مباحث اصلی برنامه نویسی رمزنگاری در ویندوزه،اونو اینجا مطرح کردم)

- یه سوال دیگه:
آیا برای ساختن هر فایل dll ، حتما باید یه فایل def. یا h. هم تعریف کرد تا دو تا فایل dll و lib ساخته بشه؟
چه فرقی بین فایل های def. و h.  برای کامپایل و اجرای پروژه های dll هست و کدوم بهتره یا اینکه آیا به هر دو شون نیاز هست؟

- یه سوال دیگه:
اگه من بخوام یه سری توابع به اون نمونه کد قالب csp اضافه کنم،آیا باید هدر فایل و فایل def اش رو هم تغییر بدم؟
اصلا قواعد و دستورات نوشتن یه هدر فایل برای فایل های dll چه جوریه(در این مورد اگه لینکی که هم دستورات رو توضیح داده باشه و هم چند نمونه مثال داشته باشه،معرفی کنین ممنون میشم)

- در ضمن چه جوری میشه دو تا فایل dll رو به هم لینک کرد؟
من تو پروژه ام می خوام فایل custom csp که می نویسم و به صورت dll هست،بتونه فایل کارت ماژول رو (که اون هم یه  dll هستش که قراره بنویسم) صدا بزنه تا از توابعش استفاده کنه؟

و یه سوال دیگه اینکه:
آیا بهتره که من custom csp و card module رو با هم ترکیب کنم و هر دو در قالب یک dll ، توسعه بدم(یعنی کدهای مربوط به custom csp و card module رو در یک فایل dll بنویسم) یا اینکه دو تا dll مجزا باشه؟

(البته من توضیحات مربوط به dll در تالارهای مربوطه رو که قبلا معرفی فرمودین،کامل نگاه کردم ولی این سوال هایی که در مورد dll پرسیدم،در اونها مطرح نشده بود)

ممنون میشم اگه مثل همیشه راهنمایی کنید

----------


## Nima_NF

بهتر هست اگر سوالات متفاوتی دارید در تاپیک های جداگانه مطرح کنید، تا در آینده اگر کسی سوال پرسید بتوانیم به آن ارجاع دهیم.
(مثل کل سوالات پست قبلی شما که همگی سوالات عمومی برای dll ها هست و خلاف قوانین محسوب می شود)
در هر حال اگر برای سوالات شماره بزنید راحت تر می توان پاسخ داد.

برای حالت load-time شما باید فایل .lib و .h را داشته باشید ( lib همراه dll تولید می شود و آدرس های توابع را در خود دارد)
به این شکل به راحتی با اضافه کردن فایل lib به لینکر در تنظیمات پروژه خود می توانید از توابع استفاده کنید. به این شکل در کل سیستم هم حافظه کمتری
اما در حالت  باید خودتان dll را لود کنید با LoadLibrary  و آدرس هر تابع را با GetProcAddress تک تک بدست آورید و از آن استفاده کنید. پس تا زمانی که سورس کد پروژه دست شما است از همان load-time استفاده کنید.
و مزایا و معایب دیگر که زیاد هستند.

فایل def هم برای این هست که دردسر شما از بابت export توابع به dll کمتر شود و نیاز نباشد تک تک در کنار توابع (declspec (dllexport__ را بنویسید.
در بعضی از پروژه ها نیز تعریف فایل DEF ضروری هست.

فایل Def را بله، اگر تابع در فایل .h های اصلی csp وجود ندارد (SDK) آن ها را تغییر ندهید، بلکه یک فایل جدید با پسوند .h بسازید و در آن تعریف ها را انجام دهید.
همانطور که گفتم برای حالت load-time نیاز خواهد شد.

استفاده از یک dll در dll دیگر همانند استفاده یک dll در یک برنامه دیگر هست.
در حالت load-time در لینکر .lib را وارد کنید به علاوه اضافه کردن فایل .h در include پروژه.

در مورد سوال آخر هم نظری ندارم.

----------


## bizmit

سلام

1- اگه من بخوام یه سری توابع به اون نمونه کد قالب csp اضافه کنم،(مثلا یه الگوریتم hash یا یه الگوریتم cryptography (رمزنگاری) به اون قالب های تابع cryptoAPI ای که در کد CSP موجوده (همون 23 تا تابع) اضافه کنم،آیا باید هدر فایل و فایل def اش رو هم تغییر بدم؟
البته این سوال رو در پست قبلی جواب دادین،ولی اگه بخوام الگوریتم یا کدهای مربوطه درون تابع های موجود در csp باشه(مثلا درون تابع CPEncrypt )، باز هم نیازی به تغییر def و .h هست؟
1-1- در مورد .h جدید که در پست قبلی فرمودین، آیا اشکالی نداره که یه dll ، دو تا هدر فایل داشته باشه؟

2- به فرض اگه بخوام کدهای پایین رو به csp اضافه کنم و نتیجه رو ببینم،یعنی اینکه یه برنامه کاربردی داشته باشم که  csp.dll رو صدا بزنه و یه سری داده واسش بفرسته (داده به عنوان ورودی csp) و ازش بخواد اون داده ها رو با الگوریتم AES رمزگذاری کنه و کلید های رمزنگاری رو تولید کنه(چون خروجی csp ، کلیدهای رمزنگاری(عمومی-خصوصی) هستش) و نتیجه رو برای همون برنامه کاربردی فراخوان بفرسته، آیا این کار قابل انجامه؟
راستش من می خواستم ازتون خواهش کنم بخش های لازم این کدها رو به اون نمونه کد csp اضافه کنین و دوباره csp (که حالا custom شده) رو کامپایل کنین(توابعی که باید کدهای رمزنگاری یا hash بهشون اضافه بشه،از اسمشون معلومه،منظورم همون 23+2 تابعی هست که در فایل def لیست شدن) و ببینین dll اش تولید میشه تا برنامه کاربردی من بتونه صداش کنه و ازش استفاده کنه!

راستش من این کار رو کردم ولی توی کامپایل دچار مشکل شدم،اگه شما لطف کنین این کار رو انجام بدین، از عملکرد درست این کار مطمئن میشم،

این برنامه، کد الگوریتم AES (یه الگوریتم رمزنگاری در ویندوز) هستش:
http://www.hotshare.net/file/106277-7719739402.html


اینم برنامه مربوط به الگوریتم SHA که یه الگوریتم hashing هستش!
http://www.hotshare.net/file/106807-525254763a.html


با تشکر

----------


## bizmit

ببخشید یه سوال دیگه!
دستور 
extern "C" {
}
که تو هدر فایل csp یا همون cspdk.h موجوده،به چه معناست؟
ممنون

----------


## Nima_NF

1- چیز اصلا پیچیده ای نیست، این موضوع اصول اولیه برنامه نویسی هست : یعنی اگر تابعی می خواهید بنویسید، در بالای آن قبل از main باید قالب تابع را تعریف کنید.
حال اگر تابع جدید می خواهید تعریف کنید و قبلا هدر آن تعریف نشده است پس خودتان در یک فایل .h باید قالب را تعریف کنید، اگر هم فقط می خواهید محتوای داخلی تابع کنونی مانند CPEncrypt را تغییر دهید به شرط اینکه پارامترهای ورودی - خروجی تغییر نمی کنند، چون قبلا در .h تعریف شده هست دیگر نیازی به تعریف مججد نیست. مگر اینکه تصمیم بگیرید که کلا قالب تابع (آرگومان ها) را تغییر دهید.

1-1- خیر هر تعدادی می تواند باشد، وقتی آن را با include به فایل cpp اضافه می کنید مثل این هست که همه محتوای آن فایل .h در همان قسمت فایل کپی می شود.
شاید این هدر فایل ها در SDK کامپایلر کسی وجود داشته باشد و به این شکل با تغییر آن دو هدر فایل مشابه (با دو تعریف مشابه) خواهید داشت که مشکل ایجاد می کند.

2-  دو سورس کدی که قرار دادید الگوریتم ها را در داخل یک برنامه به شکل sample نوشته اند. شما باید اگوریتم ها را از داخل فایل Main جدا کنید و و داخل تابع استفاده کنید.
متوجه نشدم که می خواهید آن ها را داخل کدام تابع در csp.dll بنویسید، در تابعی جدید؟ یا ...

با توجه به اینکه من اطلاع زیادی از کاری که شما می خواهید انجامد دهید ندارم و تا 2 هفته آینده هم اصلا وقت آزاد ندارم، شما لطف کنید خودتان کارهای لازم را انجام دهید و هر جایی که پروژه اشکال دارد مطرح کنید، یا مثلا پروژه نیمه کامل خود را جایی upload کنید تا آن را بررسی کنم و اشکالاتش را بگوییم که وقت زیادی هم از من نگیرد.

3- extern C برای مواقعی هست که می خواهیم کدهایمان قابل استفاده در هر دو C و ++C باشد. 
برای dll ها هم در مورادی که از فایل DEF استفاده نمی شود حتما باید به کار ببریم تا عناوین توابع هنگام export به Dll تغییر نکند.

----------


## bizmit

سلام
ببخشید من یه پروژه دارم که قبلا در زبان ++VC ورژن 2005 کامپایل شده و حالا که من می خوام توی 2008 کامپایلش کنم،(بعد از تبدیل اون به برنامه سازگار با 2008 ) که خود نسخه 2008 به صورت ویزارد اینو انجام میده،بعد از کامپایل این ارورها رو می بینم:
------ Build started: Project: SimplePCSC, Configuration: Debug Win32 ------
Linking...
LINK : warning LNK4076: invalid incremental status file '.\Debug/SimplePCSC.ilk'; linking nonincrementally
LINK : fatal error LNK1207: incompatible PDB format in 'f:\Csp Thesis\Rezaei 87_10_24\PCSC sample code\SimplePCSC with SAM on ACG\Debug\SimplePCSC.pdb'; delete and rebuild
Build log was saved at "file://f:\Csp Thesis\Rezaei 87_10_24\PCSC sample code\SimplePCSC with SAM on ACG\Debug\BuildLog.htm"
SimplePCSC - 1 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

به نظرتون چی کار باید انجام بدم؟
برنامه هم یه برنامه ساده PCSC هست که از کتابخونه WINSCARD.DLL (یا همون ویندوز اسمارت کارت) برای ارتباط با کارت هوشمند استفاده می کنه(به زبان ویندوزی هم هست!)
اگه لازم می دونید، برنامه رو بعدا آپلود کنم

با تشکر

----------


## Nima_NF

قبل از کامپایل ابتدا از طریق گزینه clean project در منوی build کدهای کامپایل شده قبلی را پاک کنید و سپس دوباره کامپایل کنید. (یا می توانید به صورت دستی نیز فولدرهای debug و release را پاک کنید.)

----------


## bizmit

سلام
من تازه 2008 ++VC رو نصب کردم؛
در مورد کامپایل اون نمونه کد CSP ، ابتدا *دقیقا* تمام مراحلی رو که توی MSDN در صفحه ای با عنوان 
Creating and Using a Dynamic Link Library (C++‎)
نوشته دنبال کردم ولی با اون روش، فقط فایل csp.dll رو می ساخت و فایل lib اش رو نمی ساخت!

پس معلوم میشه که برای کامپایل اون نمونه کد، باید یه پروژه از نوع dll درست کنم و فایل های موجود در پوشه csp رو بهش add کنم تا نتیجه درستی بگیرم!

1- می خواستم ازتون خواهش کنم اگه ممکنه دقیقا تمام مراحلی که برای کامپایل csp اجرا کردین رو به صورت تیتروار(یعنی با شماره) بیان کنین تا من هم همون کارها روانجام بدم!

و یه سوال؟
2- اینکه چرا با روشی که توی اون صفحه msdn توضیح داده(یعنی فقط اضافه کردن csp.c و cspdk.h ، چون برای ایجاد یک dll فقط به سورس و هدرش نیاز هست!) فایل lib تولید نمی شد؟

اگه لازم می دونید توضیحات اون صفحه msdn رو بذارم؟!

ممنون

----------


## Nima_NF

یعنی همه مطالبی که تا حالا توضیح دادم دوباره بگم !!!


اگر فایل DEF ساخته نمی شود یعنی اینکه اشتباهی انجام دادید و تابعی export نمی شود که lib برایش ساخته شود. احتمالا همان فلگ DEF 


1- طبق همان مقاله  یک پروژه win32 apllication بسازید، در wizard ظاهر شده با زدن Next نوع پروژه را به dll تغییر دهید. (از application project)، پروژه را نیز حتما خالی تعریف کنید. (empty را تیک بزنید)

2- همه فایل های موجود در فولدر نمونه CSP را به پروژه اضافه کنید. res. sys . h . cpp c و ...

3- فایل های فولدر sdkinc  را به برنامه اضافه نکنید، مسیر آن را به option اضافه کنید:




> Tools -> Option - > project and solution -> VC++‎ Directories



با include files و source files دو فایل موجود در فولدر sdkinc را اضافه کنید. تا توسط پروژه شناخته شوند.
 
4- سوییچ DEF را تعریف کنید:



> ضمنا من یک اشتباهی در پروژه ای که در پست 4 گذاشتم کرده بودم، که آن را دوباره upload کردم و از آن استفاده کنید که رجیستر هم می شود، فلگ DEF/ را تعریف نکرده بودم، به همین خاطر هیج تابعی export نشده بود.
> شما باید فلگ DEF/ را در بخش linker تعریف کنید


از منوی project و سپس در properties پروژه (هم برای debug هم برای release) در قسمت linker در input در فیلد Modual definition file نام فایل def را بنویسید مثلا  csp.def
(نمونه من را در حالت release نگاه کنید)

پروژه را کامپایل کنید.

برای اینکه ببینید dll تابعی دارد یا نه از Dependency Walker استفاده کنید.

در مورد سوال 2، اگر لینک مقاله را دارید بزارید تا ببینیم، مقاله عمومی با این عنوان برای dll هست ولی ندیدم که برای ساخت csp هم توضیحی باشد.

----------


## bizmit

با سلام و تشکر



> یعنی همه مطالبی که تا حالا توضیح دادم دوباره بگم !!!


می دونم تا حالا خیلی زحمت کشیدین و بسیاری از مشکلاتم با راهنماییهای خوب شما حل شده ولی چون ویژوال استودیو 2008 رو تازه نصب کردم و قبلا از ورژن 6 استفاده می کردم، باهاش زیاد آشنا نیستم، به خاطر همین به مشکل برخوردم و دوباره پرسیدم،به هر حال باید ببخشید.
و ممنون از راهنمایی مجددتون!




> در مورد سوال 2، اگر لینک مقاله را دارید بزارید تا ببینیم، مقاله عمومی با این عنوان برای dll هست ولی ندیدم که برای ساخت csp هم توضیحی باشد.


اینم لینک مقاله:
http://msdn.microsoft.com/en-us/library/ms235636.aspx
همانطور که فرمودین، برای ساخت csp توضیحی وجود نداره، این مقاله ، یک دستورالعمل عمومی برای ساخت یک نمونه کد DLL هست و چون CSP هم باید به صورت DLL کامپایل می شد، من اول این دستورالعمل رو اجرا کردم( که به مشکل هم برخوردم!)

یه سوال دیگه هم از حضورتون داشتم:

من نیاز  به " Platform Builder SDK " دارم که مربوط به ویندوز ce هست و توضیحاتش هم در msdn موجوده،مثلا در این صفحه:
http://msdn.microsoft.com/en-us/library/ms834394.aspx

تو اینترنت گشتم تا یه لینک دانلود ازش پیدا کنم ولی چون پولیه، هیچ لینکی پیدا نکردم!
من به یکی از sample code های موجود در این بسته با عنوان "scwcsp " که در بخش: 
%_WINCEROOT%\Public\Common\Sdk\Samples directory
قرار داره، نیاز دارم،
می خواستم بپرسم می تونم این بسته رو تو بازار پیدا کنم ، یعنی CD اون تو بازار موجوده که برم بخرم؟
(شما اطلاعی در مورد این بسته دارید؟)

بسیار ممنون میشم اگه در این خصوص کمک کنید

----------


## Nima_NF

فکر نمی کنم چنین چیز کمیابی در بازار موجود باشه...

در هر حال تا چند ماه می توانید از نسخه Trial استفاده کنید، این نسخه را دریافت کنید شاید فعلا به کارتان آمد:
http://www.microsoft.com/windowsembe...s/default.mspx

----------


## bizmit

سلام
ببخشید یه سوال در مورد یه تابع ویندوزی داشتم؛
توی همون نمونه کد csp ، یه تابعی هست بنام "CPAcquireContext " که ساختارش به این شکله:
BOOL  WINAPI CPAcquireContext(
    OUT HCRYPTPROV *phProv,
    IN  LPCSTR szContainer,
    IN  DWORD dwFlags,
    IN  PVTableProvStruc pVTable)

متغیر چهارمش یه اشاره گر به یک ساختار هستش، یعنی "PVTableProvStruc " اشاره گری به ساختار "VTableProvStruc " هستش که تعریفش به شکل زیره:
typedef struct VTableProvStruc 
{  DWORD Version; 
 FARPROC FuncVerifyImage; 
 FARPROC FuncReturnhWnd;  
DWORD dwProvType;  
BYTE* pbContextInfo;  
DWORD cbContextInfo;  
LPSTR pszProvName;
} VTableProvStruc,  *PVTableProvStruc;

حالا متغیر سوم این ساختمان یعنی "FuncReturnhWnd " به این صورت تعریف میشه:
void FuncReturnhWnd(
  [in, out]            HWND* phWnd
);

که csp اونو برای گرفتن یه دستگیره ی پنجره ای که باید از اون به عنوان پدر(parent ) یا مالک (owner ) هر UI ای که نمایش داده میشه، استفاده کنه، بکار می گیره.

متغیر phWnd در این تابع، آدرس یک متغیر "HWND " هست که دستگیره پنجره پدر رو دریافت می کنه!


حالا سوالم اینجاست که آیا مثالی از بکارگیری این متغیر وجود داره؟

یعنی می خواستم ببینم آیا یه کد نمونه ای از طرز استفاده از این متغیر هست و آدرس یه متغیر "HWND " چه جوری باید باشه و آیا در خروجی، واقعا یه پنجره نشون میده؟

با تشکر

----------


## bizmit

سلام
من توی msdn ، مثالی پیدا کردم که یه نمونه کد هستش که از HWND استفاده می کنه و به طور کلی، یه برنامه ی ویندوزی هست که کدش به صورت زیره:
#include <windows.h>

HINSTANCE g_hInst = NULL;     // Handle to the application instance
HWND g_hwndMain = NULL;       // Handle to the application main window
TCHAR g_szTitle[80] = TEXT ("Main Window"),    
                              // Application main window name
      g_szClassName[80] = TEXT ("Main window class");  
                              // Main window class name
                
/**************************************************  *********************

FUNCTION: 
  WndProc

PURPOSE: 
  The callback function for the main window. It processes messages that
  are sent to the main window.

**************************************************  *********************/
LRESULT CALLBACK WndProc (HWND hwnd, UINT umsg, WPARAM wParam, 
                          LPARAM lParam)
{
  switch (umsg)
  {
    // Add cases such as WM_CREATE, WM_COMMAND, WM_PAINT if you don't 
    // want to pass these messages along for default processing.

    case WM_CLOSE:
      DestroyWindow (hwnd);
      return 0;

    case WM_DESTROY:
      PostQuitMessage (0);
      return 0;
  }

  return DefWindowProc (hwnd, umsg, wParam, lParam);
}

/**************************************************  *********************

FUNCTION: 
  InitInstance

PURPOSE: 
  Create and display the main window.

**************************************************  *********************/
BOOL InitInstance (HINSTANCE hInstance, int iCmdShow)
{

  g_hInst = hInstance;
  
  g_hwndMain = CreateWindow (
                  g_szClassName,  // Registered class name         
                  g_szTitle,      // Application window name
                  WS_OVERLAPPED,  // Window style
                  CW_USEDEFAULT,  // Horizontal position of the window
                  CW_USEDEFAULT,  // Vertical position of the window
                  CW_USEDEFAULT,  // Window width
                  CW_USEDEFAULT,  // Window height
                  NULL,           // Handle to the parent window
                  NULL,           // Handle to the menu the identifier
                  hInstance,      // Handle to the application instance
                  NULL);          // Pointer to the window-creation data

  // If it failed to create the window, return FALSE.
  if (!g_hwndMain)
    return FALSE;

  ShowWindow (g_hwndMain, iCmdShow);
  UpdateWindow (g_hwndMain);
  return TRUE;
}

/**************************************************  *********************

FUNCTION: 
  InitApplication

PURPOSE:
  Declare the window class structure, assign values to the window class
  structure members, and register the window class.

**************************************************  *********************/
BOOL InitApplication (HINSTANCE hInstance)
{
  WNDCLASS wndclass;

  wndclass.style = CS_HREDRAW | CS_VREDRAW;
  wndclass.lpfnWndProc = (WNDPROC)WndProc;
  wndclass.cbClsExtra = 0;
  wndclass.cbWndExtra = 0;
  wndclass.hIcon = NULL;
  wndclass.hInstance = hInstance;
  wndclass.hCursor = NULL;
  wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
  wndclass.lpszMenuName = NULL;
  wndclass.lpszClassName = g_szClassName;
  
  return RegisterClass (&wndclass);
}

/**************************************************  *********************

FUNCTION: 
  WinMain

PURPOSE: 
  The WinMain function of the application. It is called by the system as
  the initial entry point for this Windows CE-based application.

**************************************************  *********************/
int WINAPI WinMain (
               HINSTANCE hInstance,     // Handle to the current instance
               HINSTANCE hPrevInstance, // Handle to the previous instance
               LPWSTR lpCmdLine,        // Pointer to the command line
               int iCmdShow)            // Shows the state of the window
{
  MSG msg;                             // Message structure
  HACCEL hAccel;                       // Handle of the accelerator 
                                      // table
    

// Use this code to prevent your application from starting twice
// assuming that your application has not changed its window text
if (FindWindow(g_szClassName, g_szTitle)){
   SetForegroundWindow(FindWindow(g_szClassName, g_szTitle));
   return FALSE;
}
  

  if (!hPrevInstance)
  {
    if (!InitApplication (hInstance))
      return FALSE; 
  }

  if (!InitInstance (hInstance, iCmdShow))
    return FALSE;
  
  // Insert code here to load the accelerator table.
  // hAccel = LoadAccelerators (...);
  
  while (GetMessage (&msg, NULL, 0, 0))
  {
    if (!TranslateAccelerator (
                    g_hwndMain,     // Handle to the destination window
                    hAccel,         // Handle to the accelerator table
                    &msg))          // Address of the message data
    {
      TranslateMessage (&msg);
      DispatchMessage (&msg);
    }
  }
  
  return msg.wParam;
}

وقتی که من این کد رو در ویژوال استودیو 2008 کامپایل می کنم، این ارور رو میده:

------ Build started: Project: window example, Configuration: Debug Win32 ------
Compiling...
1.cpp
d:\window example\1.cpp(119) : error C2731: 'WinMain' : function cannot be overloaded
        

window example - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

میشه خواهش کنم بفرمایید چه طوری باید این ارور رو رفع کنم؟
ممنون

----------


## Nima_NF

قطعه کد فوق ساده ترین برنامه win32 هست که چیز خاصی نیست و نیاز نیست خودتان بنویسید، یک پروژه win32 project جدید بسازید (آن را empty نکنید) وقتی پروژه را بسازید همین برنامه با این کدها را برایتان می سازد.


در هر حال اگر می خواهید همین برنامه فوق کار کند بخش WinMain  را به شکل زیر تغییر دهید:

int WINAPI WinMain( 
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int iCmdShow
)
ضمنا از TranslateAccelerator استفاده نکردید پس آن را نیز باید پاک کنید. (کلا به این شکل برنامه ناقصی هست)

----------


## bizmit

سلام
ببخشید شما تا حالا از کتابخانه "++Crypto " که یک کتابخانه برای پیاده سازی اعمال رمزنگاری هست، استفاده کردین؟

با تشکر

----------


## Nima_NF

خیر چون تا کنون نیاری به استفاده از این موارد در سایر پلتفرم ها نداشتم

----------


## bizmit

سلام
من در اون فایل CSP ای که شما زحمت کشیدید و کامپایل کردید، یک دیالوگ MFC به نام CSPCaller درست کردم و اون رو به همین پروژه اضافه کردم و قصدم این است که برنامه CSPCaller ، توابع موجود در CSP را صدا بزنه( یعنی توابع این DLL رو صدا بزنه!)
مثلا یک دکمه در دیالوگ به نام CPAcquireContext(یکی از توابع کد CSP ) قرار دادم که اگر کاربر این دکمه رو فشار داد، در تابع مربوط به این دکمه در برنامه CSPCaller ، این تابع از CSP.dll فراخوانی بشه!
البته نباید از بیرون محتویات CSP رو دید(منظورم دسترسی به متغیرهای داخلی و ... هست!)
فقط من می خوام کد CSP یه فرم داشته باشه که در هر تابعی لازم شد، از کاربر درخواست PIN کنه!
یعنی اینکه علاوه بر دیالوگ CSPCaller ، یه دیالوگ دیگه هم واسه csp ایجاد بشه که در خواست PIN کنه!
عکس دیالوگ CSPCaller به این صورته:


مثلا تو این دیالوگ، وقتی من دکمه "CPSignHash " رو فشار میدم، تابع متناظر با این دکمه در برنامه CSPCaller باید همین تابع رو در CSP.C فراخوانی کنه و چون این تابع موجود در CSP ، برای عملکردش نیاز به کلید موجود روی کارت داره، قبلش باید PIN وارده توسط کاربر رو بررسی کنه!

پس یعنی هر وقت این دکمه فشار داده شد، یه دیالوگ یا فرم به کاربر نشون داده بشه که در اون درخواست PIN میکنه و این فرم باید مربوط به خود csp.c باشه نه CSPCaller !
عکس بخش solution explorer پروژه من به صورت زیره:





اگه من بخوام اون فرم رو برای فقط csp (نه cspcaller ) درست کنم،باید روی بخش csp در solution explorer کلیک راست کنم و گزینه Add New Item رو انتخاب کنم و بعد از category ی UI ، یه Windows form ایجاد کنم و توش بنویسم که PIN وارد بشه و در واقع از این طریق، داده مربوط به PIN ، مستقیما وارد کد csp بشه!

1-حالا سوالم اینه که آیا این کار درسته؟ (آخه من تا حالا نه فرمی ایجاد کردم و نه توی پروژه ای دو تا دیالوگ داشتم، مثل اینجا که قراره یه دیالوگ واسه CSPCaller و یه دیالوگ (یا همون فرم ) برای csp باشه!)

2-اصلا به نظر شما برای این کار من باید windows form ایجاد کنم یا user control ؟
(با توجه به اینکه csp.c قراره که یه DLL باشه و کسی به محتویات اون دسترسی نداشته باشه،یعنی محتویاتش برای کسی مانیتور نشه!)

3- فرق ویندوز فرم و دیالوگ چیه؟

4- من می خوام که هر وقت  چند تا تابع که نیاز به PIN داشتن، در دیالوگ CSPCaller فراخوانی شدن، این فرم(مربوط به وارد کردن PIN ) ظاهر بشه!
این کار چه طوری ممکنه؟
 یعنی مثلا من در کد تابع "CPSignHash " که در csp.c موجوده، چه طوری ابتدای کد تابع، بهش بفهمونم که اول اون فرم رو به کاربر نشون بده؟(یعنی چه دستوری رو در ابتدای کد تابع بذارم که اون فرم رو نمایش بده و داده PIN رو بگیره؟)

5- در ضمن آیا اختصاص یه متغیر به نام PIN که از کاربر درخواست میشه، به windows form مثل دیالوگ MFC می مونه؟ (یعنی با Add variable به یه کنترل کادر ویرایش، و بطور کل کار کردن با یه فرم مثل کارکردن با یه دیالوگ MFC هست یا نه؟)


ببخشید که سوالام اینقدر زیاده، آخه تا حالا یه فرم ایجاد نکردم!
با تشکر

----------


## Nima_NF

> اید روی بخش csp در solution explorer کلیک راست کنم و گزینه Add New Item رو انتخاب کنم و بعد از category ی UI ، یه Windows form ایجاد کنم


 Add New Item را انتخاب نمی کنیم، بلکه resource را انتخاب می کنیم تا یک دیالوگ به برنامه اضافه کنیم.

بحث windows form و user control برای کدهای مدیریت شده .Net هست نه MFC، شما هم در اینجا قصد برنامه نویسی دات نت یا ترکیب کدهای کنونی با دات نت را ندارید پس به آن ها کاری نداریم.
 تنها لازم هست که یک dialog به resource همان پروژه (در اینجا پروژه CSP dll ) اضافه کنید.

سپس برای آن یک کلاس از CDialog به ارث ببرید (مثلا CPinDialog ) و هرگاه که می خواهید تابعی از dll را فراخوانی کنید یک تابع مثلا GetPin را اجرا کنید که در آن دیالوگ را به صورت modal اجرا می کند. اگر درست بود برنامه ادامه یابد در غیر این صورت پیام خطا دهد و break کند /یا IDCANCEL برگرداند/ یا از یک متغیر استفاده کنید / ... تا کدهای دیگر اجرا نشود.

در MFC برای نمایش دیالوگ :

CPinDialog  myPinDialog;
myPinDialog.DoModal();

اما از آنجایی که پروژه csp dll شما از نوع win32 هست (نه MFC) و شما هم می خواهید در همان پروژه یک دیالوگ بسازید، باید دیالوگ را نیز به صورت win32 بسازید و فراخوانی کنید:

if (DialogBox(hinst,  MAKEINTRESOURCE(DLG_PINDIALOG), 
              hwnd, (DLGPROC)PinCheckProc)==IDOK) 
{
  // do something
}
و سپس یک تابع PinCheckProc برای پردازش پیام ها بسازید:

BOOL CALLBACK PinCheckProc(HWND hwndDlg, 
                             UINT message, 
                             WPARAM wParam, 
                             LPARAM lParam) 
{ 
    switch (message) 
    { 
        case WM_COMMAND: 
            switch (LOWORD(wParam)) 
            { 
                case IDOK: 
                    // DO something 
 
                case IDCANCEL: 
                    EndDialog(hwndDlg, wParam); 
                    return TRUE; 
            } 
    } 
    return FALSE; 
} 
در کل پیشنهاد می کنم به جای اینکه دیالوگ را در پروژه csp dll بسازید در همان پروژه فراخوانی کننده dll قبل از فراخوانی هر تابع pin را دریافت کنید و سپس در همانجا چک کنید. تابع بررسی pin را فقط در قالب یک تابع فراخوانی و استفاده کنید.

 - open fialog
- get pin
- Check pin (from dll)
- if (pin= true)  function1();  else  showerror



اگر کار با دیالوگ ها را نمی دانید حتما یک کتاب MFC و win32 مطالعه کنید.

----------


## bizmit

با سلام و بی نهایت تشکر
راهنمایی هاتون خیلی کلیدی بود،ممنونم.



> بحث windows form و user control برای کدهای مدیریت شده .Net هست نه MFC، شما هم در اینجا قصد برنامه نویسی دات نت یا ترکیب کدهای کنونی با دات نت را ندارید پس به آن ها کاری نداریم.


بله دقیقا، چون خودم هم یک فرم ایجاد کردم و دیدم با دستوراتش اصلا آشنایی ندارم و در اصل پروژه من هم نباید از دات نت استفاده کنه و فقط باید از رویکرد win32 استفاده کنه!




> Add New Item را انتخاب نمی کنیم، بلکه resource را انتخاب می کنیم تا یک دیالوگ به برنامه اضافه کنیم.


من کارهایی که کردم رو به صورت مرحله به مرحله و تصویری می گذارم به سه دلیل:
1-	شما تایید بفرمایید که کارهایی که کردم درست بوده یا نه!
2-	سوالام رو در حین مراحل ازتون بپرسم و هدفم از انجام این کار کاملا معلوم بشه.
3-	اگر مراحل کامل و درست بوده، بتونه مرجعی باشه که کاربران دیگه هم استفاده کنن.

(در ضمن تمام سوالهام رو با شماره پرسیدم و پر رنگشون کردم)

*مراحل:*
1-اول در بخش solution explorer ، روی csp کلیک راست کردم و از منوی ظاهر شده add و بعد resource رو اضافه کردم:


2- از پنجره باز شده، بخش دیالوگ رو انتخاب کردم،



3- از بین انواع دیالوگ ها، من IDD_PROPPAGE-LARGE رو انتخاب کردم که به صورت زیر بود:

*سوال 1: آیا انتخابم درست بوده یا نوع دیگه ای رو باید انتخاب می کردم یا اینکه اصلا با هم فرقی ندارن؟
(البته 4 مورد اول با 3 مورد آخر متفاوت بودن و فقط 3 مورد آخر به صورت دیالوگ استاندارد شبیه
MFC بودن و من از بین 3 تای آخر،یکی اش رو انتخاب کردم!)*



4- اجزایی رو که لازم داشتم به دیالوگ اضافه کردم، به صورت زیر:


5- بعد دکمه Enter رو دو بار کلیک کردم و صفحه زیر ظاهر شد و بعد کلاس CPinDialog (که شما هم در پستتون انتخاب کردین) رو به عنوان اسم کلاس انتخاب کردم، به صورت زیر:


6- بعد یک متغیر به نام m_pin و از نوع CString به کنترل کادر ویرایش موجود در دیالوگ اختصاص دادم (که در واقع متغیری هست که PIN وارده توسط کاربر رو در خودش نگه می داره!)


7- هدر فایل و سورس فایل مربوط به PinDialog ایجاد شدند که هدر فایلش به صورت زیر هست:







> در کل پیشنهاد می کنم به جای اینکه دیالوگ را در پروژه csp dll بسازید در همان پروژه فراخوانی کننده dll قبل از فراخوانی هر تابع pin را دریافت کنید و سپس در همانجا چک کنید. تابع بررسی pin را فقط در قالب یک تابع فراخوانی و استفاده کنید.
>  - open fialog
> - get pin
> - Check pin (from dll)
> - if (pin= true)  function1();  else  showerror


دلیل اینکه من می خوام دیالوگ "Enter PIN " فقط مختص csp.c باشه و مستقل از دیالوگ "CSPCaller " باشه ، به این خاطره که کلا مکانیزم چک کردن PIN در پروژه من متفاوته و با اون روالی که شما مد نظرتون هست فرق داره!

من می خوام PIN وارده رو از طریق PIN موجود در کارت هوشمند چک کنم، روال کاری که انجام می دم، به صورت زیره:
از طریق دیالوگ "Enter PIN " متغیر m_pin رو(که به صورت CString ) دریافت می کنم، به صورت APDU (APDU قالب دستوراتی هست که به کارت هوشمند فرستاده میشه و به صورت بایتی هست و یک نمونه از اون و اجزاش رو در زیر می گذارم که APDU ی مربوط به دستور VerifyPIN هست!) به کارت می فرستم و اگر کارت در جواب دو بایت وضعیت 00-90  رو فرستاد، به کاربر یک پیغام (مثلا از طریق MessageBox ) می دم که pin ورودی اش درسته و اگر نه، می گم pin وارده اشتباهه!

قالب دستور APDU ی VerifyPIN ای که به کارت می فرستم به صورت زیره:
APDU  apdu;

//Do verify PIN
	apdu.bSend = TRUE;
	apdu.CLA = 0x00;
	apdu.INS = 0x20;
	apdu.P1 = 0x00;
	apdu.P2 = 0x00;
	apdu.P3 = 0x08;//length of PIN in bytes
	for(int i=0;i<8;i++)
		apdu.Buffer[i]=m_pin[i];
	DoTransmit(apdu);


چهار بایت اول(از CLA تا P2 ) فرمت دستور معادل VerifyPIN هست که توسط کارت قابل فهمه،بعد طول PIN که 8 هست رو به صورت Hex در P3 ریختم و در حلقه for هم کاراکترهایی که کاربر وارد کرده،به صورت بایتی در آرایه بایتی عضو شی apdu ریخته می شه و نهایتا با تابع  DoTransmit(apdu) (که جداگانه تعریف کردم) به کارت ارسال میشه و اگر بایتهای خاصی از apdu ی پاسخ کارت هوشمند،دو بایت 90-00 باشه، یک MessageBox برای کاربر ظاهر بشه که pin اش درسته یا غلط!

PIN موجود در کارت معادل با رشته کاراکتری "12345678 " هست که معادل اسکی اون باید به کارت ارسال بشه، یعنی {38و37و36و...31}.

اگه خاطرتون باشه، من در این تاپیک:
https://barnamenevis.org/showthread.php?t=146557
ازتون پرسیدم که متغیر m_pin که از نوع CString تعریف شده، مقدارش به صورت اسکی ذخیره میشه یا نه که شما فرمودین اگه m_pin به صورت رشته تعریف بشه، مقداری که کاربر وارد می کنه، در اون بصورت اسکی ذخیره میشه!
حالا برای اینکه از درستی کاری که می کنم مطمئن بشم دوباره ازتون می پرسم:

*سوال 2- من می خوام رشته کاراکتری که کاربر وارد می کنه، در متغیر m_pin به صورت بایتی ذخیره بشه تا بتونم این بایتها رو مستقیما به کارت ارسال کنم تا pin رو بررسی کنه و پاسخ رو برگردونه!

2-1- آیا این کار درسته که من متغیر m_pin رو در دیالوگ "Enter PIN " به صورت CString تعریف کنم یا باید نوع دیگه ای واسش تعریف کنم؟
  (چرا که قصد من اینه که کاربر یه رشته کاراکتری رو از روی کیبورد وارد کنه و من بایتهای کد   اسکی اون رو به کارت بفرستم.)

2-2- اگر به فرض بایتهای کد اسکی در متغیر m_pin قرار گرفت، آیا فرمت این بایتها به صورت Hex هست (یعنی مثلا کاراکتر 1 به صورت 0x31 در اولین جزء رشته m_pin قرار می گیره؟) که من راحت اون رو در عضو Buffer از شی apdu بریزم (که این عضو به صورت یک آرایه بایتی هست و فقط بایتهای به فرمت Hex (یعنی مثلا 0x3d ) باید در اون ریخته بشه!) یا اینکه قبل از ریختن مقادیر موجود در m_pin باید تبدیلی انجام بدم؟
اگر تبدیلی باید انجام بگیره، چه تبدیلیه؟

2-3- آیا این شکل دستور درسته؟
apdu.Buffer[i]=m_pin[i];
یعنی می تونم با متغیر از نوع CString ی m_pin به صورت آرایه برخورد کنم و درایه های اون رو بایت به بایت در درایه های متغیر Buffer بریزم؟
*

به همین دلیل(یعنی عدم دسترسی به محتویات csp.dll و عدم مانیتور شدن اون توسط کاربرد دیگه ای) من مجبورم که یک دیالوگ جداگانه و فقط مختص csp.c درست کنم که pin وارده فقط بتونه داخل اون بره نه جای دیگه!

*سوال 3- اگر من بخوام از متغیر m_pin که در هدر فایل  pindialog.h تعریف شده و در واقع به کنترل کادر ویرایش موجود در دیالوگ "Enter PIN " اختصاص داده شده، مستقیما در کد CSP.C استفاده کنم و محتویات اون رو در apdu.buffer بریزم، آیا برای این کار باید هدر فایل pindialog رو در بالای کد csp.c ،  include کنم؟
یعنی آیا بدون include کردن این هدر فایل، csp.c می تونه از متغیر m_pin استفاده کنه یا نه؟*





> اما از آنجایی که پروژه csp dll شما از نوع win32 هست (نه MFC) و شما هم می خواهید در همان پروژه یک دیالوگ بسازید، باید دیالوگ را نیز به صورت win32 بسازید و فراخوانی کنید:


*سوال 4- ساختن دیالوگ به صورت win32 و فراخوانی اون چه طوریه؟ 
من تا حالا فقط دیالوگ MFC ساختم، ولی حالا چون می خوام یه دیالوگ به csp.dll (که از نوع win32 هستش!) اضافه کنم، چه کار باید بکنم؟
آیا اون مراحلی که در ابتدای پستم انجام دادم، یک دیالوگ از نوع win32 می سازه یا نه؟*


به فرض من در تابع "CPSignHash" که در کد csp.c موجوده ،می خوام ابتدای تابع این دیالوگ " Enter PIN " رو فراخوانی کنم،
این کد مربوط به تابع هست که من بخشی اش رو گذاشتم:
BOOL WINAPI
CPSignHash(
    IN  HCRYPTPROV hProv,
    IN  HCRYPTHASH hHash,
    IN  DWORD dwKeySpec,
    IN  LPCWSTR szDescription,
    IN  DWORD dwFlags,
    OUT LPBYTE pbSignature,
    IN OUT LPDWORD pcbSigLen)
{

	BOOL CALLBACK PinCheckProc(HWND hwndDlg, 
                             UINT message, 
                             WPARAM wParam, 
                             LPARAM lParam) 
{ 
    switch (message) 
    { 
        case WM_COMMAND: 
            switch (LOWORD(wParam)) 
            { 
                case IDOK: 
                    // DO something 
 
                case IDCANCEL: 
                    EndDialog(hwndDlg, wParam); 
                    return TRUE; 
            } 
    } 

	if (DialogBox(hinst,  MAKEINTRESOURCE(DLG_PINDIALOG), 
              hwnd, (DLGPROC)PinCheckProc)==IDOK) 
{
  // do something
}

	if(dwKeySpec!=0)
		SetLastError(NTE_NO_KEY);

	if(szDescription!=NULL)
		SetLastError(ERROR_MORE_DATA);

	if(dwFlags!=0)
 SetLastError(NTE_BAD_FLAGS);
//rest of code ...
{


با توجه به دستوراتی که شما برای فراخوانی دیالوگ نوع *Win32* گذاشتید، به نظر میرسه که اول باید تابع PinCheckProc و بعد دستور: 
if (DialogBox(hinst,  MAKEINTRESOURCE(DLG_PINDIALOG), 
              hwnd, (DLGPROC)PinCheckProc)==IDOK) 
{
  // do something
}

رو در ابتدای تابع "CPSignHash" قرار داد!

*هدف دقیق من اینه:*
وقتی کاربر در دیالوگ مربوط به CSPCaller ،دکمه CPSignHash رو فشار داد،بعد از اون دیالوگ "Enter PIN " ظاهر بشه تا کاربر PIN رو وارد کنه و بعد در تابع "CPSignHash" مقدار m_pin ارزیابی بشه!

*سوال5- برای تحقق این هدف که ذکر شد، دقیقا باید چه کار کنم؟
منظورم اینه که کدوم تابع مستقیما دیالوگ "Enter PIN " رو صدا می زنه که به کاربر نمایش داده بشه؟
آیا دستور زیر که شما گذاشتید به محض اجرا، دیالوگ "Enter PIN " رو مستقیما به کاربر نشون میده؟*

if (DialogBox(hinst,  MAKEINTRESOURCE(DLG_PINDIALOG), 
              hwnd, (DLGPROC)PinCheckProc)==IDOK) 
{
  // do something
}






> اگر کار با دیالوگ ها را نمی دانید حتما یک کتاب MFC و win32 مطالعه کنید.


راستش من کتاب برنامه نویسی با ویژوال C++‎ تالیف مهندس جعفر نژاد قمی رو کامل خوندم ولی هم چین چیزی رو نداره،یعنی دستوری که بشه در تابعی گذاشت و از طریق اون دیالوگ رو فراخوانی کرد، هیچ جای دیگه ای هم هم چین مثالی پیدا نکردم!
میشه شما راهنمایی کنید که برای تحقق هدف ذکر شده، دقیقا چه دستوراتی رو باید در تابع CPSignHash قرار بدم؟
چون میترسم اگه خودم بنویسم، موقع کامپایل نهایی پروژه،به مشکل بر بخورم چرا که ساختار این توابع رو دقیق نمی دونم!


و در نهایت اینکه واقعا ممنون میشم اگه سوالاتم رو جواب بدین!
صمیمانه واستون آرزوی موفقیت می کنم، البته این رو حمل بر تملق نذارین، چون واقعا کمکهاتون به دیگران نیاز به تقدیر ویژه داره!
(امیدوارم همونطور که شما وقت می ذارین و دیگران رو کمک می کنین ،خدا هم همیشه کمکتون کنه.)
با تشکر

----------


## Nima_NF

1- آن ها فقط یک template یا قالب هستند و فرقی نمی کند کدام را انتخاب می کنید، بعد از ساخت باید خواص دیالوگ را خودتان هر طوری می خواهید تنظیم کنید.
در کل بهتر هست برای حالت عادی برای یک دیالوگ بر روی همان dialog کلیک کنید و قالب ها یا زیر شاخه های آن را انتخاب نکنید.

2- در این مورد به قدر کافی توضیح دادم!
تقریبا درست هست، اما دوباره به همان تاپیک مراجعه کنید و مطالعه کنید، اگر می خواهید مستقیم با CString کار کنید باید از متد های آن استفاده کنید و مانند آرایه کار نکنید، مثلا با GetBuffer یا برای هر کارکتر از GetAt استفاده کنید نه آرایه:

CString s( "12345");
int x = *(int)* s.GetAt( 2 );
 یا آن را کلا با GetBuffer در آرایه ای از char بریزید.

در هر حال وقتی می خواهید کد اسکی را بگیرید فقط کافی هست آن را با یک *(int)* به صورتصریح در یک متغیر عددی بریزید.

char strX[5] = "1234";
int  x = (int) str[2];

پروژه هم باید اسکی کامپایل شود در غیر این صورت از معادل های اسکی Cstring که در همان تاپیک گفتم استفاده کنید.

3- شما برای ارتباط با dll باید تابع تعریف کنید، dll فقط تابع می فهمد، اگر قرار است متغیری ارسال یا دریافت شود باید تابعی مثلا با نام GetPin نوشته شود و متغیر را دریافت کنید یا بفرستد. پس هدر فایل معنایی ندارد، مگر اینکه تعریف تابع در فایل .h برای dll هدف شماست.

4- سوال 1 شما دیالوگ MFC می سازد نه win32، به طور کامل این مورد را نیز در پست قبلی توضیح دادم!
در win32 اصلا کلاس نداریم، فقط دیالوگ را بسازید و همین کدهایی را که گذاشتید بنویسید. اعمال چک کردن pin را هم در داخل پیام ها قرار دهید نه انتهای تابع CPSignHash، مثلا در داخل case بعد از IDOK قرار دهید.

5- شما دارید یک custom Dll می سازید، پس ابتدای هر تابع که در dll صادر می شود (همه توابع) می توانید همین کد DialogBox را قرار دهید تا اگر درست نبود اصلا تابع NULL برگرداند.
(اگر قرار هست که دیالوگ توسط توابع dll اجرا شود و شما آن را در برنامه client فراخوانی نکنید)




> استش من کتاب برنامه نویسی با ویژوال C++‎ تالیف مهندس جعفر نژاد قمی رو کامل خوندم ولی هم چین چیزی رو نداره،یعنی دستوری که بشه در تابعی گذاشت و از طریق اون دیالوگ رو فراخوانی کرد، هیچ جای دیگه ای هم هم چین مثالی پیدا نکردم!
> میشه شما راهنمایی کنید که برای تحقق هدف ذکر شده، دقیقا چه دستوراتی رو باید در تابع CPSignHash قرار بدم؟
> چون میترسم اگه خودم بنویسم، موقع کامپایل نهایی پروژه،به مشکل بر بخورم چرا که ساختار این توابع رو دقیق نمی دونم!


چیزی که شما یاد گرفتید برنامه نویسی  MFC با ++visual C هست. برای win32  (کاری که برای ساخت dll دارید انجام می دهید) منبع فارسی نداریم به اعلان ها همین بخش برای کتاب win32 API مراجعه کنید.

در نهایت اگر هنوز با win32 آشنایی ندارید حتما آن ها را مطالعه کنید. MFC از همان API های win32 برای پیاده سازی خود استفاده می کند و آن ها را در قالب کلاس هایی ارائه می کند.

*تذکر مهم*: در کل اگر می خواهید در ویندوز و توسط MFC یک dll بسازید احتمالا در همان کتاب نحوه ساخت آن را توضیح داده است یا می توانید از کتاب  ++visual C در 21 روز استفاده کنید.، شما می توانید به جای یک پروژه win32 dll یک پروژه MFC dll بسازید و در آن از همان توابع و کلاس های MFC استفاده کنید و توابع را به همان شکل تعریف کنید و دیالوگ را به شکل MFC بسازید و با DoModal فراخوانی کنید و ... 
البته به این شکل دیگر خودتان باید توابع را از نمونه پروژه مایکروسافت به این MFC dll وارد کنید.

----------


## bizmit

سلام و ممنون!



> تذکر مهم: در کل اگر می خواهید در ویندوز و توسط MFC یک dll بسازید احتمالا در همان کتاب نحوه ساخت آن را توضیح داده است یا می توانید از کتاب ++visual C در 21 روز استفاده کنید.، شما می توانید به جای یک پروژه win32 dll یک پروژه MFC dll بسازید و در آن از همان توابع و کلاس های MFC استفاده کنید و توابع را به همان شکل تعریف کنید و دیالوگ را به شکل MFC بسازید و با DoModal فراخوانی کنید و ... 
> البته به این شکل دیگر خودتان باید توابع را از نمونه پروژه مایکروسافت به این MFC dll وارد کنید.


راستش من اصلا قصد ساخت MFC dll رو ندارم،چون نمونه کد csp که از مایکروسافت گرفتم هم باید به صورت win32 dll ساخته بشه و از طرفی آشنایی هم با ساخت MFC dll ندارم و هم چنین اصلا فرصت یادگیری اش رو هم ندارم، چراکه باید تا چند روز آینده از پروژه ام جواب بگیرم!





> چیزی که شما یاد گرفتید برنامه نویسی MFC با ++visual C هست. برای win32 (کاری که برای ساخت dll دارید انجام می دهید) منبع فارسی نداریم به اعلان ها همین بخش برای کتاب win32 API مراجعه کنید.
> 
> در نهایت اگر هنوز با win32 آشنایی ندارید حتما آن ها را مطالعه کنید. MFC از همان API های win32 برای پیاده سازی خود استفاده می کند و آن ها را در قالب کلاس هایی ارائه می کند.


ببخشید این کدهایی که شما برای فراخوانی دیالوگ MFC در یک کد win32 ، در پستتون قرار دادید رو از چه کتابی یاد گرفتید؟
یعنی دستورات فراخوانی دیالوگ در یک کد win32 و احیانا اضافه کردن هدر فایل های لازم به کد win32 برای شناختن این دستورات، در چه کتابی موجوده؟
اگر لطف کنید و اسم کتاب و بخشی از کتاب که به این موضوع اختصاص داده شده رو معرفی کنید، ممنون میشم!
(چون من که فعلا هیچ کتابی در این زمینه پیدا نکردم و از طرفی بقیه وقتم رو 
هم باید صرف تکمیل بخش های رمزنگاری پروژه ام کنم و این فقط یک بخشی از پروژه ام هست!)



من تابع CPSignHash رو به صورت زیر می خوام پیاده سازی کنم:
CPSignHash()
{
if (DialogBox(hinst,  MAKEINTRESOURCE(DLG_PINDIALOG), 
              hwnd, (DLGPROC)PinCheckProc)==IDOK) 
{
  // CPSignHash function code
}
else

SetLastError(NTE_FAIL);//The function CPSignHash fails
Return FALSE;
}

یعنی ابتدای تابع، دیالوگ  "Enter PIN " رو به کاربر نشون بده و PIN رو دریافت و بررسی کنه، و اگر PIN درست بود، تابع PinCheckProc مقدار TRUE برگردونه و نهایتا شرط if درست بشه و بعد بقیه کد تابع CPSignHash فراخوانی بشه.
اگر نه، یک ارور ویندوزی در تابع CPSignHash ست بشه!





> شما برای ارتباط با dll باید تابع تعریف کنید، dll فقط تابع می فهمد، اگر قرار است متغیری ارسال یا دریافت شود باید تابعی مثلا با نام GetPin نوشته شود و متغیر را دریافت کنید یا بفرستد. پس هدر فایل معنایی ندارد، مگر اینکه تعریف تابع در فایل .h برای dll هدف شماست.


*سوال صفر- راستش منظورتون رو از تابع GetPin متوجه نمی شم، من فقط دستورات تابع PinCheckProc رو کامل کردم به صورت زیر:
(البته در MFC که با دستور UpdateData(TRUE متغیر از دیالوگ به کد انتقال پیدا می کرد،منم اینجا همون کار رو کردم، یعنی متغیر m_pin رو این جوری وارد تابع کردم،درسته؟)
*

BOOL CALLBACK PinCheckProc(HWND hwndDlg, 
                             UINT message, 
                             WPARAM wParam, 
                             LPARAM lParam) 
{ 
    switch (message) 
    { 
        case WM_COMMAND: 
            switch (LOWORD(wParam)) 
            { 
                case IDEnter: 
                    // DO something
			UpdateData();//For getting m_pin from Edit control
			// For both unicode or ANSI
			int sizeOfpin = (m_pin.GetLength() + 1);
			LPTSTR sBuffer=m_pin.GetBuffer(sizeOfpin);

			APDU  apdu;
                    //Do verify PIN
   	                apdu.bSend = TRUE;
 	                apdu.CLA = 0x00;
	                apdu.INS = 0x20;
	                apdu.P1 = 0x00;
	                apdu.P2 = 0x00;
	                apdu.P3 = 0x08;//length of PIN in bytes
	                for(int i=0;i<8;i++)
						apdu.Buffer[i]=(BYTE)sBuffer[i];
				//DoTransmit(apdu);
				BYTE	SendBuff[256 + 5];
	                BYTE	RecvBuff[256 + 2];
	                DWORD	SendBuffLen;
	                DWORD	RecvBuffLen;
	                SCARD_IO_REQUEST	pioSendRequest;
	                LONG    lReturn;

				SendBuff[0] = apdu.CLA;
				SendBuff[1] = apdu.INS;
				SendBuff[2] = apdu.P1;
				SendBuff[3] = apdu.P2;
				SendBuff[4] = apdu.P3;
				if (apdu.bSend)
	{
		for(int indx=0; indx < apdu.P3; indx++)
		{
			SendBuff[indx + 5] = apdu.Buffer[indx];
		} //for loop
	}

					if (apdu.bSend)
	{
		SendBuffLen = apdu.P3 + 5;
		RecvBuffLen = 2;
	}
					else//recieve APDU response with Data 
	{
		SendBuffLen = 5;
		RecvBuffLen = apdu.P3 + 2;
	}
			pioSendRequest.dwProtocol = m_APrtocol;
	        pioSendRequest.cbPciLength = sizeof(SCARD_IO_REQUEST);
		//////////////////////
		lReturn = SCardTransmit(hProv->hCard,
							  &pioSendRequest,
							  SendBuff,
							  SendBuffLen,
							  NULL,
							  RecvBuff,
							  &RecvBuffLen);
		if (lReturn != SCARD_S_SUCCESS)
		SetLastError(lReturn);

		m_pin.ReleaseBuffer( );

		//RecvBuff is a byte array which is respose apdu
             if(RecvBuff[0]==0x90 && RecvBuff[1]==0x00)
		{
              MessageBox(“The PIN is correct!”);
		return TRUE;//Exit the function PinCheckProc
		}

             Else
              {
              MessageBox(“The PIN is incorrect!”);
			m_pin.Empty();
			UpdateData(FALSE);
               }

                case IDCANCEL: 
                    EndDialog(hwndDlg, wParam); 
                    return TRUE; 
            } 
    } 
    return FALSE; 
}


حالا چند سوال در مورد همین تابع داشتم:

*سوال 1- من این تابع رو در بالای کد csp.c تعریف کردم، آیا این کار درسته؟
یعنی در کد های pindialog.h و pindialog.cpp که مربوط به دیالوگ "Enter PIN " هست، تعریف نکردم،حتی اعلان هم نکردم!
(چرا که فقط بعضی از توابع موجود در csp.c قراره که در ابتدای کدشون( یعنی به عنوان آرگومان ورودی DialogBox )این تابع رو(به منظور چک کردن PIN ) فراخوانی کنند.)*






> درwin32 اصلا کلاس نداریم، فقط دیالوگ را بسازید و همین کدهایی را که گذاشتید بنویسید. اعمال چک کردن pin را هم در داخل پیام ها قرار دهید نه انتهای تابع CPSignHash، مثلا در داخل case بعد از IDOK قرار دهید.


در زیر IDEnter(چون یک دکمه به اسم Enter تعریف کردم و خاصیت ID اون رو
IDEnter انتخاب کردم! به جای IDOK )
اینم عکس دیالوگ:


اول اندازه m_pin رو گرفتم و بعد محتویات اون (که قراره بایتهای اسکی باشه) رو در اشاره گر بایتی sBuffer ریختم.بعد از مقداردهی پارامترهای apdu ، با دستور زیر بایتهای اسکی sBuffer (یعنی همون pin ) رو در پارامتر بافر apdu ریختم. برای اینکه مطمئن بشم بایتهای اسکی رو از نوع Hex می ریزه، یه cast از نوع int هم ازش گرفتم:
apdu.Buffer[i]=(int)sBuffer[i];


*سوال 2- پارامتر Buffer از شی apdu از نوع BYTE هست (یعنی یک آرایه بایتی که از نوع Data type های ویندوزی یعنی BYTE تعریف شده!)
حالا که من می خوام بایتهای کد اسکی متغیر sBuffer رو در اون بریزم،
نمی دونم cast از نوع BYTE ازش بگیرم یا cast از نوع int ؟
(البته شما در پست قبلیتون اشاره کردین برای گرفتن کد اسکی باید cast از نوع int از کاراکتر گرفت ولی اینجا پارامتر Buffer از نوع BYTE هست!)
*


بعد از اون دستورات DoTransmit هست که از خط comment ی //DoTransmit(apdu); شروع میشه تا خط زیر:
SetLastError(lReturn);

بعد از این خط بافر مربوط به CString رو آزاد کردم:
m_pin.ReleaseBuffer( );
*
سوال 3- آیا جای این دستور مناسبه؟*

بعد از اون چک کردم که اگه جواب apdu ی پاسخ، دو بایت 90 و 00 باشه، یه MessageBox نشون بده که pin وارده درسته!

*سوال 4- آیا میتونم در تابع PinCheckProc (یا در واقع در کد csp.c ) از دستور MessageBox استفاده کنم؟
البته این سوالم بیشتر برای اینه که شما تایید کنید درست می گم یانه!
این تابع در هدر winuser.h موجوده و این هدر هم در windows.h موجوده که در بالای کد csp.c ، include شده. پس کامپایلر میتونه این تابع رو بشناسه!
درسته؟

واینکه نیازی نیست که دیگه pindialog.h رو در cspdk.h ، include کنم؟
*


*سوال 5- من می خوام بعد از این که MessageBox داد که PIN درسته، دیالوگ "Enter PIN " بسته بشه و شرط if در دستور زیر درست بشه تا دستورات بعدی تابع CPSignHash انجام بشه، آیا درسته که برای اینکار، بعد MessageBox Return TRUE کنم و آیا بعد از اینکه شرط if در دستور زیر درست شد، دیالوگ "Enter PIN " خود به خود بسته می شه یا داخل if ، ابتدا باید دستوری گذاشت تا این دیالوگ بسته بشه و بعد کد های تابع CPSignHash اجرا بشه؟
*

if (DialogBox(hinst,  MAKEINTRESOURCE(DLG_PINDIALOG), 
              hwnd, (DLGPROC)PinCheckProc)!=IDOK) 
{
  // do something
}


*سوال 6- می خواستم ببینم به جای مقدار DLG_PINDIALOG در دستور بالا چه مقداری رو باید قرار بدم؟
یعنی این مقدار رو باید از کجا دید، چون ممکنه دیالوگی که من ایجاد کردم، این مقدارش با اینی که شما گذاشتید فرق کنه!
*

درضمن هدر فایل pindialog.h به صورت زیره:
#pragma once


// CPinDialog dialog

class CPinDialog : public CDialog
{
	DECLARE_DYNAMIC(CPinDialog)

public:
	CPinDialog(CWnd* pParent = NULL);   // standard constructor
	virtual ~CPinDialog();

// Dialog Data
	enum { IDD = IDD_DIALOG1 };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

	DECLARE_MESSAGE_MAP()
public:
	CString m_pin;
};


*با تشکر فراوان*

----------


## Nima_NF

کم کم سوالات طولانی تر می شوند و اشتباهات هم وسیع تر...

همانطور که گفتم به اعلان ها همین بخش برای کتاب win32 API مراجعه کنید!
کتاب Programming Windows Fifth Edition

صفر) برنامه نویسی MFC یعنی همان win32 در قالب کلاس هایی تحت عنوان MFC به علاوه امکان استفاده مستقیم ازAPI  win32 .
 اما برنامه نویسی win32 API یعنی فقط win32 API و نمی توانید ازهیچ کدام یک از توابع MFC استفاده کنید. در win32 نه تخصیص متغیر داریم، نه کلاس،  نه UpdateData ، نه CString نه ...  بلکه شما باید خودتان محتویات یک فیلد را مثلا با GetWindowText دریافت کنید، محتویات را فقط برای یک کنترل می گیریم، برای تمامی کنترل ها باید این مورد فراخوانی شود:

HWND hwndEditBox ; 
TCHAR PStr[20];

hwndEditBox = GetDlgItem(hwndDlg, IDD_EDITBOX1); 
GetWindowText(hwndEditBox, PStr, 10); 
پس کل سوالاتی مواردی که مثلا بافر CString دارد و غیره همه غلط هستند و در win32 معنا نمی دهد. در win32 باید با ++C/C استاندارد کارکنید ، مثلا اشاره گری از  char و ...

یعنی در سوالات زیر نیمی از موارد شما اشتباه هست.

1) بله
چون فقط می خواهید از این تابع در داخل dll استفاده کنید نیازی به export به dll ندارد و لذا تعریف هم نمی خواهد (اگر بالای فایل تعریف می کنید، اگر پایین DllMain بود باید تعریف آن را هم اضافه می کردید)

2) می توانید به نوع *BYTE* تبدیل کنید یا اصلا نکنید*.
*نگاه کنید اصلا فرق نمی کند که شما تبدیل کنید یا نه ، حقیقتا این موضوع را 3 مرتبه توضیح دادم (!!!) چیزی که در  char قرار دارد کارکتر نیست بلکه عدد است، حرف 1 در یک char ذخیره نمی شود بلکه همان 49 ذخیره می شود که همان 31 هگز هست. BYTE همان char هست یعنی بازه -127 تا 127 . این اصول برنامه نویسی هست. تبدیل به int یا BYTE هم نیاز نیست. 

ما در win32 رشته CString نداریم، از char برای اسکی یا TCHAR برای یونیکد استفاده کنید.

3) خودتان هر جایی که فکر می کنید همه موارد دریافت شده است، پیام را نشان دهید.

4) بله، MessageBox  از توابع API win32 هست.

5) متوجه نشدم، چند جمله داخل هم شد...

6) وقتی دیالوگی ساختید (باز هم تکرار می کنم برای win32، نه MFC)، در پنجره properties در قسمت طراحی ID دیالوگ را می توانید تغییر دهید، در مثال من DLG_PINDIALOG قرار دادم.

CPinDialog شما که کلاسی از CDialog است برای MFC هست، win32 کلاس نمی خواهد و بی معناست. همان تابع PinCheckProc کار مشابه کلاس  MFC را در win32 می کند.

تعجب می کنم که شما در پروژه win32 که dll را می سازد چطور برای آن کلاس MFC تعریف کردید!

----------

