Как сделать оконное приложение с параметром /ENTRY:WinMain ?

Тема в разделе "WASM.WIN32", создана пользователем Arisu, 2 дек 2007.

  1. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    (не придумал куда лучше постить: сюда или в раздел по Ц. не серчайте, если что)

    делаю очень маленькое приложение на Ц с WINAPI и обязательно с окном (кнопки там всякие то-сё).

    Как делать маленькие приложения в 2кб я знаю ) но я их всю жизнь делал без окон. драйверы, сервисы всякие.
    А сейчас хочу сделать такое же маленькое, но с окном.

    Необходимое условие для создание минимального экзешника это параметр /ENTRY:WinMain . А всё остальное я как бы делаю руками что бы минимизировать размер.

    Но обнаружил досадный баг (или это не баг): с этим ключём прога, в которой окно создаётся по всем API правилам компилируется без проблем и даже запускается и работает, НО функции ShowWindow() и UpdateWindow() не дают никакого эффекта. Т.е. класс окна я настроил, зарегестрировал его, окно создал с помощью CreateWindowEx (и крейт виндоу и регистркласс отрабатывают нормально) а дальше пытаюсь его нарисовать, однако ничего у меня не выходит. Функции как "в холостую" отрабатывают. Окно так и не появляется. Хотя и обработчик сообщений окна и всё остальное - работает, но самого окна невидно.

    Стоит ключь /ENTRY:WinMain из батника убрать, как окно магическим образом начинает рисоваться, но за это я плачу аж 16 килобаетами.

    Может есть какой-то тайный способ?
     
  2. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    а в ShowWindow что передаешь, SW_SHOW или последний параметр WinMain?
     
  3. Arisu

    Arisu Алиса Селезнёва

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    89
    rmn
    да прибудет с тобой сила! я передавал параметр с винмэйн, при этом был уверен что там то, что нужно. всё заработало
     
  4. Mental_Mirror

    Mental_Mirror New Member

    Публикаций:
    0
    Регистрация:
    7 май 2007
    Сообщения:
    431
    Arisu
    Явно тут не изза ENTRY баг, т.к. я писал и baseindependent-shellcodes с изображением окна. Работало. В вашем случае если рассуждать технологически могут возникать лишь проблемы с инициализацией стандартной библиотеки с, других потенциальных проблем трудно придумать изза использования ключа ENTRY. Если хотите сделать мааленький EXE, то лучше конечно использовать не С, а ASM. Для решения проблемы в вашем случае лишь могу посоветовать покопать в отладчике значение GetLastError()/@err,hr (если использовать VC) после вызова каждой из функции, холостых вызовов быть не доллжно, если вы все делаете правильно. Правильное использование инструментов может освободить ваш моск от сложных технических размышлений о классах окон. И конечно выкладывайте код, мы очень любим читать код, если он хорошо и красиво написан.
     
  5. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    Mental_Mirror
    Да нет, все проще :) Функция в точке входа получает только один параметр - адрес PEB. Именно он будет в hInstance WinMain, в остальных параметрах будет какой-нибудь мусор со стека.
     
  6. roman_pro

    roman_pro New Member

    Публикаций:
    0
    Регистрация:
    9 фев 2007
    Сообщения:
    291
    Ага, наступал на такие же грабли, только проблема была с командной строкой. Решил вызовом GetCommandLine().

    http://ru.wikipedia.org/wiki/WinMain
     
  7. Mental_Mirror

    Mental_Mirror New Member

    Публикаций:
    0
    Регистрация:
    7 май 2007
    Сообщения:
    431
    rmn
    Зачем мне объяснять очевидные вещи?
     
  8. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    Mental_Mirror
     
  9. Mental_Mirror

    Mental_Mirror New Member

    Публикаций:
    0
    Регистрация:
    7 май 2007
    Сообщения:
    431
    Тут просто была проблема в коде, а не в использовании ключа ENTRY.
     
  10. CoolCmd

    CoolCmd New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2007
    Сообщения:
    21
    Адрес:
    Moscow
    Интересно. Ты уверен что у функции один параметр? Я погуглил немножко, peb берут из fs:xxxx, а у функции нет никаких параметров.
     
  11. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    CoolCmd
    Угу: typedef DWORD (WINAPI *PPROCESS_START_ROUTINE)(VOID);
     
  12. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    crt0.c:

    Код (Text):
    1. /***
    2. *BaseProcessStartup(PVOID Peb)
    3. *
    4. *Purpose:
    5. *       This routine does the C runtime initialization, calls main(), and
    6. *       then exits.  It never returns.
    7. *
    8. *Entry:
    9. *       PVOID Peb - pointer to Win32 Process Environment Block (not used)
    10. *
    11. *Exit:
    12. *       This function never returns.
    13. *
    14. *******************************************************************************/
    это комментарий к функциям mainCRTStartup и WinMainCRTStartup, которые, собственно, и являются точкой входа.
     
  13. CoolCmd

    CoolCmd New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2007
    Сообщения:
    21
    Адрес:
    Moscow
    rmn
    Вот виндовая функция в winxp, которая запускает xxxCRTStartup():
    Код (Text):
    1. 7C816FB4 6A 0C            push        0Ch  
    2. 7C816FB6 68 E0 6F 81 7C   push        7C816FE0h
    3. 7C816FBB E8 06 B5 FE FF   call        7C8024C6
    4. 7C816FC0 83 65 FC 00      and         dword ptr [ebp-4],0
    5. 7C816FC4 6A 04            push        4    
    6. 7C816FC6 8D 45 08         lea         eax,[ebp+8]
    7. 7C816FC9 50               push        eax  
    8. 7C816FCA 6A 09            push        9    
    9. 7C816FCC 6A FE            push        0FFFFFFFEh
    10. 7C816FCE FF 15 A0 13 80 7C call        dword ptr ds:[7C8013A0h]
    11. 7C816FD4 FF 55 08         call        dword ptr [ebp+8]
    12. 7C816FD7 50               push        eax  
    13. 7C816FD8 E8 7B 50 FF FF   call        7C80C058
    14. 7C816FDD 90               nop              
    15. 7C816FDE 90               nop              
    16. 7C816FDF 90               nop              
    17. 7C816FE0 ??               db          ffh  
    18. 7C816FE1 ??               db          ffh  
    19. 7C816FE2 ??               db          ffh
    call 7C8024C6 - это вроде как настройка SEH
    call dword ptr ds:[7C8013A0h] - не знаю что, но она свои 4 параметра из стека достает
    call dword ptr [ebp+8] - собсно вызов xxxCRTStartup()

    Как видишь, никакими peb и не пахнет. Из какого компилятора ты привел комментарий? В VC++ нет такого, по крайней мере начиная с шестой версии.

    И здесь у тебя ошибочка. Это call 7C80C058 никогда не возвращается. :)
     
  14. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    Как раз из VC++ и именно 6-й версии.

    Возможно, комментарий устарел.
     
  15. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Именно. Ты не заметил, что xxxCRTStartup имеет параметр void? То есть, не имеет аргументов.
     
  16. Mental_Mirror

    Mental_Mirror New Member

    Публикаций:
    0
    Регистрация:
    7 май 2007
    Сообщения:
    431
    Вобщем листинг почти в яблочко, только точка входа начинается еще чуть раньше.
    Вот точная точка входа на XP SP2:
    Код (Text):
    1. .text:7C810665                 xor     ebp, ebp
    2. .text:7C810667                 push    eax
    3. .text:7C810668                 push    0
    4. .text:7C81066A                 jmp     loc_7C816FB4
    После этого кода выполняется как раз то, о чем говорил CoolCmd. Ну видите сами смещения совпадают.
    Что такое точка входа? Есть параметр EntryPoint в опциональном заголовке PE-модуля. При создании процесса процесс родитель создает первичный поток. Вот именно адрес 0x7C810665 и есть стартовый адрес для нового потока. Этот адрес тоже можно считать точкой входа. Далее, это так-сказать первичная точка входа вызывает точку входа, которая указана в опциональном заголовке PE-модуля. Вызывает и действительно не передает никаких параметров. Есть тонкость, она может пронзить ваш спинной мозг холодом на несколько секунд. Итак, пойду убью сибя ап стену.
     
  17. CoolCmd

    CoolCmd New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2007
    Сообщения:
    21
    Адрес:
    Moscow
    rmn
    Упс ошибся, дано шестерку забросил.

    IceStudent
    Там формат вызова __cdecl, могут все что угодно в параметрах написать и прога будет работать... если эти параметры не использовать. :)

    Mental_Mirror
    У тебя IDA? Может этот код вызывается для запуска всех новых потоков? Тогда call 7C80C058 скорее всего ExitThread().

    Давай выкладывай тонкость, я хочу умереть. :)
     
  18. Mental_Mirror

    Mental_Mirror New Member

    Публикаций:
    0
    Регистрация:
    7 май 2007
    Сообщения:
    431
    CoolCmd
    Тонкость в том, что есть точка входа еще до той которая указана в контексте нового создаваемого потока. Что она активизировалась, надо поставить в PEB флаг BeingDebugged и обработать int3, тогда мы попадаем на на начальный этап загрузки процесса, когда еще TLS Callbacks не вызваны.

    IDA. Не, только для стартового. В Context.EAX записывается EntryPoint из опционального заголовка. Потом он кладется в стек. И вызов идет call dword ptr [ebp+8]. Про ExitThread верно. Ну в общем возьми IDA и посмотри, там все видно и без моих коментариев. :) Полезно.