[wine] 将WindowsPath转为UnixPath的解决方案

[wine] 将WindowsPath转为UnixPath的解决方案

参考这个代码

wine-devel maling list

>>Am 07.01.2016 um 09:49 schrieb Jianqiu Zhang:
>>> +
>>> +pcap_dumper_t* CDECL wine_pcap_dump_open(pcap_t *p, const char *fname)
>>> +{
>>> +    return pcap_dump_open(p, fname);
>>> +}
>>
>>This can't work, the wpcap function might be called with fname set to "C:dump.pcap" and the native function will be confused by that.
> 
> Ah, I see, I didn't take this scheme in to consideration, I will try to use a helper function to convert the fname to UNIX fname
> Do you think it's a solution?

Wine needs to do that in other functions, have a look for wine_nt_to_unix_file_name

要在wine下实现对wpcap的兼容, 使用了wrapper的手段来进行, 即不自己实现wpcap的相应函数, 通过调用Linux下的pcap相应的函数, 达到同样的效果. 这个函数的作用是将监听到的数据dump到fname指定的文件里, 因Linux下的文件路径和Windows的不同, 想要调用LInux原生的pcap_dump_open之前需要进行路径的转换,因此尝试进行修改, 变成这个样子:

pcap_dumper_t* CDECL wine_pcap_dump_open(pcap_t *p, const char *fname)
{
    UNICODE_STRING nt_name;
    ANSI_STRING fname_unix;
    int len = 0;
    LPWSTR fname_W = HeapAlloc(GetProcessHeap(), 0, 100000);
    fname_unix.Buffer = NULL;
    printf("fname is %sn", fname);
    len = MultiByteToWideChar(CP_ACP, 0, fname, -1, fname_W, 0) ;
    printf("Convert to WCHAR Success, %d chars writtenn", len);
    printf("VOID_DEBUG Widechar is %sn", wine_dbgstr_w(fname_W));
    if(RtlDosPathNameToNtPathName_U(fname_W, &nt_name, NULL, NULL))
    wine_nt_to_unix_file_name(&nt_name, &fname_unix, FILE_OPEN, FALSE);
    RtlFreeUnicodeString(&nt_name);
    printf("VOID_DEBUG: unix_filename_is: %sn", fname_unix.Buffer);
    printf("=============================2===============================n");
    return pcap_dump_open(p, fname_unix.Buffer);
}

然后很干脆的跪了

fname is C:file
Convert to WCHAR Success, 8 chars written
VOID_DEBUG Widechar is L"088011128011"
ERR! Cannot Rename

Convert to Widechar 就出问题了 , 经过查看MSDN 的MultiByteToWideChar得到了相应的信息:

  len = MultiByteToWideChar(CP_ACP, 0, fname, -1, fname_W, 0) ;

https://msdn.microsoft.com/en-us/library/windows/desktop/dd319072(v=vs.85).aspx 参考MSDN

cchWideChar [in]

Size, in characters, of the buffer indicated by lpWideCharStr. If this value is 0, the function returns the required buffer size, in characters, including any terminating null character, and makes no use of the lpWideCharStr buffer.

因为我的cchWideChar = 0 所以转换后的结果没有存到fname_W里, 因而转换失败

 

在IRC上请教了wine开发者之后, 选用了RtlInitAnsiString + RtlAnsiStringToUnicodeString + RtlDosPathNameToNtPathName_U + wine_nt_to_unix_file_name 的方法, 注意 一定要有 RtlDosPathNameToNtPathName_U 这个函数, 将 由前两个函数转换得到的DosPath转换为NtPath, 不然在wine_nt_to_unix_file_name的时候会出错(STATUS_OBJECT_NAME_INVALID) 不合法的NtPath, 然后经过修改的代码如下:

pcap_dumper_t* CDECL wine_pcap_dump_open(pcap_t *p, const char *fname)
{
    UNICODE_STRING nt_name, dospathW;
    ANSI_STRING fname_dos;
    ANSI_STRING fname_unix;
    int res;
    fname_unix.Buffer = NULL;
    RtlInitAnsiString(&fname_dos, fname);
    RtlInitAnsiString(&fname_unix, NULL);
    res = RtlAnsiStringToUnicodeString(&dospathW, &fname_dos, TRUE);
    res = RtlDosPathNameToNtPathName_U(dospathW.Buffer, &nt_name, NULL, NULL);
    res  = wine_nt_to_unix_file_name(&nt_name, &fname_unix, FILE_OPEN_IF, FALSE);
    RtlFreeUnicodeString(&nt_name);
    RtlFreeAnsiString(&fname_dos);
    return pcap_dump_open(p, fname_unix.Buffer);
}

这个代码还有内存泄露和没有错误检查的问题, 需要继续修改,不过已经可以将winpath转换为unixpath了

Leave a Reply

Your email address will not be published. Required fields are marked *

8 + seventeen =

This site uses Akismet to reduce spam. Learn how your comment data is processed.