Как я могу записать универсальную функцию C для того, чтобы вызвать функцию Win32?

Вот как вы можете это сделать.

Во-первых, вы используете Document.querySelector () (или document.getElementById (), getElementsByTagName () и т. Д.) Для извлечения кнопки Element (предположим, что она имеет класс [111 ]). Далее вы можете просто получить доступ к его атрибутам и проверить его значения.

Если вы хотите проверить его disabled атрибуты, вы можете просто проверить значение в button['disabled'].

const button = document.querySelector('.buttonA');
console.log(button['disabled']) //prints true or false

6
задан Johan Dahlin 3 February 2010 в 00:13
поделиться

8 ответов

Нет, я не думаю, что его возможное делает с, не пишущий некоторый блок. Причина - Вы, нуждаются в точном управлении тем, что находится на стеке, прежде чем Вы вызовете целевую функцию, и нет никакого реального способа сделать это в чистом C. Конечно, просто сделать в блоке все же.

Кроме того, Вы используете PCSTR для всех этих аргументов, которые действительно справедливы const char *. Но так как все эти args не являются строками, что Вы на самом деле хотите использовать для возвращаемого значения, и для Аргументов [] void * или LPVOID. Это - тип, который необходимо использовать, когда Вы не знаете истинный тип аргументов, вместо того, чтобы бросить их к char *.

5
ответ дан 8 December 2019 в 13:49
поделиться

Первые вещи сначала: Вы не можете передать тип в качестве параметра в C. Единственная опция, с которой Вам оставляют, является макросами.

Эта схема работает с небольшой модификацией (массив пустоты * для аргументов), если Вы делаете a LoadLibrary/GetProcAddress вызывать функции Win32. Наличие строки имени функции иначе будет бесполезно. В C единственный способ, которым Вы вызываете функцию, через ее имя (идентификатор), который в большинстве случаев затухает к указателю на функцию. Также необходимо заботиться о кастинге возвращаемого значения.

Мой лучший выбор:

// define a function type to be passed on to the next macro
#define Declare(ret, cc, fn_t, ...) typedef ret (cc *fn_t)(__VA_ARGS__)

// for the time being doesn't work with UNICODE turned on
#define Call(dll, fn, fn_t, ...) do {\
    HMODULE lib = LoadLibraryA(dll); \
    if (lib) { \
        fn_t pfn = (fn_t)GetProcAddress(lib, fn); \
        if (pfn) { \
            (pfn)(__VA_ARGS__); \
        } \
        FreeLibrary(lib); \
    } \
    } while(0)

int main() {
    Declare(int, __stdcall, MessageBoxProc, HWND, LPCSTR, LPCSTR, UINT);

    Call("user32.dll", "MessageBoxA", MessageBoxProc, 
          NULL, ((LPCSTR)"?"), ((LPCSTR)"Details"), 
          (MB_ICONWARNING | MB_CANCELTRYCONTINUE | MB_DEFBUTTON2));

    return 0;
}
8
ответ дан 8 December 2019 в 13:49
поделиться

Другие штанги правы относительно почти определенной потребности в блоке или других нестандартных приемах на самом деле выполнить вызов, не говоря уже обо всех деталях фактических соглашений о вызовах.

Использование Windows DLLs по крайней мере два отличных соглашения о вызовах для функций: stdcall и cdecl. Вы должны были бы обработать обоих, и, возможно, даже должны были бы выяснить, чтобы использовать.

Один способ иметь дело с этим состоит в том, чтобы пользоваться существующей библиотекой для инкапсуляции многих деталей. Удивительно, существует тот: libffi. Примером его использования в среде сценариев является реализация Постороннего объекта Lua, модуль Lua, который позволяет интерфейсам произвольному DLLs быть созданными в чистом Lua кроме самого Постороннего объекта.

2
ответ дан 8 December 2019 в 13:49
поделиться

Много API Win32 берет указатели на структуры с определенными разметками. Из них большое подмножество следует за общим шаблоном, где первый DWORD должен быть инициализирован, чтобы иметь размер структуры, прежде чем это назовут. Иногда они требуют, чтобы блок памяти был передан, в который они запишут структуру, и блок памяти должен иметь размер, который определяется первым вызовом того же API с Нулевым указателем и чтением возвращаемого значения для обнаружения корректного размера. Некоторые API выделяют структуру и возвращают указатель на него, такой, что указатель должен быть освобожден со вторым вызовом.

Я не был бы то, который удивил, если набор API, которые можно полезно назвать в одном выстреле с отдельными аргументами, конвертируемыми от представления простой строки, является довольно маленьким.

Для создания этой идеи обычно применимой мы должны были бы перейти к вполне экстремальному значению:

typedef void DynamicFunction(size_t argumentCount, const wchar_t *arguments[],
                             size_t maxReturnValueSize, wchar_t *returnValue);

DynamicFunction *GenerateDynamicFunction(const wchar_t *code);

Вы передали бы простой отрывок кода в GenerateDynamicFunction, и он перенесет тот код в некоторый стандартный шаблон и затем вызовет компилятор C / компоновщик для создания DLL из него (существует довольно много бесплатных доступных опций), содержа функцию. Это было бы затем LoadLibrary тот DLL и использование GetProcAddress найти функцию и затем возвратить его. Это было бы дорого, но Вы будете делать это однажды и кэшировать получающийся DynamicFunctionPtr для повторного использования. Вы могли сделать это динамично путем хранения указателей в хеш-таблице, включенной самими фрагментами кода.

Шаблон мог бы быть:

#include <windows.h> 
// and anything else that might be handy

