گفتگو هایی در باب سی شارپ

the_king

مدیرکل انجمن
ممنون استاد علی
الان منظورتون اینه که هر بکاپی که گرفته شد ، درخواست ها (مثل فراخونی توابع مربوط به vss) فقط به پروسه ( requester و writer) اش جواب میده و غیر از اونها ، جواب نمیده؟
که فکر نکنم منظورتون این باشه و من اشتباه برداشت میکنم . چون هر کس با همون متد Delete

IVssBackupComponents::DeleteSnapshots

یا با دستور vssadmin delete shadows all در command line ، میتونه همه ی بکاپ هایی که هر پروسه و requester ای گرفت را حذف کنه .

منبع مشخصی برای این ادعاتون دارید یا صرفا بهتون الهام شده؟ چون شما کلا منکر وجود پیغام خطای Error: Snapshots were found, but they were outside of your allowed context. Try removing them with the backup application which created them. هستید.

بله . منظور من هم همین بود . اینکه چجوری میشه مشتقات اینترفیس IVssBackupComponents را (در api) پیدا کرد و هم اینکه مثلا در اون wrapper alphavss چه کدی نوشتن که با این متد میتونه توسط سی شارپ ارتباط برقرار کنه؟ و کلا اگه میشد یه مثالی از فراخونی این متد در این اینترفیس توسط سی شارپ بزنین ، عالی میشد .
ممنون
منظورتون از چیزی که میگید به عقل جن هم نمیرسه. دو تا مرحله داره که اگه هزار بار هم براتون بگم هیچ فایده ای نداره، چون حاضرید هزار ساعت سر چیزی که نمیدانید استدلال بتراشید و با من بحث کنید ولی ده ساعت برای مطالعه منابع وقت نمیذارید. اول اینکه در سایت مایکروسافت جستجو اش کنید و دوم نتایج جستجو رو بخونید. صد تا لینک نتایج جستجو هم پیدا کنید تا وقتی نخونیدش حاصلی نداره.
اینجا خیلی صریح نوشته که با فراخوانی CreateVssBackupComponents شیء ای از اینترفیس IVssBackupComponents بدست میاد :
IVssBackupComponents
و alphavss رو هم همونطور که خودتون در شروع مستنداتش خوندید به زبان ++C نوشته شده، نه #C. طبعا تصور نمی کنید که ارتباطات داخلی ++C کاری با #C داشته باشه. یک شیء از زبان ++C ئه، با کد ++C هم متد هاشو فراخوانی می کنه :
AlphaVSS 1.4.0 – AlphaVSS – Bringing Windows Volume Shadow Copy Service to .NET
و زمان خیلی طولانی ای لازمه که اونقدر به NET. و CLI مسلط شده باشید که بخواهید مستقیما فراتر از زبان با IL و پشته مستقیما متد فراخوانی کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
الزاما ربطی به خود Visual Studio نداره، جزو Windows SDK ئه. اگر Windows SDK یکی از ویندوز ها رو از سایت مایکروسافت بصورت کامل دانلود کنید (معمولا یک فایل iso) مجموعه کاملی از این header ها هم داخلش هست. برای برنامه نویس های زبان ++C/C اصولا نیازی به دیدن مقادیر ثابت ها یا جستجو شون نیست، چون یکباره کل header رو در کدشون مرجع قرار می دهند و فقط از همون اسم مقادیر استفاده می کنند.

سلامی مجدد
ممنون استاد علی
برای ویندوز 10 ، منظورتون این لینک 810 مگابایتی هه؟ :

Windows 10 SDK - Windows app development

http://go.microsoft.com/fwlink/p/?LinkID=2033686

موقع نصب ویژال استودیو هم احتمالا چشمم به گزینه ی windows sdk خورد . همینه؟ همونو میتونم نصب کنم؟
بعد اینکه نمیدونم توی سی شارپ چجوری رفرنس میدن یا کلا چجوری از هدرهاش توی سی شارپ استفاده میکنن؟ قابلیت اکسپلور توی object browser را داره تا مقادیر هدرهاشو ببینیم؟


منبع مشخصی برای این ادعاتون دارید یا صرفا بهتون الهام شده؟ چون شما کلا منکر وجود پیغام خطای Error: Snapshots were found, but they were outside of your allowed context. Try removing them with the backup application which created them. هستید.

:)
ممنون
البته سئوال پرسیدم و گفتم شک دارم دیگه!
پس الان طبق توضیحات زیر :

Security Considerations for Requesters - Windows applications

ورودی اول متد CoInitializeSecurity یعنی pSecDesc را اگه null ندیم ، میتونیم فراخونی هایی (مثلا متد delete برای vss) که صورت میگیره را فقط از کاربرانی که به اکنت خاصی متعلق هستند ، صورت بدیم :

A COM server (such as a requester) that is calling CoInitializeSecurity with a non-NULL security descriptor as the first parameter can use the descriptor to configure itself to accept incoming calls only from users that belong to a specific set of accounts.

طبق توضیحات این پارامتر در متد CoInitializeSecurity ، یه اشاره گر به AppID یا اینترفیس IAccessControl یا استراکچر SECURITY_DESCRIPTOR میگیره .
حالا من که میخوام فقط بکاپ هایی که از پروسه و برنامه ی خودم گرفته شد ، فقط از این پروسه به بکاپ هام دسترسی داشته باشم (و بتونم فقط از این پروسه ، مدیریت و حذف شون کنم) ، باید در این پارامتر اول در این متد ، مقدار اشاره گر به AppID برنامه و پروسه ی خودم را بدم؟
بعد هم طبق بقیه ی توضیحات در همون لینک اول در بالا ، مقدار ورودی dwAuthnLevel در اون متد را RPC_C_AUTHN_LEVEL_PKT_PRIVACY و مقدار dwImpLevel را RPC_C_IMP_LEVEL_IDENTIFY و مقدار dwCapabilities را EOAC_NONE و بقیه ی ورودی های اون تابع را null بدم؟
بعد هم اینکه متد CoInitializeSecurity در اعضای alphavss نبود .


منظورتون از چیزی که میگید به عقل جن هم نمیرسه. دو تا مرحله داره که اگه هزار بار هم براتون بگم هیچ فایده ای نداره، چون حاضرید هزار ساعت سر چیزی که نمیدانید استدلال بتراشید و با من بحث کنید ولی ده ساعت برای مطالعه منابع وقت نمیذارید. اول اینکه در سایت مایکروسافت جستجو اش کنید و دوم نتایج جستجو رو بخونید. صد تا لینک نتایج جستجو هم پیدا کنید تا وقتی نخونیدش حاصلی نداره.
اینجا خیلی صریح نوشته که با فراخوانی CreateVssBackupComponents شیء ای از اینترفیس IVssBackupComponents بدست میاد :
IVssBackupComponents
و alphavss رو هم همونطور که خودتون در شروع مستنداتش خوندید به زبان ++C نوشته شده، نه #C. طبعا تصور نمی کنید که ارتباطات داخلی ++C کاری با #C داشته باشه. یک شیء از زبان ++C ئه، با کد ++C هم متد هاشو فراخوانی می کنه :
AlphaVSS 1.4.0 – AlphaVSS – Bringing Windows Volume Shadow Copy Service to .NET
و زمان خیلی طولانی ای لازمه که اونقدر به NET. و CLI مسلط شده باشید که بخواهید مستقیما فراتر از زبان با IL و پشته مستقیما متد فراخوانی کنید.

ممنون
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلامی مجدد
ممنون استاد علی
برای ویندوز 10 ، منظورتون این لینک 810 مگابایتی هه؟ :

Windows 10 SDK - Windows app development

http://go.microsoft.com/fwlink/p/?LinkID=2033686

بله، باید همون باشه.
موقع نصب ویژال استودیو هم احتمالا چشمم به گزینه ی windows sdk خورد . همینه؟ همونو میتونم نصب کنم؟
احتمالا اون یک نسخه ناقصه. فقط یک بخشی شو که مورد استفاده کامپایلرها است و احتمالا بخشی اش از قبل کامپایل هم شده قرار میدن. من جای شما باشم روی اون نسخه همراه ویژوال استدیو حساب باز نمی کنم.
بعد اینکه نمیدونم توی سی شارپ چجوری رفرنس میدن یا کلا چجوری از هدرهاش توی سی شارپ استفاده میکنن؟ قابلیت اکسپلور توی object browser را داره تا مقادیر هدرهاشو ببینیم؟
چی رو رفرنس بدن؟ هدر ++C رو رفرنس بدن به #C؟ هیچکدوم؛ نه رفرنس دادنیه و نه با Object Browser دیدنیه. نهایتا به عنوان یک کد ++C ازدر یک پروژه جداگانه Library داخل Solution تون قرار میدهید که پروژه #C تون به پروژه ++C رفرنس بده. این جدا کامپایل میشه و اون جدا. البته دوباره کاریه چون همینکار رو از قبل alphavss انجام داده دیگه.

