如何使用va_list在FormatMessage()中添加多个参数?

时间:2018-03-15 19:50:15

标签: c winapi

我有以下功能:

void test() {
    char lpBuffer[MAX_PATH];
    LPVOID pv = NULL;
    va_list Environment = (va_list)malloc(MAX_PATH);
    Environment = (va_list)"abc";
    FormatMessageA(0x2500, "%1\\test.exe", 0, 0, (LPSTR)&pv, 0, &Environment);
    printf("%s\n", pv);
}

test()函数打印abc\test.exe。现在我想从函数参数中添加更多字符串。例如,

void test(char* var) {
    ...
    Environment =(va_list)"abc";
    ...
    ...
    FormatMessageA(0x2500, "%1\\test.exe %2", 0, 0, (LPSTR)&pv, 0, &Environment);
    printf("%s\n", pv);
}

现在该函数应该打印abc\test.exe var,但这不起作用。我已阅读FormatMessage()文件。我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:1)

va_list是一个不透明的对象类型,其实现取决于操作系统和/或编译器。它通常只是堆栈中的一个位置,但你不能假设它。

获得va_list的有效方法来自可变函数:

int myfunc(const char*fmt, ...)
{
  va_list args;
  va_start(args, fmt);
  // use args va_list here.
  va_end(args);
}

使用FormatMessage,它可能如下所示:

LPSTR FormatMyMessage(const char*fmt, ...)
{
  int ret;
  LPSTR str;
  va_list args;
  va_start(args, fmt);
  ret = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_STRING, fmt, 0, 0, (LPSTR) &str, 0, &args);
  va_end(args);
  return ret ? str : NULL;
}

...

LPSTR str = FormatMyMessage("%1\\test.exe %2", "abc", "def");
if (str)
{
  MessageBoxA(NULL, str, NULL, 0);
  LocalFree(str);
}

如果此模式不适合您,则无法使用va_list。

幸运的是,FormatMessage函数在使用FORMAT_MESSAGE_ARGUMENT_ARRAY标志时也支持简单数组中的参数:

DWORD_PTR params[2] = { (DWORD_PTR) "abc", (DWORD_PTR) "def" };
char*str;
if (FormatMessageA(FORMAT_MESSAGE_ARGUMENT_ARRAY|FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_STRING, "%1\\test.exe %2", 0, 0, (LPSTR) &str, 0, (va_list*) params))
{
  MessageBoxA(NULL, str, NULL, 0);
  LocalFree(str);
}

对于像这样的简单字符串格式,您也可以使用wsprintf,但它不会为您分配内存。