You get ERROR_INVALID_PARAMETER because you are trying to free a string not allocated with heap functions. The RtlFreeAnsiString you wrote below is unnecessary. This is not the only mistake though - I'm aware that you are still working on it, nevertheless I thought it might be useful for you to point them out, to make you more familiar with the (sometimes a bit strict) Wine coding guidelines. As a general remark, I would suggest to look at other examples how some API functions are used, to get more familiar with them, and to look at the example I provided on IRC yesterday: http://pastebin.com/raw/m43tkLdT
Below are some inline comments:
On 10.02.2016 14:59, Jianqiu Zhang wrote:
Hi, sorry for the late reply
I have met some problem when implementing wine_pcap_dump_open My wine_pcap_dump_open code goes like this
--snip--
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;
Please always use variables with the proper type (NTSTATUS or BOOL or ...).
fname_unix.Buffer = NULL; RtlInitAnsiString(&fname_dos, fname); RtlInitAnsiString(&fname_unix, NULL);
The line above is not necessary.
res = RtlAnsiStringToUnicodeString(&dospathW, &fname_dos, TRUE);
There should be an error check here and you should set last error if appropriate.
res = RtlDosPathNameToNtPathName_U(dospathW.Buffer, &nt_name, NULL, NULL); if(!res) {
You should release the dospathW unicode string here and set an error.
printf("RtlDosPathNameToNtPathName_U failed\n"); return NULL; } res = wine_nt_to_unix_file_name(&nt_name, &fname_unix, FILE_OPEN_IF, FALSE); printf("#1 ERRCODE is %X\n", GetLastError()); printf("VOID_DEBUG: Nt FileName is %s\n", wine_dbgstr_w(nt_name.Buffer)); if(res != 0 && res != 0xC000000F)
Please always use STATUS_* variables instead of hardcoded numbers.
{ SetLastError(0xB7);
Same here. Code to release allocated memory is also missing.
printf("wine_nt_to_unix_file_name failed\n"); printf("#2 ERRCODE is %X\n", GetLastError()); return NULL; } RtlFreeUnicodeString(&nt_name); printf("#3 ERRCODE is %X\n", GetLastError()); RtlFreeAnsiString(&fname_dos);
RtlInitAnsiString does not duplicate the string. You get an ERROR_INVALID_PARAMETER error here because you are trying to free a string not allocated with heap functions.
//HeapFree(GetProcessHeap(), 0, fname_dos.Buffer); printf("#4 ERRCODE is %X\n", GetLastError()); //SetLastError(0xB7); return pcap_dump_open(p, fname_unix.Buffer);
You are leaking memory of fname_unix here. In contrast to fname_dos, it is allocated on the heap.
}
--snip--
And I modify the test program source code , the source is attached in the attachment(test.c)
And I run the same test both on win32(XP) and wine , Below are my tests:
- test.exe "AFileNameDoesNotExist" on wine it gets errorcode 0x57 on Windows it gets errorcode 0x00, Both get the correct dumpfile
- test.exe "NameThatExists" on wine it gets errorcode 0x57, on windows it gets errorcode 0xB7, both overwrite the previous file and get the correct dumpfile
And I dig into the code found RtlFreeAnsiString calls two functions RtlFreeHeap and RtlZeroMemory both give the errorcode 0x57(ERROR_INVALID_PARAMETER) , I wonder why this happens If it's a undefined behavior, can I use SetLastError(0) to Manually reset the error code? Thanks in advance