طبق توضیحات این پارامتر در متد CoInitializeSecurity ، یه اشاره گر به AppID یا اینترفیس IAccessControl یا استراکچر SECURITY_DESCRIPTOR میگیره .
حالا من که میخوام فقط بکاپ هایی که از پروسه و برنامه ی خودم گرفته شد ، فقط از این پروسه به بکاپ هام دسترسی داشته باشم (و بتونم فقط از این پروسه ، مدیریت و حذف شون کنم) ، باید در این پارامتر اول در این متد ، مقدار اشاره گر به AppID برنامه و پروسه ی خودم را بدم؟
بعد هم طبق بقیه ی توضیحات در همون لینک اول در بالا ، مقدار ورودی dwAuthnLevel در اون متد را RPC_C_AUTHN_LEVEL_PKT_PRIVACY و مقدار dwImpLevel را RPC_C_IMP_LEVEL_IDENTIFY و مقدار dwCapabilities را EOAC_NONE و بقیه ی ورودی های اون تابع را null بدم؟

اولا شک دارم که این پروسه شما است که backup رو گرفته، پستی که نوشته بودم رو مجددا بخونید، چون گفتم شک دارم اینکاریه که خودتون باید انجام بدید. چون شما از alphavss استفاده می کنید احتمال داره پروسه خودتون کاره ای نباشه که بیایید CoInitializeSecurity رو اجرا کنید. پروژه شما که اصولا ارتباط COM با VSS نداره. اگر وظیفه alphavss باشه دسترسی COM پروسه شما هر چی که باشه فرقی بحال دسترسی alphavss نمی کنه. و از طرف دیگه پروسه شما با کجا ارتباط COM داره که برایش دسترسی تعریف کنید؟ با Alphavss که ارتباط COM ندارید. با VSS هم که ارتباط مستقیمی ندارید. همچین جایی در کدتون نیست که ارتباط COM برقرار باشه.
بعد هم اینکه متد CoInitializeSecurity در اعضای alphavss نبود .
نبایدم باشه، اون متد رو خودش باید استفاده کنه و اجرا کنه. چیزی که برای شما باید بذاره یک متد یا پروپرتی یا رخدادی هست که بتوانید دسترسی ای رو داخلش تعریف کنید، وگرنه CoInitializeSecurity رو که مستقیما به پروسه شما واگذار نمیکنه. و اونم فقط یکبار اجراش می کنه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بله، باید همون باشه.

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

چی رو رفرنس بدن؟ هدر ++C رو رفرنس بدن به #C؟ هیچکدوم؛ نه رفرنس دادنیه و نه با Object Browser دیدنیه. نهایتا به عنوان یک کد ++C ازدر یک پروژه جداگانه Library داخل Solution تون قرار میدهید که پروژه #C تون به پروژه ++C رفرنس بده. این جدا کامپایل میشه و اون جدا. البته دوباره کاریه چون همینکار رو از قبل alphavss انجام داده دیگه.


اولا شک دارم که این پروسه شما است که backup رو گرفته، پستی که نوشته بودم رو مجددا بخونید، چون گفتم شک دارم اینکاریه که خودتون باید انجام بدید. چون شما از alphavss استفاده می کنید احتمال داره پروسه خودتون کاره ای نباشه که بیایید CoInitializeSecurity رو اجرا کنید. پروژه شما که اصولا ارتباط COM با VSS نداره. اگر وظیفه alphavss باشه دسترسی COM پروسه شما هر چی که باشه فرقی بحال دسترسی alphavss نمی کنه. و از طرف دیگه پروسه شما با کجا ارتباط COM داره که برایش دسترسی تعریف کنید؟ با Alphavss که ارتباط COM ندارید. با VSS هم که ارتباط مستقیمی ندارید. همچین جایی در کدتون نیست که ارتباط COM برقرار باشه.

نبایدم باشه، اون متد رو خودش باید استفاده کنه و اجرا کنه. چیزی که برای شما باید بذاره یک متد یا پروپرتی یا رخدادی هست که بتوانید دسترسی ای رو داخلش تعریف کنید، وگرنه CoInitializeSecurity رو که مستقیما به پروسه شما واگذار نمیکنه. و اونم فقط یکبار اجراش می کنه.

ممنون
نمیدونم دنبال چه نامی باید بگردم ولی چیز خاصی در این باره توی اعضای IVssBackupComponents پیدا نکردم . اما alphavss ، کلاس خیلی داره . نمیدونم توی کدوم کلاسش باید دنبال چه نامی بگردم .
پس با این اوضاع که توضیح دادین ، راهکار دیگه ای جز این روش نداره؟ چون میگین نمیشه مستقیما از تابع CoInitializeSecurity برای کار خودم که در alphavss هست ، استفاده کرد .
 

the_king

مدیرکل انجمن
ممنون
نمیدونم دنبال چه نامی باید بگردم ولی چیز خاصی در این باره توی اعضای IVssBackupComponents پیدا نکردم . اما alphavss ، کلاس خیلی داره . نمیدونم توی کدوم کلاسش باید دنبال چه نامی بگردم .
پس با این اوضاع که توضیح دادین ، راهکار دیگه ای جز این روش نداره؟ چون میگین نمیشه مستقیما از تابع CoInitializeSecurity برای کار خودم که در alphavss هست ، استفاده کرد .
اولا من گفتم شک دارم، نگفتم نمیشه. شما بررسی کردید و به این نتیجه رسیدید که alphavss در پروسه مجزا کار می کنه که میگید نمیشه؟ ثانیا دنبال راهکار دیگه ای هستید، شاید باشه، شاید اگر بگردید پنج تا راهکار دیگه پیدا کنید،
اما برای پیدا کردن هر راهکاری باید زمان صرف کنید.
یکبار بشینید برای خودتون حساب و کتاب کنید ببینید میخواهید وقت بقدر کافی صرف کنید یا نه. یک مواقعی هست، به چیزی علاقه داریم ولی حوصله و فرصتش رو نداریم، خوب قضیه منتفی میشه.
اگه حوصله شو ندارید بذاریدش کنار، اینترنت پر از معلومات نرم افزاریه که شاید اسمشونم نشنیده باشید و میتوانید هر کدومشون رو یاد بگیرید و یا نگیرید، هر روز هم مطالب جدیدی برای یادگیری هست.
اما اگر قراره مطلبی رو یادبگیرید عجولانه و بی حوصله و جسته گریخته نخونید.
alphavss که بی دلیل بزرگ نیست، خودش هیچ چیزی نیست جز یک Wrapper. این ساختار VSS ئه که بزرگه و پیچیده است. نمیشه که بگید من از این ماشین پیچیده چهار تا دکمش رو میدونم چیکار میکنه و صد تای بقیه اش نمیدونم برای چیه و همینطوری با همون چهار تا راهش میندازم. این مدلی هیچ راهکاری به درد شما نمیخوره، چون یادگیری هر مبحث جدیدی نیاز به صرف زمان و حوصله داره که ظاهرا ندارید. حوصله مطالعه مستندات VSS رو ندارید، یکسره میپرید سر استفاده از alphavss که قراره رابط VSS باشه. که اینم درست نیست، alphavss که قرار نیست هر مساله ریزی رو در VSS مجددا در مستنداتش شرح بده، شرح اجزاء خودش رو میده. بر چه اساسی از ابتدا برید سراغ کلاس های alphavss وقتی خود VSS براتون جای ابهام داره. از طرف دیگه حوصله خوندن کامل مستندات alphavss رو هم ندارید، همینطور با جستجو دنبال یک متد میگردید که بدون یادگیری کامل مستندات کار تون راه بیافته. راهکار جدید هم پیدا کنید باز همین بساطه دیگه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اولا من گفتم شک دارم، نگفتم نمیشه. شما بررسی کردید و به این نتیجه رسیدید که alphavss در پروسه مجزا کار می کنه که میگید نمیشه؟ ثانیا دنبال راهکار دیگه ای هستید، شاید باشه، شاید اگر بگردید پنج تا راهکار دیگه پیدا کنید،
اما برای پیدا کردن هر راهکاری باید زمان صرف کنید.
یکبار بشینید برای خودتون حساب و کتاب کنید ببینید میخواهید وقت بقدر کافی صرف کنید یا نه. یک مواقعی هست، به چیزی علاقه داریم ولی حوصله و فرصتش رو نداریم، خوب قضیه منتفی میشه.
اگه حوصله شو ندارید بذاریدش کنار، اینترنت پر از معلومات نرم افزاریه که شاید اسمشونم نشنیده باشید و میتوانید هر کدومشون رو یاد بگیرید و یا نگیرید، هر روز هم مطالب جدیدی برای یادگیری هست.
اما اگر قراره مطلبی رو یادبگیرید عجولانه و بی حوصله و جسته گریخته نخونید.
alphavss که بی دلیل بزرگ نیست، خودش هیچ چیزی نیست جز یک Wrapper. این ساختار VSS ئه که بزرگه و پیچیده است. نمیشه که بگید من از این ماشین پیچیده چهار تا دکمش رو میدونم چیکار میکنه و صد تای بقیه اش نمیدونم برای چیه و همینطوری با همون چهار تا راهش میندازم. این مدلی هیچ راهکاری به درد شما نمیخوره، چون یادگیری هر مبحث جدیدی نیاز به صرف زمان و حوصله داره که ظاهرا ندارید. حوصله مطالعه مستندات VSS رو ندارید، یکسره میپرید سر استفاده از alphavss که قراره رابط VSS باشه. که اینم درست نیست، alphavss که قرار نیست هر مساله ریزی رو در VSS مجددا در مستنداتش شرح بده، شرح اجزاء خودش رو میده. بر چه اساسی از ابتدا برید سراغ کلاس های alphavss وقتی خود VSS براتون جای ابهام داره. از طرف دیگه حوصله خوندن کامل مستندات alphavss رو هم ندارید، همینطور با جستجو دنبال یک متد میگردید که بدون یادگیری کامل مستندات کار تون راه بیافته. راهکار جدید هم پیدا کنید باز همین بساطه دیگه.

