Объединение выделенной памяти

Тема в разделе "WASM.BEGINNERS", создана пользователем Painter, 7 окт 2011.

  1. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    У меня возник другой вопрос... Мне надо чтобы моя прога выдовала мне текст последней ошибки. Сначала я получаю ее код при помощи GetLastError, а вот потом как этот код обработать так чтобы текстовая информация была не знаю... Ну а потом думаю при помощи MessageBox вывести на экран. Подскажите пожалуйста! Заранее спасибо.
     
  2. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    Спасибо огромное всем кто откликнулся на мой вопрос про реализацию буфера под текст. Прочитал много интересных решений!
     
  3. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Painter
    Как-то вот так вот:
    Код (Text):
    1. LPTSTR lpBuffer;
    2. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, GetLastError(), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),(LPTSTR)&lpBuffer, 0, NULL);
    3. //Выводим lpBuffer
    4. LocalFree(lpBuffer);
    Dmitry_Milk
    Ну HeapReAlloc так вряд ли работает. Для небольших блоков это в любом случае не прокатило бы, т.к. они разделяют страницы с другими блоками памяти, управляемыми менеджером кучи. А вот для больших блоков, требующих собственные страницы, можно было бы и сделать так, что, правда, потребовало бы несуществующий системный сервис вроде ZwReallocateVirtualMemory. Сам-то юзермодный менеджер кучи целиком реализован в ntdll, поэтому не имеет прямого доступа к таблицам страниц.
    Я знаю, что такая техника ремаппинга страниц без копирования используется в некоторых ОС для реализации пакетного IPC при передаче больших блоков памяти (типа в этом процессе странички размапили, в том примапили и можно не копировать 100MB), но Windows вроде так не делает... ну не считая возможности собственноручно реализовать такое с помощью разделяемых секций.
     
  4. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    l_inc
    дело в том что я уже пробывал так набирать и вот незадача ни фасм ни я не знаем что за функция такая MAKELANGID... Поэтому тут и загвоздка. Вообще если я не ошибаюсь это не функция WinAPI. Так что если можно как то без нее, то подскажите.
     
  5. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Dmitry_Milk
    Нет, т.к. менеджер кучи это просто юзермодная надстройка над системными VirtualAlloc\VirtualFree
    А подобие того, о чем ты говоришь можно реализовать через CreateFileMapping(INVALID_HANDLE_VALUE,...) + MapViewOfFile возрастающего размера. Подобие - потому, что по любому нужно задавать максимальный размер маппинга в CreateFileMapping, выше которого "не прыгнешь". Другое дело, что этот размер можно "смело" задавать значительно больше, чем при VirtualAlloc, т.к. реальное резервирование\выделение адресов происходит только при MapViewOfFile
     
  6. Euler

    Euler New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2009
    Сообщения:
    56
    Это макрос. Там внизу есть и описание:
    Код (Text):
    1. #define MAKELANGID(p, s) ((((WORD) (s)) << 10) | (WORD) (p))
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Painter
    Это не функция, а макрос. Можно заменить выражением Lang | (SubLang << 10) или просто подставить готовый идентификатор языка
     
  8. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    Ну я уже кое как нашел как оно формируется... А вот теперь вопрос... Это та часть кода при помощи которой должна выводиться ошибка...
    Код (Text):
    1.   invoke GetLastError
    2.   invoke FormatMessage,FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,\
    3.                        0,eax,LANG_NEUTRAL or SUBLANG_DEFAULT,ERROR_BUFER,0,0
    4.   invoke MessageBox,0,ERROR_BUFER,szErrorWin,MB_OK or MB_ICONERROR
    и мне MessageBox выдает какую то несуразицу! Код ошибки 2 (File not found). Когда в оли дебугил то FormatMessage возвращает eax 22h а там примерно следующее:
    CPU Dump
    Address Hex dump ASCII
    00401030 80 2A 08 00|00 00 00 00|00 00 00 00|00 00 00 00 | *.............
    00401040 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00 | ................
     
  9. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    Скажу сразу что SUBLANG_DEFAULT уже был смещен на 10! А адрес 00401030 это адрес буфера.
     
  10. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Мда, глянь в описание ф-ии - раз ты указываешь флаг FORMAT_MESSAGE_ALLOCATE_BUFFER, то ф-я тебе возвращает в ERROR_BUF не сам текст, а адрес блока памяти, который она выделила и куда записала этот текст. Тебе это нужно? Просто убери этот флаг и передай в предпоследним параметре nSize размер твоего буфера
     
  11. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    leo
    Спасибо. Помогло. А про описание еще раз отмечу что оно на английском. Ну а я как то слабоват в нем. То что пойму с помощью переводчика то и делаю!
     
  12. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    Не могу понять в чем дело... Запускаю код из под дебугера все ок, из под стандартного редактора фасма тоже прокатывает на ура, а вот из под тотала чего то ругается!
    Код (Text):
    1.                 invoke GetCommandLine                           ; получаем адрес командной строки
    2.                 mov esi,eax
    3.                 invoke MessageBox,0,eax,szInformation,MB_OK or MB_ICONINFORMATION
    4.  
    5.             find_file_name:                                     ; пытаемся найти имя файла для открытия
    6.                 lodsb
    7.                 cmp al,'"'                                      ; если встречается кавычка то пытаемся пропустить все что находится в кавычках
    8.                 je skip_quoted_text
    9.                 or al,al                                        ; если конец командной строки то выходим
    10.                 je exit_find_file
    11.                 cmp byte [esi+1],' '
    12.                 je find_file_name
    13.                 stdcall OpenF,esi,OPEN_EXISTING         ; открываем файл
    14.                 cmp eax,-1                                      ; если ошибка открытия
    15.                 je ERROR_OPEN                                 ; выводим ошибку на экран
    16.                 mov [hFile],eax                                 ; сохраняем дескриптор файла
    17.                 jmp exit_find_file
    18.  
    19.             ERROR_OPEN:
    20.                 stdcall ERROR_MESSAGE
    21.                 jmp exit_find_file
    22.  
    23.             skip_quoted_text:
    24.                 lodsb
    25.                 cmp al,'"'
    26.                 jne skip_quoted_text
    27.                 jmp find_file_name
    28.  
    29.             exit_find_file:
    Код (Text):
    1.   proc ERROR_MESSAGE
    2.   invoke GetLastError
    3.   invoke FormatMessage,FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,\
    4.                        0,eax,LANG_NEUTRAL or SUBLANG_DEFAULT,pERROR_BUFER,0,0
    5.   invoke MessageBox,0,[pERROR_BUFER],szErrorWin,MB_OK or MB_ICONERROR
    6.   ret
    7.   endp
    У меня при запуске такого кода под тоталом процедура ERROR_MESSAGE выдает мне (системе не удается найти указанный путь). Ну почему не удается это понятно, так как не указан файл а мой код почему то попытался открыть(функцией OpenF) файл... Какую ситуацию я не предусмотрел? Почему не опрокидывает часть кода там где открывается файл?
     
  13. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    Уточню что при запуске программы с каким либо параметром(который точно не является именем файла) выдает сообщение (не удается найти указанный файл). А под тоталом без параметров (не удается найти указаный путь).
     
  14. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Painter
    Ну вообще-то далеко не одну. Например, что будет, если командная строка содержит ровно одну двойную кавычку?
    А что, если первый параметр-путь сам в кавычках (что так и должно быть, если путь содержит пробелы)?
    А что, если нулевой параметр (обычно, но не обязательно, это путь к файлу или его имя) без кавычек?
    Ну и сам по себе очевидный баг: вместо cmp byte [esi+1],' ' должно быть cmp byte [esi],' ', т.к. на момент этой инструкции esi указывает на символ после последней чётной кавычки.
     
  15. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    l_inc
    Дело в том что командная строка выглядит примерно так: ("path\file.ext" param) где path - путь; file - запущенный файл; ext - расширение; param - параметры передающиеся нашей программе. Так вот я пропускаю все что находится в двойных кавычках, и после пробела, который обязательно присутствует, пытаюсь прочитать параметр. В данной ситуации это имя файла который надо открыть. Вот по поводу cmp byte [esi+1] я с вами соглашусь, дал маху. Хотя эта команда возникла для того чтобы пропустить лишние пробелы после кавычек(ну если они имеются, с чем еще не сталкивался)...
     
  16. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    Поменял cmp byte [esi],' ', но все равно не помогает. Самое интересное эта команда появилась после обнаружения ошибки. До этого я считал что там нет лишних пробелов, почему то и сейчас так думаю. Когда найду причину ошибки думаю что эта команда не понадобится!
     
  17. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    Все я разобрался где была ошибка! Дело в том что тотал в командной строке после кавычек ставил пробел, а потом если есть параметры. А я по этому пробелу и искал параметры. Ну пришлось проверять не идет ли сразу после пробела ноль, и если идет то значит нет параметров. А cmp byte [esi],' ' я убрал за ненадобностью.
     
  18. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Painter
    Вот именно, что примерно. И то исключительно в стандартных ситуациях. Реально же передать можно всё, что угодно. И, например, если в переданной командной строке будет только одна кавычка, то Ваш код должен выдавать ошибку, а не падать с ошибкой доступа к памяти. Кроме того, даже в стандартных ситуациях нулевой параметр (который "path\file.ext") не обязан содержать весь путь целиком, не обязан быть заключённым в кавычки и вообще не обязан быть. Программам, работающим с параметрами командной строки можно передать просто пробел (без "path\file.ext"), после чего ожидаемые аргументы, и они при этом должны и будут правильно работать с аргументами.
    Они могут быть и их нужно пропускать. Но одной этой инструкцией не обойтись уж точно.
    Он не обязательно присутствует. "path\file.ext" без пробела - валидная (и, кстати, часто передаваемая) командная строка. Пустая строка - валидная командная строка. Один пробел без ничего - валидная командная строка.

    В общем правильный разбор такой:
    1) Пропускаем всё до первого пробела или символа табуляции или конца строки (очень важная проверка, которая у Вас отсутствует) с учётом пункта 2.
    2) Если по пути (например, начиная с самого первого символа) встречается двойная кавычка, предварённая чётным числом (начиная с нуля и до ...) обратных слешей, то пропускаем всё (включая пробелы и символы табуляции) до следующей двойной кавычки, предварённой чётным числом обратных слешей, или до конца строки. После этого пропускаем двойную кавычку и продолжаем согласно пункту 1.
    3) Пропускаем все пробелы и символы табуляции, которых может быть от одного до ... (от нуля, если нарвались на конец строки).

    Вот после выполнения этих трёх пунктов у Вас есть указатель на первый аргумент командной строки или на конец командной строки, если аргументов нету.

    P.S. Хотя со слешами я, наверное, переборщил. Их, видимо, нужно игнорировать.
     
  19. Painter

    Painter New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2011
    Сообщения:
    46
    l_inc
    Можно поинтересоваться как определить конец строки? И еще один вопрос. Какую функцию выполняют следующие строки?
    Код (Text):
    1.                 or al,al                                        ; если конец командной строки то выходим
    2.                 je exit_find_file
     
  20. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Painter
    Конец строки - это символ с кодом 0. И этот код как раз и проверяет, не находится ли в al нуль. Хотя чаще используется test al,al, а не or al,al, хоть это и не принципиально.