Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.145.40.139] |
|
Сообщ.
#1
,
|
|
|
Привет всем!
Есть известная опенсурсная софтина CrystalDiskMark, исходник можно скачать с оф. сайта https://crystalmark.info/redirect.php?produ...stalDiskMarkSrc Написан в Microsoft Visual Studio без единого комментария. Пока добился того, что исходник у меня на машине компилируется и затем работает. https://cloud.mail.ru/public/KG1n/6DVkZHDoB Мне нужно забрать результаты теста и передать бекэнду сайта. Неожиданно для себя не могу найти место, где переменная из переменной превращается в циферку... После всех вычислений должно же быть место где некая переменная с результатом уходит в отображение. Опыт в с++ околонулевой, в универе пробовал с++ builder и там через форму можно было найти объект гуя и отследить связанные с ним переменные. Тут какого-то конструктора гуя не видно вообще, где переменные уходят в printf или что-то подобное тоже не понятно... Помогите плз их найти. |
Сообщ.
#2
,
|
|
|
Цитата Berbraer @ Неожиданно для себя не могу найти место, где переменная из переменной превращается в циферку... После всех вычислений должно же быть место где некая переменная с результатом уходит в отображение. Попробуй произвести поиск по всем исходникам строки "sprintf". |
Сообщ.
#3
,
|
|
|
Код напичкан CString::Format()-ами. Походу именно так переменные и "превращаются в циферки".
|
Сообщ.
#4
,
|
|
|
Цитата ЫукпШ @ Попробуй произвести поиск по всем исходникам строки "sprintf". sprintf и т.п. в исходнике отсутствует (кроме пары мест записи в лог), его я первым делом искал, а других способов вывода данных на экран в си я не знаю. В коде где-то есть переменные, в которые в бинарной форме попадают результаты расчётов скорости диска и потом они уже как-то выводятся в гуй. Вот мне нужно эти переменные с готовыми результатами найти и данные забрать. Самое логичное, это найти место вывода в гуй и там найти эти переменные со значениями, чтобы перехватить для своих нужд. Вот эти самые места вывода данных на экран я и не смог найти. Qraizer, за подсказку CString::Format() спасибо, попробую разобраться что это. |
Сообщ.
#5
,
|
|
|
Цитата Qraizer @ Вернулся к задаче после небольшого перерыва, нашёл, что вывод происходит через DDX_Control, нашёл ID индикаторов и сам диалог: void CDiskMarkDlg::DoDataExchange(CDataExchange* pDX) { CMainDialogFx::DoDataExchange(pDX); DDX_Control(pDX, IDC_BUTTON_ALL, m_ButtonAll); DDX_Control(pDX, IDC_BUTTON_TEST_0, m_ButtonTest0); DDX_Control(pDX, IDC_BUTTON_TEST_1, m_ButtonTest1); DDX_Control(pDX, IDC_BUTTON_TEST_2, m_ButtonTest2); DDX_Control(pDX, IDC_BUTTON_TEST_3, m_ButtonTest3); //вот тут DDX_Control(pDX, IDC_TEST_READ_0, m_TestRead0); DDX_Control(pDX, IDC_TEST_READ_1, m_TestRead1); DDX_Control(pDX, IDC_TEST_READ_2, m_TestRead2); DDX_Control(pDX, IDC_TEST_READ_3, m_TestRead3); DDX_Control(pDX, IDC_TEST_WRITE_0, m_TestWrite0); DDX_Control(pDX, IDC_TEST_WRITE_1, m_TestWrite1); DDX_Control(pDX, IDC_TEST_WRITE_2, m_TestWrite2); DDX_Control(pDX, IDC_TEST_WRITE_3, m_TestWrite3); #ifdef MIX_MODE DDX_Control(pDX, IDC_TEST_MIX_0, m_TestMix0); DDX_Control(pDX, IDC_TEST_MIX_1, m_TestMix1); DDX_Control(pDX, IDC_TEST_MIX_2, m_TestMix2); DDX_Control(pDX, IDC_TEST_MIX_3, m_TestMix3); DDX_Control(pDX, IDC_COMBO_MIX, m_ComboMix); #endif DDX_Control(pDX, IDC_COMMENT, m_Comment); DDX_Control(pDX, IDC_COMBO_COUNT, m_ComboCount); DDX_Control(pDX, IDC_COMBO_SIZE, m_ComboSize); DDX_Control(pDX, IDC_COMBO_DRIVE, m_ComboDrive); DDX_Control(pDX, IDC_COMBO_UNIT, m_ComboUnit); DDX_Control(pDX, IDC_DEMO_SETTING, m_DemoSetting); DDX_Control(pDX, IDC_READ_UNIT, m_ReadUnit); DDX_Control(pDX, IDC_WRITE_UNIT, m_WriteUnit); #ifdef MIX_MODE DDX_Control(pDX, IDC_MIX_UNIT, m_MixUnit); #endif DDX_Text(pDX, IDC_COMBO_COUNT, m_ValueTestCount); DDX_Text(pDX, IDC_COMBO_SIZE, m_ValueTestSize); DDX_Text(pDX, IDC_COMBO_DRIVE, m_ValueTestDrive); DDX_Text(pDX, IDC_COMBO_UNIT, m_ValueTestUnit); DDX_CBIndex(pDX, IDC_COMBO_COUNT, m_IndexTestCount); DDX_CBIndex(pDX, IDC_COMBO_SIZE, m_IndexTestSize); DDX_CBIndex(pDX, IDC_COMBO_DRIVE, m_IndexTestDrive); DDX_CBIndex(pDX, IDC_COMBO_UNIT, m_IndexTestUnit); #ifdef MIX_MODE DDX_CBIndex(pDX, IDC_COMBO_MIX, m_IndexTestMix); #endif } С утра пытаюсь достать значение m_TestRead. Тестирую на флешке, параметры которой известны. Пытаюсь просто умножить m_TestRead на 2-100, чтобы увидеть изменение цифры на экране ну и понять, что я добрался до непосредственно значения, а не указателя и т.п. И нифига. Либо заворачивает компилятор, либо компилятор пропускает, но на экране вообще ничего не изменяется... Обычно вижу это: DDX_Control(pDX, IDC_TEST_READ_0, (m_TestRead0*100)); 1>F:\!!CrystalDiskMark8_0_2Src\CrystalDiskMark\DiskMarkDlg.cpp(193,50): error C2678: бинарный "*": не найден оператор, принимающий левый операнд типа "CStaticFx" (или приемлемое преобразование отсутствует) 1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um\d2d1helper.h(1003,1): message : может быть "D2D1_MATRIX_3X2_F operator *(const D2D1_MATRIX_3X2_F &,const D2D1_MATRIX_3X2_F &)" (компилируется исходный файл DiskMarkDlg.cpp) 1>F:\!!CrystalDiskMark8_0_2Src\CrystalDiskMark\DiskMarkDlg.cpp(193,50): message : при попытке сопоставить список аргументов "(CStaticFx, int)" 1>F:\!!CrystalDiskMark8_0_2Src\CrystalDiskMark\DiskMarkDlg.cpp(193,51): error C2660: DDX_Control: функция не принимает 2 аргументов 1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\atlmfc\include\afxdd_.h(71,13): message : см. объявление "DDX_Control" (компилируется исходный файл DiskMarkDlg.cpp) 1>Сборка проекта "DiskMark.vcxproj" завершена с ошибкой. ------------------- m_TestRead0 *= 10; 1>F:\!!CrystalDiskMark8_0_2Src\CrystalDiskMark\DiskMarkDlg.cpp(192,14): error C2676: бинарный "*=": "CStaticFx" не определяет этот оператор или преобразование к типу приемлемо к встроенному оператору 1>Сборка проекта "DiskMark.vcxproj" завершена с ошибкой. Раскурил код, насколько позволяют мои два с половиной познания Си. m_TestRead определена классом CStaticFx, этот класс написан автором кода. Но в DDX_Control она передаётся в стандартный класс CWnd, причём, через указатель, насколько понимаю значение символа &. В итоге, совершенно не понятно, появляется ли тут непосредственно результат вычисления скорости диска, или это некая смычка между классами и всё?... Я в глубокой растерянности. Как записать значение в лог представляю, собственно, у автора лог ведётся стандартным спринтф емнип. Но как достать переменные, содержащие значения выводимые на экран, не могу разобраться, памагити! Вот основыные части кода: CStaticFx m_TestRead0; CStaticFx m_TestRead1; CStaticFx m_TestRead2; CStaticFx m_TestRead3; CStaticFx m_TestWrite0; CStaticFx m_TestWrite1; CStaticFx m_TestWrite2; CStaticFx m_TestWrite3; //----------------------------------------------------------------------------- void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl); //----------------------------------------------------------------------------- void CDiskMarkDlg::DoDataExchange(CDataExchange* pDX) { CMainDialogFx::DoDataExchange(pDX); DDX_Control(pDX, IDC_BUTTON_ALL, m_ButtonAll); DDX_Control(pDX, IDC_BUTTON_TEST_0, m_ButtonTest0); DDX_Control(pDX, IDC_BUTTON_TEST_1, m_ButtonTest1); DDX_Control(pDX, IDC_BUTTON_TEST_2, m_ButtonTest2); DDX_Control(pDX, IDC_BUTTON_TEST_3, m_ButtonTest3); //m_TestRead0 *= 2; DDX_Control(pDX, IDC_TEST_READ_0, (m_TestRead0)); DDX_Control(pDX, IDC_TEST_READ_1, m_TestRead1); DDX_Control(pDX, IDC_TEST_READ_2, m_TestRead2); DDX_Control(pDX, IDC_TEST_READ_3, m_TestRead3); DDX_Control(pDX, IDC_TEST_WRITE_0, m_TestWrite0); DDX_Control(pDX, IDC_TEST_WRITE_1, m_TestWrite1); DDX_Control(pDX, IDC_TEST_WRITE_2, m_TestWrite2); DDX_Control(pDX, IDC_TEST_WRITE_3, m_TestWrite3); #ifdef MIX_MODE DDX_Control(pDX, IDC_TEST_MIX_0, m_TestMix0); DDX_Control(pDX, IDC_TEST_MIX_1, m_TestMix1); DDX_Control(pDX, IDC_TEST_MIX_2, m_TestMix2); DDX_Control(pDX, IDC_TEST_MIX_3, m_TestMix3); DDX_Control(pDX, IDC_COMBO_MIX, m_ComboMix); #endif DDX_Control(pDX, IDC_COMMENT, m_Comment); DDX_Control(pDX, IDC_COMBO_COUNT, m_ComboCount); DDX_Control(pDX, IDC_COMBO_SIZE, m_ComboSize); DDX_Control(pDX, IDC_COMBO_DRIVE, m_ComboDrive); DDX_Control(pDX, IDC_COMBO_UNIT, m_ComboUnit); DDX_Control(pDX, IDC_DEMO_SETTING, m_DemoSetting); DDX_Control(pDX, IDC_READ_UNIT, m_ReadUnit); DDX_Control(pDX, IDC_WRITE_UNIT, m_WriteUnit); #ifdef MIX_MODE DDX_Control(pDX, IDC_MIX_UNIT, m_MixUnit); #endif DDX_Text(pDX, IDC_COMBO_COUNT, m_ValueTestCount); DDX_Text(pDX, IDC_COMBO_SIZE, m_ValueTestSize); DDX_Text(pDX, IDC_COMBO_DRIVE, m_ValueTestDrive); DDX_Text(pDX, IDC_COMBO_UNIT, m_ValueTestUnit); DDX_CBIndex(pDX, IDC_COMBO_COUNT, m_IndexTestCount); DDX_CBIndex(pDX, IDC_COMBO_SIZE, m_IndexTestSize); DDX_CBIndex(pDX, IDC_COMBO_DRIVE, m_IndexTestDrive); DDX_CBIndex(pDX, IDC_COMBO_UNIT, m_IndexTestUnit); #ifdef MIX_MODE DDX_CBIndex(pDX, IDC_COMBO_MIX, m_IndexTestMix); #endif } //------------------------------------------------------------ class CStaticFx : public CStatic { DECLARE_DYNAMIC(CStaticFx); public: // Constructors CStaticFx(); virtual ~CStaticFx(); // Control BOOL InitControl(int x, int y, int width, int height, double zoomRatio, CDC* bkDC, LPCWSTR imagePath, int imageCount, DWORD textAlign, int renderMode, BOOL bHighContrast, BOOL bDarkMode); void SetMargin(int top, int left, int bottom, int right, double zoomRatio); CSize GetSize(void); void SetDrawFrame(BOOL bDrawFrame); void SetDrawFrameEx(BOOL bDrawFrame, COLORREF frameColor = RGB(128, 128, 128)); void SetGlassColor(COLORREF glassColor, BYTE glassAlpha); void SetMeter(BOOL bMeter, double meterRatio); void SetLabelUnit(CString label, CString unit); // Font void SetFontEx(CString face, int size, int sizeToolTip, double zoomRatio, double fontRatio = 1.0, COLORREF textColor = RGB(0, 0, 0), LONG fontWeight = FW_NORMAL, BYTE fontRender = CLEARTYPE_NATURAL_QUALITY); // ToolTip void SetToolTipText(LPCTSTR pText); void SetToolTipActivate(BOOL bActivate = TRUE); void SetToolTipWindowText(LPCTSTR pText); CString GetToolTipText(); // Mouse void SetHandCursor(BOOL bHandCuror = TRUE); protected: // Draw Control virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); virtual void DrawControl(CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct, CBitmap& ctrlBitmap, CBitmap& bkBitmap, int no); virtual void DrawString(CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct); // Image BOOL LoadBitmap(LPCTSTR fileName); BOOL LoadBitmap(HBITMAP hBitmap); void SetBkReload(void); BOOL SetBitmap(CBitmap& bitmap); void LoadCtrlBk(CDC* drawDC); // ToolTip void InitToolTip(); virtual BOOL PreTranslateMessage(MSG* pMsg); // Message Map DECLARE_MESSAGE_MAP() afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnMouseHover(UINT nFlags, CPoint point); afx_msg void OnMouseLeave(); afx_msg void OnKillfocus(); afx_msg void OnSetfocus(); afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); protected: // Control int m_X; int m_Y; CSize m_CtrlSize; CRect m_Margin; int m_RenderMode; BOOL m_bHighContrast; BOOL m_bDarkMode; BOOL m_bDrawFrame; COLORREF m_FrameColor; CString m_Label; CString m_Unit; // Glass COLORREF m_GlassColor; BYTE m_GlassAlpha; // Meter BOOL m_bMeter; double m_MeterRatio; // Image CString m_ImagePath; int m_ImageCount; CDC* m_BkDC; CBitmap m_BkBitmap; BOOL m_bBkBitmapInit; BOOL m_bBkLoad; CBitmap m_CtrlBitmap; CImage m_CtrlImage; // Font DWORD m_TextAlign; CFont m_Font; CFont m_FontToolTip; COLORREF m_TextColor; // ToolTip CToolTipCtrl m_ToolTip; CString m_ToolTipText; // Mouse BOOL m_bHover; BOOL m_bFocas; BOOL m_bTrackingNow; BOOL m_bHandCursor; }; |
Сообщ.
#6
,
|
|
|
Цитата Berbraer @ Но как достать переменные, содержащие значения выводимые на экран, не могу разобраться, памагити! Надо исследовать подсудимую программу. я делаю так: 1. Скачаем программу DebugView с сайта Микрософт: DebugView 2. Запустим прогу, увидим окошко. 3. Добавим модуль с таким текстом в твою программу (или спрячем модуль в библиотеку): void Type_Debug_String(const TCHAR* pFmt,...) { if(!pFmt) return; va_list ap; //Указатель на список параметров va_start(ap,pFmt); //Настроились на список параметров TCHAR sss[32768]; _vsntprintf_s(sss,ARRAYSIZE(sss),_TRUNCATE,pFmt,ap); ::OutputDebugString(sss); va_end(ap); //Завершаем работу с макрокомандами } 4. Если в исходниках исследуемой программы захочется подсмотреть, как менются некие переменные (в разных точках программы в процессе работы) просто пишем вывод в стиле С: // если i - это int i, d - это double d Type_Debug_String(_T("i=%d i=0x%X d=%e"),i,i,d); В окошке DebugView увидим выводимые строчки. итп итд ----- Что касается всего исследования - у тебя есть подсказка. Объекты-строки содержат операцию "Format". Именно посредством этой операции, возможно, численные значения преобразуются в строку для последующего вывода в контрол. Значит, надо искать среди этих объектов-строк - какой из них содержит интересующую переменную. Добравшись до этого объекта можно искать дальше всю логику и историю вычислений/изменений/преобразований конкретной переменной. |
Сообщ.
#7
,
|
|
|
Ок, поищу форматы. Но m_TestWrite и иже там не встречается точно. Придётся идти шагами...
Но в строке DDX_Control(pDX, IDC_TEST_READ_0, m_TestRead0); переменная m_TestRead0 - строковая? А можно её из строки прям тут взад в бинарную преобразовать? Ну, кроме ручного метода вычитания 0x30 из символов, домножения на степень 10 и сложения |
Сообщ.
#8
,
|
|
|
Цитата Berbraer @ Ок, поищу форматы. Но m_TestWrite и иже там не встречается точно. Берем TotalCommander. Начинаем поиск в директории с zip-ом исходников. Указываем "все файлы", "ищем в архивах", строка "m_TestWrite". Обнаруживаем её тут: Смотрим файлы, и видим, что m_TestWrite - это объекты-статики: CStaticFx m_TestWrite0; CStaticFx m_TestWrite1; CStaticFx m_TestWrite2; CStaticFx m_TestWrite3; T.е., по всей вероятности, это "станция конечная" для всех переменных. Значение как-то добывается, считается. Далее преобразуется в строку, а потом для отображения выводится в статик. Переменную надо нежно брать за хобот в момент перед преобразованием в строку. Именно в этой точке имеется готовое к выводу число. |
Сообщ.
#9
,
|
|
|
Berbraer, почему бы тебе просто не сказать, какого результата ото всех своих усилий тебе хочется достичь?
|
Сообщ.
#10
,
|
|
|
ЫукпШ, слухай, ну я не настолько тупенький чтобы не разобраться как искать по проекту в студии Просто сишные передачи указателей немного ломают мозг с непривычки + непонимание, какая функция стандартная и известно что делает, какая - самописная автором.
Но не суть, нашёл. Окончательное вычисление/форматирование результата происходит в функции void CDiskMarkDlg::SetMeter(CStaticFx* control, double score, double latency, int blockSize, int unit) И выводятся в m_TestRead через void CDiskMarkDlg::UpdateScore() Соответственно, в SetMeter можно перехватывать doble результаты. Вдруг кому пригодится. Qraizer, я же написал - достать бинарную переменную, а далее передать ея в интернет. Сделал через запись результатов в файл. Из своего клиента я отслеживаю изменение файла, и новую запись странслирую на сайт. Т.к. тест даже самого быстрого диска занимает минуту минимум, такой способ обмена вполне приемлем. И универсален. |