سلام استاد علی
چرا با این لحن صحبت میکنین؟ یه کم بخندین :green: آدم میترسه سئوال بپرسه.
خوب من جستجو میکنم و گاها جواب نمیگیرم ، گاها هم به قول تون سطحی میخونم ولی اون مقالاتی که فکر میکنم به کارم بیشتر میاد را تا آخر میخونم حالا ممکنه بخاطر اینکه بعضی از مسائل اش را ندونم ، متوجه نشم . بعضی ها دا که اصلا نتیجه ی خاصی پیدا نمیکنم. در این صورت ، لینک هایی که شما میدین را معمولا تا آخر میخونم. کلا منظورم اینه که این طور نیست که اغلب مطالب را سرسرکی بخونم .

_____________________

یه مطلبی در این باره پیدا کردم ببینید :

pinvoke.net: CoInitializeSecurity (ole32)

اگه اشتباه متوجه نشده باشم ، میگه اتریباتس staThreading بصورت ضمنی و مخفیانه ، داخل خودش ، متد CoInitialize را فراخونی میکنه که اون هم متد CoInitializeSecurity را فراخونی میکنه . از اونجایی که این متد فقط یه بار باید فراخونی بشه وگرنه ارور RPC_E_TOO_LATE رو میده ، پس این اتریباتس staThreading را باید از متد main حذف کرد .
در پاراگراف دوم هر چند میگه باید براش توی زبان های unmanaged یه تابع و اینا درست کرد و در زبان های unmanaged فراخونی شون کرد ولی خوب قطعا میشه توی سی شارپ هم توسط DllImport بصورت مستقیم فراخونی کرد که توی کد هم همین رو آورد .
بعد هم میگه گزینه ی Visual Studio Hosting Process که بصورت پیش فرض فعال هست ، باعث میشه همین متد CoInitializeSecurity فراخونی بشه که باید این گزینه را غیر فعال کنید .

حالا اینهایی که متوجه شدم ، درسته و کلا مقاله اش به این موضوع ربط داره دیگه؟ اگه ربط نداره ، لطف میکنین لینک ها و مقالاتی بدین تا بخونم؟

بعد اینکه entery point method به متد main میگن؟ حالا جایی که تنها میگن entry point ، به چی میگن؟
 

the_king

مدیرکل انجمن
یه مطلبی در این باره پیدا کردم ببینید :

pinvoke.net: CoInitializeSecurity (ole32)

اگه اشتباه متوجه نشده باشم ، میگه اتریباتس staThreading بصورت ضمنی و مخفیانه ، داخل خودش ، متد CoInitialize را فراخونی میکنه که اون هم متد CoInitializeSecurity را فراخونی میکنه . از اونجایی که این متد فقط یه بار باید فراخونی بشه وگرنه ارور RPC_E_TOO_LATE رو میده ، پس این اتریباتس staThreading را باید از متد main حذف کرد .

اون staThreading برای ارتباط بین برنامه تون و اجزاء دیگه بصورت COM لازمه، فرضا وقتی دارید از Windows Media Player یا هر ActiveX و کمپوننت COM دیگری استفاده می کنید. اینو در نظر بگیرید که اگر در برنامه تون کمپوننت COM ای دارید، حذف staThreading در ارتباطش مشکل ساز میشه.
در پاراگراف دوم هر چند میگه باید براش توی زبان های unmanaged یه تابع و اینا درست کرد و در زبان های unmanaged فراخونی شون کرد ولی خوب قطعا میشه توی سی شارپ هم توسط DllImport بصورت مستقیم فراخونی کرد که توی کد هم همین رو آورد .
بعد هم میگه گزینه ی Visual Studio Hosting Process که بصورت پیش فرض فعال هست ، باعث میشه همین متد CoInitializeSecurity فراخونی بشه که باید این گزینه را غیر فعال کنید .

حالا اینهایی که متوجه شدم ، درسته و کلا مقاله اش به این موضوع ربط داره دیگه؟ اگه ربط نداره ، لطف میکنین لینک ها و مقالاتی بدین تا بخونم؟

بله، درسته و مربوط به موضوع.
بعد اینکه entery point method به متد main میگن؟ حالا جایی که تنها میگن entry point ، به چی میگن؟
بله، مفهوم entry point مستقل از زبانه. هر برنامه های از بخش های مختلفی تشکیل شده، بخش کد، بخش داده و منابع و ... اون نقطه شروعی که کد اجرایی اولیه برنامه هست و اجرا از اون موقعیت شروع میشه entry point ئه.
اون main اسمی است که در برخی زبان های متداول برای متد آغازین در نظر گرفته شده، یعنی متدی مشخصی برایش وجود داره وگرنه اینکه متد باشه یا اسمش main باشه یک تعریف داخل زبانیه، در همه زبان ها main نیست.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اون staThreading برای ارتباط بین برنامه تون و اجزاء دیگه بصورت COM لازمه، فرضا وقتی دارید از Windows Media Player یا هر ActiveX و کمپوننت COM دیگری استفاده می کنید. اینو در نظر بگیرید که اگر در برنامه تون کمپوننت COM ای دارید، حذف staThreading در ارتباطش مشکل ساز میشه.

بله، درسته و مربوط به موضوع.

بله، مفهوم entry point مستقل از زبانه. هر برنامه های از بخش های مختلفی تشکیل شده، بخش کد، بخش داده و منابع و ... اون نقطه شروعی که کد اجرایی اولیه برنامه هست و اجرا از اون موقعیت شروع میشه entry point ئه.
اون main اسمی است که در برخی زبان های متداول برای متد آغازین در نظر گرفته شده، یعنی متدی مشخصی برایش وجود داره وگرنه اینکه متد باشه یا اسمش main باشه یک تعریف داخل زبانیه، در همه زبان ها main نیست.

سلامی مجدد استاد علی . خیلی ممنونم
طبق همون لینکی که دادم ، کد زیر را نوشتم :


کد:
    public static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>

        //[STAThread]
        static void Main()
        {
            //Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
            Thread.CurrentThread.ApartmentState = ApartmentState.STA;

            int res = CoInitSecure.CoInitializeSecurity(, -1, IntPtr.Zero,
        IntPtr.Zero, RpcAuthnLevel.PktPrivacy,
        RpcImpLevel.Identify, IntPtr.Zero, EoAuthnCap.None, IntPtr.Zero);
           

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());

        }
    }

دقت کنید که اتریباتس [STAThread] را کامنت کردم و غیر فعال هه .
گزینه ی "Visual Studio Hosting Process" را هم در ویژال استودیو 2017 اصلا ندیدم و این جور که تحقیق کردم ، انگار توی 2017 ، برداشتن اش (انگار توی نسخه ی 2015 وجود داشت)
با این حال ، وقتی قبل و حتی بعد از اجرای خط اول متد main ، مقدار ApartmentState نخ جاری را استعلام میگیرم ، در هر دو ، مقدار ApartmentState.MTA داره (با اونکه مقدار STA را در خط اول تابع دادم) .
اگه مقدار ApartmentState نخ اصلی ، ApartmentState.MTA نمیشه com ها را در اون فراخونی کرد؟ الان توابع CoInitializeSecurity و همچنین استراکچر SECURITY_DESCRIPTOR ، جزء com ها هستن دیگه؟ درسته؟ :

CoInitializeSecurity function

_SECURITY_DESCRIPTOR

وقتی هم با متد SetApartmentState بجای پروپرتی ApartmentState ، این کار را انجام میدم ، کلا با خطا متوقف میشه .
بعد اینکه طبق توضیحات remark تابع CoInitializeSecurity ، این طور که متوجه شدم در پارامتر اول این تابع ، مقدار استراکچر SECURITY_DESCRIPTOR را باید بدیم و در این مورد بکار ما میاد .
فیلدهای این استراکچر هم توضیحاتش خودش داستان داره :

[MS-DTYP]: SECURITY_DESCRIPTOR

حالا میخواستم بهتون بگم به نظرتون الان که نخ اصلی ام با اون کد بالا ، باز هم نوع MTA (بجای STA) هست ، اصلا میشه از این متدها و استتراکچرهای api ویندوز استفاده و فراخونی کرد؟ اگه نمیشه که بی خیال این تابع بشم وگرنه روی اعضای استراکچر SECURITY_DESCRIPTOR کار کنم .

یا اینکه به نظرتون ویژال استودیو 2015 را بخاطر داشتن گزینه ی "Visual Studio Hosting Process" نصبش کنم تا غیر فعالش کنم شاید کد بالا برای STA جواب داد؟
 

the_king

مدیرکل انجمن
سلامی مجدد استاد علی . خیلی ممنونم
طبق همون لینکی که دادم ، کد زیر را نوشتم :