void DynamicFunctionWrapper(size_t argumentCount, const wchar_t *arguments[],
                             size_t maxReturnValueSize, wchar_t *returnValue)
{
    // --- insert code snipped here
}

Таким образом, использование в качестве примера этой системы было бы:

DynamicFunction *getUserName = GenerateDynamicFunction(
    "GetUserNameW(returnValue, (LPDWORD)(&maxReturnValueSize))");

wchar_t userName[100];
getUserName(0, NULL, sizeof(userName) / sizeof(wchar_t), userName);

Вы могли улучшить это путем создания GenerateDynamicFunction примите количество аргумента, таким образом, оно могло генерировать чек в начале обертки, что корректное количество аргументов было передано. И если Вы помещаете хеш-таблицу там для кэширования, функции для каждого встретились с codesnippet, Вы могли быть рядом со своим исходным примером. Функция Вызова взяла бы фрагмент кода вместо просто имени API, но иначе будет тем же. Это искало бы фрагмент кода в хеш-таблице, и если не существующий, это назовет GenerateDynamicFunction и сохранит результат в хеш-таблице в следующий раз. Это затем выполнило бы запрос к функции. Использование в качестве примера:

wchar_t userName[100];

Call("GetUserNameW(returnValue, (LPDWORD)(&maxReturnValueSize))",
     0, NULL, sizeof(userName) / sizeof(wchar_t), userName);

Конечно, не было бы большого количества точки, делающей ни одно из этого, если идея не состояла в том, чтобы открыть некоторую общую дыру в системе безопасности. например, выставить Call как веб-сервис. Последствия безопасности существуют для Вашей исходной идеи, но менее очевидны просто, потому что исходный подход, который Вы предложили, не будет настолько эффективным. Чем в более общем плане мощный мы делаем его, тем больше проблемы безопасности это было бы.

Обновление на основе комментариев:

Платформа.NET имеет функцию, названную p/invoke, который существует точно для решения проблемы. Таким образом, при выполнении этого как проекта узнать о материале Вы могли бы посмотреть на p/invoke для понимания то, насколько сложный это. Вы могли возможно быть нацелены на платформу.NET со своим языком сценариев - вместо того, чтобы интерпретировать сценарии в режиме реального времени или скомпилировать их в Ваш собственный байт-код, Вы могли скомпилировать их в IL. Или Вы могли разместить существующий язык сценариев от многих, уже доступных на.NET.

1
ответ дан 8 December 2019 в 13:49
поделиться

Наличие функции как этот походит на плохую идею, но можно попробовать это:

int Call(LPCSTR DllName, LPCSTR FunctionName, 
  USHORT ArgumentCount, int args[])
{
   void STDCALL (*foobar)()=lookupDLL(...);

   switch(ArgumentCount) {
        /* Note: If these give some compiler errors, you need to cast
           each one to a func ptr type with suitable number of arguments. */
      case 0: return foobar();
      case 1: return foobar(args[0]);
      ...
   }
}

В 32-разрядной системе почти все значения вписываются в 32-разрядное слово, и более короткие значения продвинуты на стек как 32-разрядные слова для аргументов вызова функции, таким образом, необходимо смочь назвать фактически все API-функции Win32 этим путем, просто бросить аргументы интервалу и возвращаемому значению от интервала до соответствующих типов.

0
ответ дан 8 December 2019 в 13:49
поделиться

Я не уверен, будет ли это представлять интерес для Вас, но опция состояла бы в том, чтобы выйти из оболочки к RunDll32.exe и иметь его, выполняют вызов функции для Вас. RunDll32 имеет некоторые ограничения, и я не полагаю, что можно получить доступ к возвращаемому значению вообще, но если Вы сформируете параметры командной строки правильно, то это вызовет функцию.

Вот ссылка

0
ответ дан 8 December 2019 в 13:49
поделиться

Во-первых, необходимо добавить размер каждого аргумента как дополнительный параметр. Иначе необходимо предугадать размер каждого параметра для каждой функции для продвижения на стек, который возможен для функций WinXX, так как они должны быть совместимы с параметрами, они документируются, но утомительные.

Во-вторых, нет "чистого C" способа вызвать функцию, не зная аргументы за исключением функции varargs, и нет никакого ограничения на соглашение о вызовах, используемое функцией в.DLL.

На самом деле вторая часть более важна, чем первое.

В теории Вы могли настроить препроцессор macro/#include структура для генерации всех комбинаций типов параметра до, скажем, 11 параметров, но это подразумевает, что Вы знаете заранее, какие типы будут переданы через Вас функция Call. Который является довольно сумасшедшим, если Вы спрашиваете меня.

Хотя, если Вы действительно хотели сделать это небезопасно, Вы могли бы передать скорректированное имя C++ и использование UnDecorateSymbolName извлечь типы параметров. Однако это не будет работать на функции, экспортируемые со связью C.

0
ответ дан 8 December 2019 в 13:49
поделиться

Вы можете попробовать что-то вроде этого - это хорошо работает для функций API Win32:

int CallFunction(int functionPtr, int* stack, int size)
{
    if(!stack && size > 0)
        return 0;
    for(int i = 0; i < size; i++) {
        int v = *stack;
        __asm {
            push v
        }
        stack++;
    }
    int r;
    FARPROC fp = (FARPROC) functionPtr;
    __asm {
        call fp
        mov dword ptr[r], eax
    }
    return r;
}

Параметры в аргументе «стек» должны быть в обратном порядке (так как это порядок, в котором они помещаются в стек).

1
ответ дан 8 December 2019 в 13:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: