Кресты / Говнокод #18197 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
class LoaderLock
	{
	public:
		void lock();
		void unlock();
		bool IsLocked() const;
		LoaderLock() = default;

	private:
		LoaderLock(LoaderLock&) = delete;
		LoaderLock(LoaderLock&&) = delete;
		LoaderLock& operator=(LoaderLock&) = delete;
		LoaderLock& operator=(LoaderLock&&) = delete;
		bool _Locked = false;
		ULONG _cookie = 0;
		std::unique_ptr<void, std::function<void(void*)>> _ntdll{ LoadLibrary("NTDLL.DLL"), [](void* h){if (h)FreeLibrary((HMODULE)h); } };
		typedef NTSTATUS(__stdcall*LdrLockLoaderLockFunc)(
			ULONG Flags,
			ULONG *State,
			ULONG *Cookie);
		LdrLockLoaderLockFunc _LdrLockLoaderLock = !_ntdll ? 0 : (LdrLockLoaderLockFunc)GetProcAddress((HMODULE)_ntdll.get(), "LdrLockLoaderLock");
		typedef NTSTATUS(__stdcall*LdrUnlockLoaderLockFunc)(
			ULONG Flags,
			ULONG Cookie);
		LdrUnlockLoaderLockFunc _LdrUnlockLoaderLock = !_ntdll ? 0 : (LdrUnlockLoaderLockFunc)GetProcAddress((HMODULE)_ntdll.get(), "LdrUnlockLoaderLock");
	};

Уже давно минул 2014 год, а C++11 не перестает радовать нас размазанными по интерфейсу конструкторами и деструкторами.

Запостил: LispGovno LispGovno, (Updated )