کد:
    public static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>

        //[STAThread]
        static void Main()
        {
            //Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
            Thread.CurrentThread.ApartmentState = ApartmentState.STA;

            int res = CoInitSecure.CoInitializeSecurity(, -1, IntPtr.Zero,
        IntPtr.Zero, RpcAuthnLevel.PktPrivacy,
        RpcImpLevel.Identify, IntPtr.Zero, EoAuthnCap.None, IntPtr.Zero);
          

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());

        }
    }

دقت کنید که اتریباتس [STAThread] را کامنت کردم و غیر فعال هه .
گزینه ی "Visual Studio Hosting Process" را هم در ویژال استودیو 2017 اصلا ندیدم و این جور که تحقیق کردم ، انگار توی 2017 ، برداشتن اش (انگار توی نسخه ی 2015 وجود داشت)
با این حال ، وقتی قبل و حتی بعد از اجرای خط اول متد main ، مقدار ApartmentState نخ جاری را استعلام میگیرم ، در هر دو ، مقدار ApartmentState.MTA داره (با اونکه مقدار STA را در خط اول تابع دادم) .

مقداری که به ApartmentState میدهید نادیده گرفته میشه. در حال پیشرفت هستید ولی همچنان هر موردی رو که استفاده می کنید، مستنداتش رو هم بخونید که دلیل این موارد براتون مشخص بشه.
Thread.ApartmentState Property (System.Threading)
مقدار پیشفرض ApartmentState.MTA ئه، مگر اینکه قبل از زمانی که نخ تشکیل میشه با STAThread برایش مدل متفاوتی تعیین بشه و بعد از اینکه نخ ایجاد شد هم دیگه تغییر مقادیر ApartmentState نادیده گرفته میشه، چون قبلش یکبار تعیین شده.
اگه مقدار ApartmentState نخ اصلی ، ApartmentState.MTA نمیشه com ها را در اون فراخونی کرد؟

مشکل ایجاد می کنه، به این شکل که COM فقط برای STA هماهنگسازی فراخوانی رو انجام میده و ActiveX ها هم که کلا در حالت STA کار می کنند.

الان توابع CoInitializeSecurity و همچنین استراکچر SECURITY_DESCRIPTOR ، جزء com ها هستن دیگه؟ درسته؟ :

CoInitializeSecurity function

_SECURITY_DESCRIPTOR

وقتی هم با متد SetApartmentState بجای پروپرتی ApartmentState ، این کار را انجام میدم ، کلا با خطا متوقف میشه .

CoInitializeSecurity بله ولی SECURITY_DESCRIPTOR مختص COM نیست.

وقتی هم با متد SetApartmentState بجای پروپرتی ApartmentState ، این کار را انجام میدم ، کلا با خطا متوقف میشه .

توضیحات متد ها رو بخونید، وقتی نخ ایجاد شده و در حال اجرا است که دیگه نمیتونه مدلش رو تغییر بده. این متد برای زمانی کاربرد داره که نخی دارید که هنوز Start نشده.
Thread.SetApartmentState(ApartmentState) Method (System.Threading)

بعد اینکه طبق توضیحات remark تابع CoInitializeSecurity ، این طور که متوجه شدم در پارامتر اول این تابع ، مقدار استراکچر SECURITY_DESCRIPTOR را باید بدیم و در این مورد بکار ما میاد .
فیلدهای این استراکچر هم توضیحاتش خودش داستان داره :

[MS-DTYP]: SECURITY_DESCRIPTOR

حالا میخواستم بهتون بگم به نظرتون الان که نخ اصلی ام با اون کد بالا ، باز هم نوع MTA (بجای STA) هست ، اصلا میشه از این متدها و استتراکچرهای api ویندوز استفاده و فراخونی کرد؟ اگه نمیشه که بی خیال این تابع بشم وگرنه روی اعضای استراکچر SECURITY_DESCRIPTOR کار کنم .
اگه در برنامه تون به هر دلیلی از ActiveX ها استفاده می کنید که نمی توانید با این حالت MTA ادامه بدید، و کلا اجزائی که با نخ ایجاد کننده فرم ارتباط دارند میتوانند با MTA ناسازگار باشند.
اما در مورد ارتباطات COM دیگه ای که ActiveX نیستند، مثل VSS، نمیشه قطعی گفت کار می کنند یا نه. بستگی به اون موردی داره که باهاش کار می کنید. در مورد VSS که راحت می توانید بدون توجه به اون کدهایی که برای دسترسی میخواستید بنویسید امتحان کنید که کد هایی که قبلا برای alphavss کار می کردند با این حالت MTA همچنان کار می کنند یا نه. اگر کار کنند نباید مشکلی با MTA داشته باشید.
یا اینکه به نظرتون ویژال استودیو 2015 را بخاطر داشتن گزینه ی "Visual Studio Hosting Process" نصبش کنم تا غیر فعالش کنم شاید کد بالا برای STA جواب داد؟
به نظرم منطقی نمیاد. Visual Studio Hosting Process برای Debug کردن در داخل محیط ویژوال استدیو است، وقتی فایل اجرایی Build شده رو مستقل از ویژوال استدیو اجرا می کنید دیگه نه Visual Studio Hosting Process نقشی داره و نه تفاوتی میان 2015 و 2017 هست.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
مقداری که به ApartmentState میدهید نادیده گرفته میشه. در حال پیشرفت هستید ولی همچنان هر موردی رو که استفاده می کنید، مستنداتش رو هم بخونید که دلیل این موارد براتون مشخص بشه.
Thread.ApartmentState Property (System.Threading)
مقدار پیشفرض ApartmentState.MTA ئه، مگر اینکه قبل از زمانی که نخ تشکیل میشه با STAThread برایش مدل متفاوتی تعیین بشه و بعد از اینکه نخ ایجاد شد هم دیگه تغییر مقادیر ApartmentState نادیده گرفته میشه، چون قبلش یکبار تعیین شده.

مشکل ایجاد می کنه، به این شکل که COM فقط برای STA هماهنگسازی فراخوانی رو انجام میده و ActiveX ها هم که کلا در حالت STA کار می کنند.


CoInitializeSecurity بله ولی SECURITY_DESCRIPTOR مختص COM نیست.


توضیحات متد ها رو بخونید، وقتی نخ ایجاد شده و در حال اجرا است که دیگه نمیتونه مدلش رو تغییر بده. این متد برای زمانی کاربرد داره که نخی دارید که هنوز Start نشده.
Thread.SetApartmentState(ApartmentState) Method (System.Threading)


اگه در برنامه تون به هر دلیلی از ActiveX ها استفاده می کنید که نمی توانید با این حالت MTA ادامه بدید، و کلا اجزائی که با نخ ایجاد کننده فرم ارتباط دارند میتوانند با MTA ناسازگار باشند.
اما در مورد ارتباطات COM دیگه ای که ActiveX نیستند، مثل VSS، نمیشه قطعی گفت کار می کنند یا نه. بستگی به اون موردی داره که باهاش کار می کنید. در مورد VSS که راحت می توانید بدون توجه به اون کدهایی که برای دسترسی میخواستید بنویسید امتحان کنید که کد هایی که قبلا برای alphavss کار می کردند با این حالت MTA همچنان کار می کنند یا نه. اگر کار کنند نباید مشکلی با MTA داشته باشید.

به نظرم منطقی نمیاد. Visual Studio Hosting Process برای Debug کردن در داخل محیط ویژوال استدیو است، وقتی فایل اجرایی Build شده رو مستقل از ویژوال استدیو اجرا می کنید دیگه نه Visual Studio Hosting Process نقشی داره و نه تفاوتی میان 2015 و 2017 هست.

سلامی مجدد
ممنون استاد علی
پس کلا این مسئله ی CoInitializeSecurity را بی خیال شم؟ چون یه عالمه روش وقت بذارم اما در آینده کدی که مینویسم را ساپورت نکنه چی؟
یا اینکه شما اتریباتس ای نمیشناسید که بجای STAThread استفاده کنم اما مثل STAThread بصورت ضمنی و داخل خودش ، تابع CoInitializeSecurity را فراخونی نکنه؟
نمیدونم چرا پس داخل اون لینک ، کد تغییر ApartmentState را داد (وقتی کار نمیکرد) .
بعد اینکه در لینک زیر ، با اونکه خودش میگه فراخونی این متدها (CoInitializeSecurity) ، بی فایده هست چون قبل از اجرای پروسه باید فراخونی بشن ، اما مثل کد قبلی ، باز هم در متد main داره فراخونی میکنه :

Rules explorer

یا این نمونه ی دیگه :

VB.NET and CoInitializeSecurity() ? | Keysight Community

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


بعد اینکه الان به همه ی متدهای api ویندوز ، com (component object model) میگن؟ درسته؟ یعنی به استراکچر و اینها در api ویندوز که com نمیگن؟ اصلا com ها اومدن که بر اساس غیر شی گرایی (مثل توابع و متدهای api ویندوز) ساخته بشن تا همه ی زبان ها(ی شی گرا یا غیر شی گرا) بتونن ازش استفاده کنن دیگه . درسته؟
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلامی مجدد
ممنون استاد علی
پس کلا این مسئله ی CoInitializeSecurity را بی خیال شم؟ چون یه عالمه روش وقت بذارم اما در آینده کدی که مینویسم را ساپورت نکنه چی؟
من که نمیدونم شما در آینده چه کدی می نویسید، اما حداقل این رو میدونم که مجبور نیستید یک فایل اجرایی بسازید و همه کارها رو داخل همون انجام بدید. می توانید برای خودتان یک Solution بسازید که کنار پروژه اصلی تان یک یا چند پروژه اجرایی دیگه باشه برای مواردی که نمیخواهید قاطی پروژه اصلی باشه. که فرضا با MTA بجای STA کار کنه. هر جا لازم شد با Process.Start فراخوانیش می کنید که کار خاصی رو در پروسه مستقل انجام بده.

یا اینکه شما اتریباتس ای نمیشناسید که بجای STAThread استفاده کنم اما مثل STAThread بصورت ضمنی و داخل خودش ، تابع CoInitializeSecurity را فراخونی نکنه؟
در #C همچین چیزی رو ندیدم.
نمیدونم چرا پس داخل اون لینک ، کد تغییر ApartmentState را داد (وقتی کار نمیکرد) .
طبعا هر کسی که خودش مستقلا شیء از Thread میسازه میتونه از ApartmentState استفاده کنه، البته میکرد چون دیگه منسوخ شده و نباید استفاده بشه.

بعد اینکه در لینک زیر ، با اونکه خودش میگه فراخونی این متدها (CoInitializeSecurity) ، بی فایده هست چون قبل از اجرای پروسه باید فراخونی بشن ، اما مثل کد قبلی ، باز هم در متد main داره فراخونی میکنه :

Rules explorer
اونکه خودش بالای کد ها داره میگه این کد Noncompliant ئه.
یا این نمونه ی دیگه :


VB.NET and CoInitializeSecurity() ? | Keysight Community

الان به نظرتون این کدهاش را تست کنم؟

تاپیکی که کسی درخواستی کرده و در پایان تاپیک به جواب نرسیده تاپیک بی سر انجامیه و طبعا کدش هم جواب نمیده.
برای راهکارهای دیگه (برای محافظت از بکاپ ها که هر کسی نتونه حذف کنه) ، من دقیقا باید چه چیزی را جستجو کنم؟ یا کدوم منبع را بخونم؟ جستجو کردم ولی مطالب خاصی گیرم نیومد .
یا اینکه به نظرتون کلا بی خیال محافظت از بکاپ ها بشم؟
اولا روی میزان حفاظتی که تو ذهنتونه فکر کنید، ادمین سیستم و کسی که میتونه سطح دسترسی ها رو تغییر بده به هر حالت میتونه راهکاری برای حذف موردی پیدا کنه. شما اگر دنبال راه حلی برای حذف اون موارد بگردید که میگید نمیشه حذف بشه، شاید از سطح حفاظتش مایوس بشید. حفاظت نرم افزاری هم وقتی موثره که خود نرم افزار فعاله، همانطور که هیچ ویروس کشی جلوی غیر فعال شدن یا حذف شدن خودشو نمیتونه بگیره. شما کل اینترنت رو هم بگردید راهکاری پیدا نمی کنید که قاطعانه برای حذف ناپذیری باشه، همونقدر تخیلی ئه که بگیم چیکار کنیم که صفحه کلید بندری برقصه. VSS سرویسی ئه که کاربرد اصیلش روی سرور ها بوده، و باید خدماتش از دسترسی کاربران متفرقه و نرم افزار های مخرب حفاظت بشه، که طبعا همین تدابیر روی سرور ها هست، خود vssadmin هم که برای کاربران غیر ادمین دسترسی میانبر ایجاد نمی کنه. برای همینه که همچین نیازی که شما تو ذهن دارید خیلی برای سایرین مطرح نبوده، مخصوصا که خود VSS برای برنامه نویسان عادی جذابیت آنچنانی نداره. مزیت VSS در پشتیبانگیری بدون نیاز به توقف سایر عملیات ها است که اونم بیشترین کاربردش در نرم افزار های تحت سرور ئه.
بعد اینکه الان به همه ی متدهای api ویندوز ، com (component object model) میگن؟ درسته؟ یعنی به استراکچر و اینها در api ویندوز که com نمیگن؟ اصلا com ها اومدن که بر اساس غیر شی گرایی (مثل توابع و متدهای api ویندوز) ساخته بشن تا همه ی زبان ها(ی شی گرا یا غیر شی گرا) بتونن ازش استفاده کنن دیگه . درسته؟
نه. ابدا. اولا بیشتر متد های API که اصلا داخل شیء خاصی نیستند چون پایه شون زبان C ئه که اصلا کلاس و شیء گرایی داخلش وجود نداره و وقتی شیء و object ای در کار نیست، اینترفیسی هم در کار نیست.
ثانیا COM صرفا یک مدل ارتباطیه، بین انواع مدلهای ارتباطی موجود. و مفهوم متد ربطی به مدل ارتباطی COM نداره.
COM بوجود اومده تا زبان های برنامه نویسی متفاوت زمان خودش بتوانند با یک استاندارد یکسان و مشخص با هم تعامل داشته باشند، ربطی به این نداره که خود یک زبان شیء گرا بوده یا نه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون استاد علی
پس جسارتا استاد علی میتونین توی مقداردهی استراکچر SECURITY_DESCRIPTOR بهم کمک کنین؟ چون من جاهایی شو متوجه نشدم چی میگه .
چندین تا سئوال دارم :
1) الان طبق این لینک :

_SECURITY_DESCRIPTOR

این استراکچر ، 7 فیلد Revision و Sbz1 و Control و Owner و Group و Sacl و Dacl داره دیگه . درسته؟
که در لینک زیر :

[MS-DTYP]: SECURITY_DESCRIPTOR

فیلد Owner با OffsetOwner و Group با OffsetGroup و Sacl با OffsetSacl و Dacl با OffsetDacl برابری میکنه . درسته؟
اما پس در لینک آخری (بالایی) ، قسمت آخر ، 4 تا فیلد OwnerSid (variable) و GroupSid (variable) و Sacl (variable) و Dacl (variable) چرا داره؟

2) اینا درستن؟ :
- این استراکچر را در 2 حالت نسبی و مطلق میتونیم تعیین کنیم . اگه بیتِ SR (بیتِ اول یا بیت با اندیس صفر) از فیلد Control را مقدار 1 بدیم ، حالت نسبی و اگه مقدار صفر بدیم ، حالت مطلق برای این استراکچر در نظر گرفته میشه . و اگه اشتباه نکنم ، از توضیحاتش برمیاد که اگه از اشاره گرها میخوایم استفاده کنیم ، حالت نسبی تعیین بشه .
- در فیلد Control که 2 بایت هست ، طبق توضیحات جدول ، اگه میخوایم اون توضیحی که برای اون بیت داد (مثلا بیتِ SR) عملی و انجام بشه (مثلا حالت نسبی که برای این بیت توضیح داد و بخوایم این حالت را ست کنیم) ، باید مقدار اون بیت را یک وگرنه باید مقدار اون بین را صفر قرار بدیم . بعد مقدار باینری این 16 بیت را حساب کنیم و بصورت دهدهی بدیم .
- کلا همه ی فیلد ها unsigned هستن .
- فیلد Revision ، یک بایت که مقدار 1 باید براش قرار داده بشه .
- فیلد Sbz1 ، یک بایت هه که به بیتِ RM (بیتِ دوم یا بیت با اندیس یک) از فیلد Control مربوطه که اگه بیت RM از فیلد Control ، به مقدار 1 ست بشه ، فیلد Sbz1 به عنوان بیتِ کنترل مدیریت کننده ی منابع تفسیر میشه (که این یعنی چی ، نمیدونم) اما اینکه مقدار فیلد Sbz1 را چند بذاریم ، چیزی نگفت .
- فیلد Control ، دو بایت هست که هر بیت اش توضیح داره ولی من توضیحاتش را متوجه نمیشم که منظورشون چیه . میشه درباره ی این بیت ها راهنمایی ام کنید؟

3) 4 فیلد آخر ، 4 بایت unsigned هستن که اشاره گر هستن .
- فیلد OffsetOwner ، اشاره گر به استراکچر RPC_SID هست؟ :

[MS-DTYP]: RPC_SID

[MS-DTYP]: SID--Packet Representation

[MS-DTYP]: SID

- فرق فیلدهای OffsetOwner و OffsetGroup را من دقیقا متوجه نشدم . هر دو اشاره گر به استراکچر RPC_SID هستن؟
فیلد OffsetSacl و استراکچر RPC_SID و بقیه ی استراکچر را در مرحله ی بعد سراغش میرم
خیلی ممنونم
 

the_king

مدیرکل انجمن
ممنون استاد علی
پس جسارتا استاد علی میتونین توی مقداردهی استراکچر SECURITY_DESCRIPTOR بهم کمک کنین؟ چون من جاهایی شو متوجه نشدم چی میگه .
چندین تا سئوال دارم :
1) الان طبق این لینک :

_SECURITY_DESCRIPTOR

این استراکچر ، 7 فیلد Revision و Sbz1 و Control و Owner و Group و Sacl و Dacl داره دیگه . درسته؟
که در لینک زیر :