Комментарии (124) RSS

  • Кстати, а почему с ntdll никто не линкуется, а вечно ебутся с LoadLibrary() + GetProcAddress()?
    Ответить
  • >std::unique_ptr<void, std::function<void(void*)>>
    Как хорошо быть Си мастер рейс.
    Ответить
    • > Си мастер рейс.
      Кем и почему? ну и лучше unique_ptr<void, void(*)(void*)>
      Ответить
  • > LdrLockLoaderLock
    Yo dawg

    Полное API, наверное, выглядит так:
    LdrLockLoaderLock
    LdrUnlockLoaderLock
    LdrLockLoaderUnlock
    LdrUnlockLoaderUnlock
    LdrLockUnloaderLock
    LdrUnlockUnloaderLock
    LdrLockUnloaderUnlock
    LdrUnlockUnloaderUnlock
    Ловить дедлок в такой схеме, наверное, было бы равноценно потеряться в пятимерном пространстве.
    Ответить
  • Больше RAII для бога RAII (не читайте перед сном):
    class Library
    {
    public:
        Library(const char *name) : mod(LoadLibrary(name)) {}
        ~Library() { FreeLibrary(mod); }
        template <typename T> T GetProcAddress(const char * name) {
            return ::GetProcAddress(mod, name);
        }
    private:
        HMODULE mod;
    };
    
    class LoaderLock
    {
    public:
        LoaderLock()
        {
            ntdll.GetProcAddress<NTSTATUS (__stdcall *)(ULONG, ULONG*, ULONG*)>("LdrLockLoaderLock")(0, 0, &cookie);
        }
        ~LoaderLock()
        {
            ntdll.GetProcAddress<NTSTATUS (__stdcall *)(ULONG, ULONG*)>("LdrUnlockLoaderLock")(0, &cookie);
        }
    private:
        Library ntdll { "ntdll.dll" };
        ULONG cookie;
    };
    Ответить
    • Я тебя расстрою может, но GetProcAddress вызывает LdrLockLoaderLock и LdrUnlockLoaderLock. И не очень пони зачем Library написал, код выше делает также, только средствами стд
      Ответить
      • > GetProcAddress вызывает LdrLockLoaderLock и LdrUnlockLoaderLock
        А этот лок нереентерабельный?
        Ответить
        • реентерабильный, просто ты три раза его захватил и отпустил подряд вместо того чтобы сделать это один раз
          Ответить
          • Мне похуй, если честно. Я ведь ещё и либу ищу, рефаю и дерефаю на каждый чих (так что есть вероятность, что не 3, а все 5). А раз лок реентерабельный - так оно ещё и работать будет 😉
            Ответить
      • > средствами стд
        И при этом выглядит как ёбаный пиздец, угу. Моё Library по крайней мере хоть какие-то зайчатки инкапсуляции и удобства показывает...
        // код курильщика
        std::unique_ptr<void, std::function<void(void*)>> _ntdll{ LoadLibrary("NTDLL.DLL"), [](void* h){if (h)FreeLibrary((HMODULE)h); } };
        
        // код здорового человека
        Library _ntdll { "ntdll.dll" }
        Ответить
    • Library написал чтобы сделать вот такой пиздец:
      class Library {
          // ...
          template <typename Ret, typename... Args> 
          Ret operator () (const char * name, Args... args) {
              return ((Ret (*)(Args...))GetProcAddress(name))(args...);
          }
      };
      
      class LoaderLock {
      public:
          LoaderLock() { ntdll("LdrLockLoaderLock", 0, 0, &cookie); }
          ~LoaderLock { ntdll("LdrUnlockLoaderLock", 0, &cookie); }
      private:
          Library ntdll { "ntdll.dll" };
      };
      Ответить
      • > Library ntdll { "ntdll.dll" };
        Тебя походу торкнули фигурные скобки
        Ответить
        • DSL для прикручивания апишек:
          Library ntdll { "ntdll.dll" };
          Function<NTSTATUS (__stdcall *)(ULONG, ULONG*, ULONG*)>
              LdrLockLoaderLock { ntdll, "LdrLockLoaderLock" };
          Function<NTSTATUS (__stdcall *)(ULONG, ULONG*)>
              LdrUnlockLoaderLock { ntdll, "LdrUnlockLoaderLock" };
          Ответить
          • Допилить что ли поддержку линупса (dlopen/dlsym) да выложить на гитхаб...
            Ответить
              • Ну почему. На работе нужна была такая либа одно время, но её не было, поэтому наговнокодили с тайпдефами... А тут в c++11 такая няшнота получается - ни одной лишней строчки.
                Ответить
                        • пасаны, пора приложение говнокод пилить для ведра
                          Ответить
                          • на 5 XE можно кодить на делфях под андроид.
                            Я даже прокси-чекер накомпелял, но девайся нет, тоска.
                            Ответить
                              • Не только.
                                http://implement.do.am/Images/6545435345.png

                                Прога должна была увидеть свет пару лет назад. Проект изначально разрабатывался на AutoIt, потом был переписан на PureBasic и наконец на Delphi. Затем я взялся переписывать код на FreePascal, чтобы прогу можно было безбоязненно распространять, но встретил на пути слишком много препятствий.
                                Ответить
                                  • Нет, это не фейк. Я приложил максимум усилий, чтобы сделать прогу устойчивой и полезной. Прога отлаживалась с fastmm, и до сих пор работает под этим ММ. Никакой функциональщины, одно слошное ООП.
                                    Ответить
                            • Сессия фактически началась - один не вывезу. Помощь треба
                              Ответить
                              • я б не отказался помочь, но я еще тот распиздяй. Да и нормальной апишки у ГК нету.
                                Ответить
                          • Прошу добавить туда оффлайн-режим с возможностью поиска по ГК и отображения удалённых постов (не зря ж я их качал). Ну или писать программу так, чтобы потом можно было добавить.
                            Ответить
                            • А ты участвовать в разработке не будешь, пельмень?
                              Чет мне кажется что наш уютненький не поддерживает нормального апи так что придётся парсить хтмл ручками
                              Ответить
                              • > мне кажется
                                Креститься надо. Само собой не поддерживает... Но, с другой стороны, тут няшный xhtml, который вполне жрётся xml парсерами.
                                Ответить
                                  • Простой html не жрётся. Ему специальный парсер нужен.
                                    Ответить
                                    • А, я чет тупанул
                                      В любом случае сейчас у меня предсессия, потоп в конце июня сессия, так что пока запишу в хотели, если не обленюсь буду летом пилить
                                      Ответить
                                    • Я думаю, в данном конкретном случае всё же идеологически важен самописный парсер на регэкспах.
                                      Ответить
                              • Я буду незримо присутствовать где-то рядом. А так мне лень...
                                Мда. Главное - сделать парсилку потоньше, а то вдруг API добавят.
                                Ответить
                                • Один фиг - если заменят все придётся или перепиливать или адаптеры втыкать по канонам ооп
                                  Ответить
                                • Опи не добавят, тут и так всякие стерторы ботов водят
                                  Ответить
                                  • "Туалет не добавят, тут и без этого всякие бомжи срут."

                                    Имхо, вреда от API не будет - все, кто хотел, уже ботов написали.
                                    Ответить
                              • Семен когда был вменяемым. Постил прикладуху для андроида для чтения ГК. надо на гитхабе поискать sam может всплывет
                                Ответить
                                • Так это настоящий s-a--m постил. А потом ныне покойный s-a--m, которого в девичестве звали anonimзабылкакойхеш, украл у него аккаунт.
                                  Ответить
                                  • >настоящий s-a--m
                                    Бля а я то все думал, что это все тот же чел, только после обострения.

                                    ШОК за Семена в ГК срал его злой брат близнец. [u]Смотреть онлайн (Только для владельцев платных аккаунтов)[u]
                                    Ответить
                    • tampermonkey не идет на телефоне, сюда по отзывам - не только у меня
                      Ответить
                • > ни одной лишней строчки.

                  потому что ты обработку ошибок забыл.
                  Ответить
                  • А нафига она в декларативном описании? Проверка будет запрятана в Function и Library (кидаем исключение, если не нашли функцию или либа не загрузилась). Либо будет непосредственно перед вызовом if (somelib.somefunc) somelib.somefunc(...).
                    Ответить
                    • > Проверка будет запрятана в Function и Library

                      ну ты как бы сверху и привел часть их реализации. GetProcAddr() без проверки возврата непредсказуемая штука.

                      ЗЫ по моему опыту такой syntax sugar только частично помогает. грабли наступают тогда когда в разных версиях виндов у функций аргументы (и/или их типы) меняются. и версию виндов надо динамичски проверять...
                      Ответить
                      • Ну реализация выше - хуёвая и без проверок, тут я не спорю 🙂

                        А насчёт разных аргументов можно вот так попробовать (искуственный пример):
                        class foo_lib {
                        public:
                            // false - тот самый required
                            Library foo { "foo.dll", "libfoo.so.1", "libfoo.so.2" };
                            Function<int (int, int), false> foo_v1 { foodll, "foo" };
                            Function<int (double), false> foo_v2 { foodll, "foo" };
                            bool new_foo_version_detected;
                        public:
                            foo_lib() {
                                new_foo_version_detected = ...;
                            }
                            int foo(int x, int y) {
                                if (new_foo_version_detected)
                                    return foo_v2(x);
                                return foo_v1(x, y);
                            }
                        };
                        Ответить
                      • Хотя я вот хочу отказаться от шаблонов, и попробовать наебашить на макросах, чтобы в сишке и старых крестах можно было заюзать...
                        Ответить
                          • Ага, один раз я до них уже наебашился (AES на препроцессоре).
                            Ответить
                          • Ну либы же не только в прикладнухе надо подгружать.
                            Ответить
                            • в не-прикладухе - системщина, встроенщина, сетевуха - там народ (например я) предпочитает явный стиль работы с системой, и библиотеки только по нужде используются (SOUP).

                              только в прикладухе народ усиленно страдает "не хочу ничего про систему слышать и видеть, лучше еще какую библиотечку качнуть".
                              Ответить
                                • переносимость с виндов на винды?

                                  либа решает виндово-специфические проблемы. на каком линухе класс проблем "недокументированые функции кернела и трахания с их вызовом" просто отсутствует. (все что нужно есть в хидерах, а новые фишки можно вызвать с помощью syscall() макро из libc.)

                                  а если это какой плагиновый интерфейс, то есть более простые способы доступа, нежели чем куча GetProcAddr()/dlsym().
                                  Ответить
                    • А что будешь делать с SetCurrentDirectory, SetCurrentDirectoryA и SetCurrentDirectoryW?
                      Ответить
                      • Оставлю версию с A или с W по ситуации, ибо SetCurrentDirectory не существует.
                        Function<NTSTATUS (__stdcall *)(LPCSTR)>
                            SetCurrentDirectory { ntdll, "SetCurrentDirectoryA" };
                        Ответить
                        • Короче нужно как-то вот так сделать
                          auto SetCurrentDirectory = make_function<
                              BOOL WINAPI (LPCSTR),
                              BOOL WINAPI (LPWCSTR)
                          > 
                          ( ntdll,
                               "SetCurrentDirectoryA",
                               "SetCurrentDirectoryW"  
                          );
                          Ответить
                      • как и в официальных хидерах? две инстанции на *A() и на *W(). плюс референс указывающий на одну из них, в зависимости от `UNICODE` (или как там дефайн нынче называется).
                        Ответить
                        • Кресты же. SetCurrentDirectory(char*), SetCurrentDirectory(wchar_t), нужную перегрузку выберет компилятор.
                          Я бы вообще предпочел загрузить только юникодную функцию и перегонять в неё из utf8.
                          Ответить
                  • Мне вот такой вариант нравится - добавить в описание функций флажок required.

                    Если required и не нашлась функция или либа - кидаем исключение сразу.

                    Если не required и не нашлась - кидаем исключение при вызове оператором (). Можно проверить оператором bool(), чтобы понять, есть ли эта функция в данной версии либы.
                    Ответить
                      • Надо в конструкторе чтобы уже было известно загрузилась функция или нет. Никаких кеширований

                        А то ведь везде где вызываешь расставлять ловлю исключений на тот случай если не загрузилась функция - та ещё упоротость
                        Ответить
                        • Да не надо расставлять ловлю исключений. Всегда можно посмотреть, загрузилась ли функция (operator bool). А если функции нет, но код этого не учитывает и всё равно дергает operator () - это самая настоящая исключительная ситуация, в которой не грех вбросить исключение (если его тут не бросить - один хуй segfault всё распидорасит.

                          А если флаг required установлен - то исключение вылетит в момент конструирования, где его несложно поймать (или не ловить).

                          Как-то так я себе это представлял 😉
                          Ответить
                        • Ну и в случаях, когда надо выбрать функцию в зависимости от версии - делаем враппер как в >>286917 и кидаем исключение из конструктора, если не нашлось никаких кандидатов.
                          Ответить
  • Почему уникве_птр инстанциируется двумя параметрами?
    Ответить
    • Второй - функция, которая вызовется для освобождения.
      Ответить
      • Вот я ушел в телефон и на сайте все сразу скисло. Где все? Ау! Где гоатсЕ? Ау!
        Ответить
        • Возможно, просто не осталось интересных тем для разговоров.
          Появление комментариев на ГК подобно испарению/кристаллизации. Нужен какой-то центр, вокруг которого начнёт расти кристалл дискуссии. Ну или, если сравнивать с испарением, центр парообразования дискуссии.
          В выходные посетители обычно уходят с работы и не участвуют в обсуждениях, на ГК остаются только школьники, с этим ничего не поделать. А вот если календарь не показывает никаких праздников, надо начинать флудить и троллить, а не просто периодически обновлять сток, ведь все обновляют сток и не пишут комментарии, если им не на что ответить.
          Ответить
      • Так там не функция в параметре, там сигнатура функции.
        Ответить
        • Там и сигнатура функции в параметре шаблона и сама функция в параметре конструктора. Читай внимательней.

          P.S. Код не taras-safe, слишком длинные строки.
          Ответить
          • А как её вызывать-то надо, если сигнатура - параметр шаблона? Или там на самом деле требуется лишь наличие оператора () с определёнными параметрами, а шаблон нужен лишь чтобы можно было пихать и функции, и лямбды, и std::function?
            Ответить
            • std::unique_ptr<void, std::function<void(void*)>> _ntdll {
              LoadLibrary("NTDLL.DLL"),
              [](void* h){if (h)FreeLibrary((HMODULE)h);</span> }
              };

              > шаблон нужен лишь чтобы можно было пихать и функции, и лямбды, и std::function
              И даже аллаха, если у него есть operator ().
              Ответить
              • Причём именно принимающий void* и возращающий void?
                > (HMODULE)h
                Забавно, везде такие шаблоны модные, а при использовании всё равно сишный говнокаст писать.
                Ответить
                • > принимающий void*
                  Если точнее - T*, где T* - что-нибудь, во что может кастануться указатель на первый аргумент. Насчёт возврата void - х.з., должен проканать и не void, просто заигнорит результат.

                  В общем это функция, которую unique_ptr будет вызывать для освобождения указателя.

                  > сишный говнокаст
                  Причём этот HMODULE и есть void *, емнип.
                  Ответить
              • Зачем тебе уникью птр? std::shared_ptr же удобнее и функциональнее:
                std::shared_ptr<void> _ntdll {
                LoadLibrary("NTDLL.DLL"),
                [](void* h){if (h)FreeLibrary((HMODULE)h); }
                };
                Ответить
  • Ваше с++ - говно, на с++ кодят только динозавры.
    Ответить

Добавить комментарий

Где здесь C++, guest?!

    А не использовать ли нам bbcode?


    8