[MS-DTYP]: SECURITY_DESCRIPTOR

فیلد Owner با OffsetOwner و Group با OffsetGroup و Sacl با OffsetSacl و Dacl با OffsetDacl برابری میکنه . درسته؟
اما پس در لینک آخری (بالایی) ، قسمت آخر ، 4 تا فیلد OwnerSid (variable) و GroupSid (variable) و Sacl (variable) و Dacl (variable) چرا داره؟

منم اگه مثل شما مطالعه کنم چیزی متوجه نمیشم. مطلبی که خودتون جستجو می کنید رو درست نمی خونید. هنوز نخونده میپرید سر پیاده سازی.

تو همون لینک اول خودش نوشته که :
Because the internal format of a security descriptor can vary, we recommend that applications not modify the SECURITY_DESCRIPTOR structure directly.
نه طولش ثابته و نه فیلد های داخلش موقعیت ثابتی دارند و نه ضمانتی هست که در سیستم عامل های بعدی چیزی تغییر نکنه یا بهش اضافه نشه.
وقتی خودش میگه قرار نیست خودتون دستی داده دهی کنید و زیر صفحه اش هم یک لیست از متد های دریافت و مقدار دهی قرار داده، وقت برای تفسیر چی میذارید؟
از اون توابع API که زیرش لیست شده برای ایجاد و مقدار دهی اش استفاده می کنند، نه اینکه دستی داده در حافظه ای که نمیدونید قراره چه فرمتی داشته باشه پر کنید.
دسترسی های یک شیء ممکنه خیلی پیچیده و مفصل باشه، برای همین یک ساختار ثابت با طول مشخص نمیتونه همچین مشخصاتی رو ثبت کنه.
اگر شیء ای فرضا یک فولدر یا شاخه Key در رجیستری دارید، Owner کاربر یا مجموعه کاربرانی است ئه که مالک اونه و طبعا حداکثر دسترسی های ممکن رو بهش داره.
Group یک مجموعه ای کاربری ئه که دسترسی مشخصی بهش دارند و هر کاربری هم که بعدا به اون مجموعه اضافه بشه بصورت خودکار همون دسترسی ها رو شامل میشه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
منم اگه مثل شما مطالعه کنم چیزی متوجه نمیشم. مطلبی که خودتون جستجو می کنید رو درست نمی خونید. هنوز نخونده میپرید سر پیاده سازی.

تو همون لینک اول خودش نوشته که :

نه طولش ثابته و نه فیلد های داخلش موقعیت ثابتی دارند و نه ضمانتی هست که در سیستم عامل های بعدی چیزی تغییر نکنه یا بهش اضافه نشه.
وقتی خودش میگه قرار نیست خودتون دستی داده دهی کنید و زیر صفحه اش هم یک لیست از متد های دریافت و مقدار دهی قرار داده، وقت برای تفسیر چی میذارید؟
از اون توابع API که زیرش لیست شده برای ایجاد و مقدار دهی اش استفاده می کنند، نه اینکه دستی داده در حافظه ای که نمیدونید قراره چه فرمتی داشته باشه پر کنید.
دسترسی های یک شیء ممکنه خیلی پیچیده و مفصل باشه، برای همین یک ساختار ثابت با طول مشخص نمیتونه همچین مشخصاتی رو ثبت کنه.
اگر شیء ای فرضا یک فولدر یا شاخه Key در رجیستری دارید، Owner کاربر یا مجموعه کاربرانی است ئه که مالک اونه و طبعا حداکثر دسترسی های ممکن رو بهش داره.
Group یک مجموعه ای کاربری ئه که دسترسی مشخصی بهش دارند و هر کاربری هم که بعدا به اون مجموعه اضافه بشه بصورت خودکار همون دسترسی ها رو شامل میشه.

آو این گونه هست :green: من لِکِّ لِکِّ (یعنی آروم آروم و کند) داشتم اون لینک دومی را بررسی میکردم . :green:
خیلی ممنونم .
اما من دقیق متوجه نشدم . الان منظور شما اینه که طول این استراکچر ثابت نیست؟ به این معنی که طول فیلدهاش ممکنه تغییر کنه؟
اگه این طوره ، چجوری میشه اندازه ی فیلدهای اون استراکچر را در سی شارپ مشخص کرد؟ چون باید طول ثابتی داشته باشن تا مشخص کنیم دیگه . فکر نکنم منظورتون این بوده باشه . درسته؟
الان یعنی طول فیلد Revision وSbz1 را از نوع byte (یک بایت unsigned) و طول فیلد Control را از نوع ushort (دو بایت unsigned) و طول بقیه ی فیلدها یعنی فیلدهای Owner و Group و Sacl و Dacl را از نوع uint (چهار بایت unsigned _ از نوع UIntPtr نگرفتم چون پروسه ام any cpu هست و توی سیستم عامل های 32 و 64 بیتی مقدار UIntPtr متفاوت میشه) باید بگیرم دیگه . درسته؟
بعد هم موقع ایجاد شی ، با اون توابع هایی که گفتین که زیرش لیست کرد ، هر فیلد را با توابع مربوط به اون فیلد ، مقداردهی کنم . درسته؟

راستی ، پارامترهای متد CoInitializeSecurity را جاهایی که اشاره گر نیاز داشت را IntPtr در نظر گرفتم . این ها را هم باید از نوع uint در نظر بگیرم دیگه؟ درسته؟ (بخاطر اینکه پروسه ام any cpu هست و توی سیستم عامل های 32 و 64 بیتی مقدار UIntPtr متفاوت میشه)
جانِ بِرار (یعنی جانِ برادر) عصبانی نشین از سئوالاتم ها :green: . خوب نمیدونم دیگه . جستجو هم کردم . خوب توان من اینه .
 
آخرین ویرایش:

the_king

مدیرکل انجمن
آو این گونه هست :green: من لِکِّ لِکِّ (یعنی آروم آروم و کند) داشتم اون لینک دومی را بررسی میکردم . :green:
خیلی ممنونم .
اما من دقیق متوجه نشدم . الان منظور شما اینه که طول این استراکچر ثابت نیست؟ به این معنی که طول فیلدهاش ممکنه تغییر کنه؟
اگه این طوره ، چجوری میشه اندازه ی فیلدهای اون استراکچر را در سی شارپ مشخص کرد؟ چون باید طول ثابتی داشته باشن تا مشخص کنیم دیگه . فکر نکنم منظورتون این بوده باشه . درسته؟
الان یعنی طول فیلد Revision وSbz1 را از نوع byte (یک بایت unsigned) و طول فیلد Control را از نوع ushort (دو بایت unsigned) و طول بقیه ی فیلدها یعنی فیلدهای Owner و Group و Sacl و Dacl را از نوع uint (چهار بایت unsigned _ از نوع UIntPtr نگرفتم چون پروسه ام any cpu هست و توی سیستم عامل های 32 و 64 بیتی مقدار UIntPtr متفاوت میشه) باید بگیرم دیگه . درسته؟

تکرار می کنم، شما قرار نیست ساختار SECURITY_DESCRIPTOR رو در #C تعریف کنید، به چند دلیل. اول اینکه ساختار مشخص و ثابتی نداره، طولش متغیره، فیلد هاش موقعیت ثابتی نداره و در آینده هم میتونه تغییر کنه و قرار هم نیست خودتون نه از فیلد ها مقدار بخونید و نه بنویسید و نه فیلد ها رو مشخص کنید. برای چندمین بار میگم، توضیحاتی که در سایت مایکروسافت نوشته شده رو بخونید. در همون تاپیک ها حتما مثالشم داره. اگر مطالعه میکردید متوجه میشدید که بجای اینکه روی فیلد های ساختار SECURITY_DESCRIPTOR فکر کنید، باید یک حافظه بطول حداقلی SECURITY_DESCRIPTOR_MIN_LENGTH با Marshal.AllocHGlobal بسازید و بعد با InitializeSecurityDescriptor یک SECURITY_DESCRIPTOR حداقلی داخلش ایجاد کنید و بعد به تدریج با توابع مربوطه تکمیلش کنید و ...

راستی ، پارامترهای متد CoInitializeSecurity را جاهایی که اشاره گر نیاز داشت را IntPtr در نظر گرفتم . این ها را هم باید از نوع uint در نظر بگیرم دیگه؟ درسته؟ (بخاطر اینکه پروسه ام any cpu هست و توی سیستم عامل های 32 و 64 بیتی مقدار UIntPtr متفاوت میشه)

نه، برای آدرس حافظه از uint و int هر داده عددی با طول ثابت دیگه ای استفاده نکنید، مگر اینکه از قبل مشخصا میدانید که هرگز این برنامه فرضا در حالت 64 بیتی اجرا نخواهد شد و آدرس حافظه حتما 32 بیتی است که اونم باز با وجود اینکه درسته و کار میکنه توصیه نمیشه، IntPtr همیشه گزینه بهتریه و توصیف بهتری هم از آدرس حافظه است.
چون uint یک داده عددی با طول مشخص و ثابته و بر اساس مدل حافظه 32 بیتی و 64 بیتی نخواهد شد. از IntPtr برای آدرس حافظه استفاده میشه، چون به مدل حافظه مرتبطه و ماشین مجازی بر اساس مدل حافظه ای که داخلش اجرا انجام میشه، میتونه در مورد 32 بیتی و 64 بیتی بودنش تصمیم بگیره و برایش طول تعیین کنه. اگر طول داده ای که برای آدرس حافظه بکار میبرید با مدل حافظه جور نباشه که داده های پشته اشتباه میشه و برنامه هم کار نخواهد کرد.
تمامی متد و ساختار هایی که از خارج محیط Managed باهاشون در ارتباط هستید، یا بر اساس مدل حافظه برنامه خودتون منطبق میشن یا صراحتا در راهنماشون هست که این نسخه 32 بیتی یا 64 بیتی ئه. در مورد API ویندوز طبعا مشکلی نیست ولی گاهی با کتابخانه هایی کار خواهید کرد که فرضا نسخه شون 64 بیتی یا 32 بیتی ئه و بخاطر اون تنظیمات Build پروژه خودتان را تغییر خواهید داد، نه اینکه IntPtr رو به نوع داده دیگری تغییر بدید.
بعد هم موقع ایجاد شی ، با اون توابع هایی که گفتین که زیرش لیست کرد ، هر فیلد را با توابع مربوط به اون فیلد ، مقداردهی کنم . درسته؟

از اون توابع استفاده می کنید ولی کاری با فیلد ها ندارید، نه اون توابع از شما فیلد میخوان و نه به شما موقعیت فیلد تحویل میدن. با شروع آدرس حافظه SECURITY_DESCRIPTOR کار دارن نه فیلد های داخلش.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
تکرار می کنم، شما قرار نیست ساختار SECURITY_DESCRIPTOR رو در #C تعریف کنید، به چند دلیل. اول اینکه ساختار مشخص و ثابتی نداره، طولش متغیره، فیلد هاش موقعیت ثابتی نداره و در آینده هم میتونه تغییر کنه و قرار هم نیست خودتون نه از فیلد ها مقدار بخونید و نه بنویسید و نه فیلد ها رو مشخص کنید. برای چندمین بار میگم، توضیحاتی که در سایت مایکروسافت نوشته شده رو بخونید. در همون تاپیک ها حتما مثالشم داره. اگر مطالعه میکردید متوجه میشدید که بجای اینکه روی فیلد های ساختار SECURITY_DESCRIPTOR فکر کنید، باید یک حافظه بطول حداقلی SECURITY_DESCRIPTOR_MIN_LENGTH با Marshal.AllocHGlobal بسازید و بعد با InitializeSecurityDescriptor یک SECURITY_DESCRIPTOR حداقلی داخلش ایجاد کنید و بعد به تدریج با توابع مربوطه تکمیلش کنید و ...

خیلی ممنون استاد علی
الان منظورتون از SECURITY_DESCRIPTOR_MIN_LENGTH ، متد GetSecurityDescriptorLength هست؟ :

GetSecurityDescriptorLength function

چون چیزی به عنوان SECURITY_DESCRIPTOR_MIN_LENGTH پیدا نکردم .
اون متد GetSecurityDescriptorLength هم به عنوان ورودی ، شی ای از استراکچر SECURITY_DESCRIPTOR میخواد . پس باید این استراکچر را با فیلدهاش و سایز فیلدهاش را توی سی شارپ تعریف کنیم تا ازش شی بسازیم دیگه .
بقیه ی متدها مثل InitializeSecurityDescriptor و GetSecurityDescriptorControl و ... هم به عنوان ورودی متدشون ، شی ای از این استراکچر میخوان و همینطور گاها بقیه ی پارامترها را هم میخوان .


نه، برای آدرس حافظه از uint و int هر داده عددی با طول ثابت دیگه ای استفاده نکنید، مگر اینکه از قبل مشخصا میدانید که هرگز این برنامه فرضا در حالت 64 بیتی اجرا نخواهد شد و آدرس حافظه حتما 32 بیتی است که اونم باز با وجود اینکه درسته و کار میکنه توصیه نمیشه، IntPtr همیشه گزینه بهتریه و توصیف بهتری هم از آدرس حافظه است.
چون uint یک داده عددی با طول مشخص و ثابته و بر اساس مدل حافظه 32 بیتی و 64 بیتی نخواهد شد. از IntPtr برای آدرس حافظه استفاده میشه، چون به مدل حافظه مرتبطه و ماشین مجازی بر اساس مدل حافظه ای که داخلش اجرا انجام میشه، میتونه در مورد 32 بیتی و 64 بیتی بودنش تصمیم بگیره و برایش طول تعیین کنه. اگر طول داده ای که برای آدرس حافظه بکار میبرید با مدل حافظه جور نباشه که داده های پشته اشتباه میشه و برنامه هم کار نخواهد کرد.
تمامی متد و ساختار هایی که از خارج محیط Managed باهاشون در ارتباط هستید، یا بر اساس مدل حافظه برنامه خودتون منطبق میشن یا صراحتا در راهنماشون هست که این نسخه 32 بیتی یا 64 بیتی ئه. در مورد API ویندوز طبعا مشکلی نیست ولی گاهی با کتابخانه هایی کار خواهید کرد که فرضا نسخه شون 64 بیتی یا 32 بیتی ئه و بخاطر اون تنظیمات Build پروژه خودتان را تغییر خواهید داد، نه اینکه IntPtr رو به نوع داده دیگری تغییر بدید.

از اون توابع استفاده می کنید ولی کاری با فیلد ها ندارید، نه اون توابع از شما فیلد میخوان و نه به شما موقعیت فیلد تحویل میدن. با شروع آدرس حافظه SECURITY_DESCRIPTOR کار دارن نه فیلد های داخلش.

خیلی ممنونم
الان پس اشاره گرهای توابع و کلا اعضای api ویندوز ، مثل سی شارپ ، با 32 بیت یا 64 بیت شدن ویندوز ، تغییر اندازه میدن مگر اینکه توی توضیحات اون متد ، خودش بگه؟
 

the_king

مدیرکل انجمن
خیلی ممنون استاد علی
الان منظورتون از SECURITY_DESCRIPTOR_MIN_LENGTH ، متد GetSecurityDescriptorLength هست؟ :

نه، SECURITY_DESCRIPTOR_MIN_LENGTH یک مقدار ثابته، طول حداقلی یک SECURITY_DESCRIPTOR ئه که دیگه از اون کمتر حافظه نمیشه برایش در نظر گرفت. مثل همون مقادیر ثابتی است که در هدر های API ویندوز تعریف شده، 20 بایت. ولی GetSecurityDescriptorLength تابعی است که طول یک SECURITY_DESCRIPTOR مشخص رو براتون اعلام می کنه که ممکنه بیشتر از این مقدار حداقلی باشه. وقتی هنوز SECURITY_DESCRIPTOR ای نساختید که موردی نیست که بخواهید به عنوان پارامتر به GetSecurityDescriptorLength بدهید.

چون چیزی به عنوان SECURITY_DESCRIPTOR_MIN_LENGTH پیدا نکردم .
define SECURITY_DESCRIPTOR_MIN_LENGTH رو تو گوگل جستجو کنید. همیشه سایت هایی هستند که هدر های ویندوز رو نشون میدن. البته قبلا هم بهتون نرم افزار ApiViewer رو معرفی کرده بودم.
الان پس اشاره گرهای توابع و کلا اعضای api ویندوز ، مثل سی شارپ ، با 32 بیت یا 64 بیت شدن ویندوز ، تغییر اندازه میدن مگر اینکه توی توضیحات اون متد ، خودش بگه؟
نیازی نیست در توضیحاتشون چیزی بگه، اگه به نوع داده ای که در API مشخص شده دقت کنید میبینید که عموما نوع داده اصلی زبان C++/C نیستند، یک نوع تعریف شده در هدر های ویندوز هستند که خود مایکروسافت تعریفشون کرده. فرضا HWND و HDC و HANDLE و LPDWORD و ...
خود هدر طوری نوشته شده که موقع کامپایل بر اساس تنظیمات مثلا 32 بیتی بودن یا 64 بیتی بودن حافظه تعریف متفاوتی اعمال کنه. این ابهامات برای برنامه نویس C++/C که پیش نمیاد چون چیزی رو مجدد تعریف نمی کنه و از همون تعاریف استفاده می کنه. برای همین چیزی در توضیحاتشون نوشته نمیشه. می توانید تعاریف هر کدوم رو در هدر های ویندوز ببینید ولی کلا اگه دیدید جایی مقداری با FLOAT یا WORD یا DWORD یا BYTE و ... تعریف شده، طول مشخص و ثابتی دارند که ربطی به مدل حافظه نداره، اما مواردی مثل HANDLE و معمولا سایر تعاریفی که اولشون H داره، مثل HDC و HWND بنا به مدل حافظه بین 32 و 64 بیت تغییر می کنه و براشون IntPtr مناسبه. و هر نوع داده ای که با * شروع بشه و معمولا تعاریفی که با P یا LP شروع بشه مثل LPSECURITY_ATTRIBUTES و PSID و PLONG نشانگر اشاره گر بودنشونه که اونها هم باید حتما با IntPtr تعریف بشن.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
نه، SECURITY_DESCRIPTOR_MIN_LENGTH یک مقدار ثابته، طول حداقلی یک SECURITY_DESCRIPTOR ئه که دیگه از اون کمتر حافظه نمیشه برایش در نظر گرفت. مثل همون مقادیر ثابتی است که در هدر های API ویندوز تعریف شده، 20 بایت. ولی GetSecurityDescriptorLength تابعی است که طول یک SECURITY_DESCRIPTOR مشخص رو براتون اعلام می کنه که ممکنه بیشتر از این مقدار حداقلی باشه. وقتی هنوز SECURITY_DESCRIPTOR ای نساختید که موردی نیست که بخواهید به عنوان پارامتر به GetSecurityDescriptorLength بدهید.


define SECURITY_DESCRIPTOR_MIN_LENGTH رو تو گوگل جستجو کنید. همیشه سایت هایی هستند که هدر های ویندوز رو نشون میدن. البته قبلا هم بهتون نرم افزار ApiViewer رو معرفی کرده بودم.

سلامی مجدد
ممنون استاد علی
آها .
پس لازمه که استراکچر SECURITY_DESCRIPTOR و فیلدهاش را با سایزش را در سی شارپ تعریف کنیم دیگه چون با متد InitializeSecurityDescriptor گفتید مقداردهی کنیم که در ورودی اش شی ای از این استراکچر را میخواد که خودتون هم در پست 995 اشاره کردید ولی با اون حال منظورتون را در همون پست که گفتید :


"تکرار می کنم، شما قرار نیست ساختار SECURITY_DESCRIPTOR رو در #C تعریف کنید"

متوجه نشدم . منظورتون این نبود که prototype اش را در سی شارپ تعریف نکنم که . درسته؟ چون باید پروتوتایپ اش تعریف بشه تا داخل اون متد و متدهای دیگه و کلا هر جای دیگه که لازمه از شی این استراکچر استفاده بشه .


نیازی نیست در توضیحاتشون چیزی بگه، اگه به نوع داده ای که در API مشخص شده دقت کنید میبینید که عموما نوع داده اصلی زبان C++/C نیستند، یک نوع تعریف شده در هدر های ویندوز هستند که خود مایکروسافت تعریفشون کرده. فرضا HWND و HDC و HANDLE و LPDWORD و ...
خود هدر طوری نوشته شده که موقع کامپایل بر اساس تنظیمات مثلا 32 بیتی بودن یا 64 بیتی بودن حافظه تعریف متفاوتی اعمال کنه. این ابهامات برای برنامه نویس C++/C که پیش نمیاد چون چیزی رو مجدد تعریف نمی کنه و از همون تعاریف استفاده می کنه. برای همین چیزی در توضیحاتشون نوشته نمیشه. می توانید تعاریف هر کدوم رو در هدر های ویندوز ببینید ولی کلا اگه دیدید جایی مقداری با FLOAT یا WORD یا DWORD یا BYTE و ... تعریف شده، طول مشخص و ثابتی دارند که ربطی به مدل حافظه نداره، اما مواردی مثل HANDLE و معمولا سایر تعاریفی که اولشون H داره، مثل HDC و HWND بنا به مدل حافظه بین 32 و 64 بیت تغییر می کنه و براشون IntPtr مناسبه. و هر نوع داده ای که با * شروع بشه و معمولا تعاریفی که با P یا LP شروع بشه مثل LPSECURITY_ATTRIBUTES و PSID و PLONG نشانگر اشاره گر بودنشونه که اونها هم باید حتما با IntPtr تعریف بشن.

خیلی ممنونم
 

the_king

مدیرکل انجمن
سلامی مجدد
ممنون استاد علی
آها .
پس لازمه که استراکچر SECURITY_DESCRIPTOR و فیلدهاش را با سایزش را در سی شارپ تعریف کنیم دیگه چون با متد InitializeSecurityDescriptor گفتید مقداردهی کنیم که در ورودی اش شی ای از این استراکچر را میخواد که خودتون هم در پست 995 اشاره کردید ولی با اون حال منظورتون را در همون پست که گفتید :


"تکرار می کنم، شما قرار نیست ساختار SECURITY_DESCRIPTOR رو در #C تعریف کنید"

متوجه نشدم . منظورتون این نبود که prototype اش را در سی شارپ تعریف نکنم که . درسته؟ چون باید پروتوتایپ اش تعریف بشه تا داخل اون متد و متدهای دیگه و کلا هر جای دیگه که لازمه از شی این استراکچر استفاده بشه .
نه، شما پروتوتایپ SECURITY_DESCRIPTOR رو تعریف نمی کنید. فیلدهاشو تعریف نمی کنید، struct برایش نمی سازید. اسمی از فیلدهای داخلش نمی برید. عرض کردم یک حافظه میسازید.
روی جزئیات کد نویسی تمرکز کنید. مثلا همین پست آخرم رو میخونید و میگید ممنون، ولی در همون پست نوشتم تعاریفی که با P شروع میشه معمولا اشاره گر هستند و در توضیحات InitializeSecurityDescriptor هم نوشته که پارامتر ورودی اش از نوع PSECURITY_DESCRIPTOR ئه.
InitializeSecurityDescriptor function
خودتون قبلا سوال کردید و میدونید هر جور struct یا شیء ای هم که به فرض میساختید، موقع ارسال به تابع InitializeSecurityDescriptor بصورت آدرس اشاره گر درمیومد.
فقط یک اشاره گر رو بجای اون SECURITY_DESCRIPTOR بکار می برید، اصلا کاری با فیلد هایش ندارید. همانطور که گفتم و بعدا ایشالا برای مثال جستجو می کنید و میبینید، یک حافظه میسازید که آدرسش بصورت IntPtr ئه و همونم به InitializeSecurityDescriptor تحویل میدید.InitializeSecurityDescriptor که اصلا به زبان C ئه و با شیء سرو کار نداره، ورودی اش هم چیزی جز یک آدرس حافظه نیست، چون تازه خودش میخواد در اون حافظه یک ساختار SECURITY_DESCRIPTOR رو پر کنه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
نه، شما پروتوتایپ SECURITY_DESCRIPTOR رو تعریف نمی کنید. فیلدهاشو تعریف نمی کنید، struct برایش نمی سازید. اسمی از فیلدهای داخلش نمی برید. عرض کردم یک حافظه میسازید.
روی جزئیات کد نویسی تمرکز کنید. مثلا همین پست آخرم رو میخونید و میگید ممنون، ولی در همون پست نوشتم تعاریفی که با P شروع میشه معمولا اشاره گر هستند و در توضیحات InitializeSecurityDescriptor هم نوشته که پارامتر ورودی اش از نوع PSECURITY_DESCRIPTOR ئه.
InitializeSecurityDescriptor function
خودتون قبلا سوال کردید و میدونید هر جور struct یا شیء ای هم که به فرض میساختید، موقع ارسال به تابع InitializeSecurityDescriptor بصورت آدرس اشاره گر درمیومد.
فقط یک اشاره گر رو بجای اون SECURITY_DESCRIPTOR بکار می برید، اصلا کاری با فیلد هایش ندارید. همانطور که گفتم و بعدا ایشالا برای مثال جستجو می کنید و میبینید، یک حافظه میسازید که آدرسش بصورت IntPtr ئه و همونم به InitializeSecurityDescriptor تحویل میدید.InitializeSecurityDescriptor که اصلا به زبان C ئه و با شیء سرو کار نداره، ورودی اش هم چیزی جز یک آدرس حافظه نیست، چون تازه خودش میخواد در اون حافظه یک ساختار SECURITY_DESCRIPTOR رو پر کنه.

آها ممنون
پس فقط با توابع Marshal باید کار کنم . چون فکر کردم مثل مثالی که در دو صفحه ی قبل زدید ، اونجوری باید عمل کنم و پروتایپ اش هم لازمه .
یه سئوال اینکه در توابعی که در See Also در راهنمای استراکچر SECURITY_DESCRIPTOR اومد :

_SECURITY_DESCRIPTOR

(بعد از مقداردهی اولیه و استفاده از تابع InitializeSecurityDescriptor) ، برای مقداردهی فیلدهای استراکچر ، باید فقط از توابعی که با Set شروع میشن استفاده کنم دیگه؟ یعنی لازم نیست با توابعی که با Get شروع میشن کار کنم دیگه؟ چون خروجی توابع Get شون همه bool هستن .

بعد اگه پارامترهای این توابعی که با Set شروع میشن ، اشاره گر به یه استراکچر دیگه خواستن (مثل تابع SetSecurityDescriptorDacl که پارامترسومش اشاره گر به استراکچر ACL میخواد) ، اون استراکچر را هم توی See Also اش ببینم اگه توابعی داشت که این استراکچر را مقداردهی اولیه کنه و اطلاعات فیلدهاش را پر کنه (مثل متد InitializeAcl و متد SetAclInformation برای استراکچر ACL) ، از توابع Marshal استفاده کنم و با AllocHGlobal براش حافظه بگیرم و بقیه ی کارهایی که گفتین را انجام بدم وگرنه اگه این توابع نبود ، خودم مثل نمونه های قبلی (که در دو صفحه ی پیش یا در مثال اتوپلی که اون موقع گفته بودین) ، پروتوتایپ اش را تعریف کنم و مقداردهی اش کنم؟ درست میگم؟
 

جدیدترین ارسال ها

بالا