Hello,
I'm trying to implement the "stub" function wtmpnam in msvcrt. Below is a patch at an attempt; there are a number of questions I have about the right way to implement it, and since I don't know the Wine codebase I thought perhaps readers of this list might (with minimal effort) be able to point me in the right direction.
Below is the text of the patch (it's short). My questions are embedded after //-style comments (4 in total).
Many thanks in advance for your help! --Tim
diff -U 3 -r winecopy/wine-1.1.8/dlls/msvcrt/file.c wine-1.1.8/dlls/msvcrt/file.c --- winecopy/wine-1.1.8/dlls/msvcrt/file.c 2008-11-07 10:09:33.000000000 -0600 +++ wine-1.1.8/dlls/msvcrt/file.c 2008-11-29 07:32:43.000000000 -0600 @@ -88,6 +88,7 @@
/* INTERNAL: Static buffer for temp file name */ static char MSVCRT_tmpname[MAX_PATH]; +static MSVCRT_wchar_t MSVCRT_wtmpname[MAX_PATH];
static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e'; static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't'; @@ -2990,6 +2991,32 @@ }
/********************************************************************* + * wtmpnam (MSVCRT.@) + */ +MSVCRT_wchar_t * CDECL MSVCRT_wtmpnam(MSVCRT_wchar_t *s) +{ + static int unique; + char tmpstr[16]; + MSVCRT_wchar_t wtmpstr[16]; + MSVCRT_wchar_t *p; + int count; + if (s == 0) + s = MSVCRT_wtmpname; + msvcrt_int_to_base32(GetCurrentProcessId(), tmpstr); + p = s + MSVCRT_swprintf(s, "\s%s.", tmpstr); // "implicit declaration" error, function is defined in wcs (but no wcs.h); but how to convert format string to MSVCRT_wchar_t? + for (count = 0; count < MSVCRT_TMP_MAX; count++) + { + msvcrt_int_to_base32(unique++, tmpstr); + mbstowcs(wtmpstr,tmpstr,strlen(tmpstr)); // need a MSVCRT_wchar version + wcscpy(p, wtmpstr); // need a MSVCRT_wchar version + if (GetFileAttributesW(s) == INVALID_FILE_ATTRIBUTES && + GetLastError() == ERROR_FILE_NOT_FOUND) + break; + } + return s; +} + +/********************************************************************* * tmpfile (MSVCRT.@) */ MSVCRT_FILE* CDECL MSVCRT_tmpfile(void) diff -U 3 -r winecopy/wine-1.1.8/dlls/msvcrt/msvcrt.spec wine-1.1.8/dlls/msvcrt/msvcrt.spec --- winecopy/wine-1.1.8/dlls/msvcrt/msvcrt.spec 2008-11-07 10:09:33.000000000 -0600 +++ wine-1.1.8/dlls/msvcrt/msvcrt.spec 2008-11-29 07:12:10.000000000 -0600 @@ -579,7 +579,7 @@ @ cdecl _wstrtime(ptr) @ cdecl _wsystem(wstr) @ cdecl _wtempnam(wstr wstr) -@ stub _wtmpnam #(ptr) +@ cdecl wtmpnam(ptr) MSVCRT_wtmpnam // needs an underscore? @ cdecl _wtoi(wstr) ntdll._wtoi @ cdecl _wtoi64(wstr) ntdll._wtoi64 @ cdecl _wtol(wstr) ntdll._wtol
Hi Tim,
- p = s + MSVCRT_swprintf(s, "\s%s.", tmpstr); // "implicit declaration"
error, function is defined in wcs (but no wcs.h); but how to convert format string to MSVCRT_wchar_t?
Declare the format string as a const buffer, e.g.: static const MSVCRT_wchar_t tmpFmt[] = { '\','s','%','s','.',0 };
- mbstowcs(wtmpstr,tmpstr,strlen(tmpstr)); // need a MSVCRT_wchar
version
MultiByteToWideChar should be enough.
- wcscpy(p, wtmpstr); // need a MSVCRT_wchar version
Just use strcpyW, as other files in msvcrt do.
+@ cdecl wtmpnam(ptr) MSVCRT_wtmpnam // needs an underscore?
The name in the .spec file must match the name in the .c file, that's all. --Juan
Hi Juan,
Many thanks for your help. This compiles now. I think I must not have something else defined, though, because when I run the program I still get a message saying wtmpnam is not implemented. Do I have to do something else to "register" the function?
Here's the output:
tim@diva:~/bin/filesforconversion$ wine XConvert.exe fixme:iphlpapi:NotifyAddrChange (Handle 0x7d8a49f8, overlapped 0x7d8a49dc): stub fixme:shell:DllCanUnloadNow stub wine: configuration in '/home/tim/.wine' has been updated. err:listview:LISTVIEW_WindowProc unknown msg 3e9d wp=0032ef78 lp=00000000 err:listview:LISTVIEW_WindowProc unknown msg 3e9d wp=0032ef78 lp=00000000 wine: Call from 0x223de1e to unimplemented function MSVCRT.dll._wtmpnam, aborting wine: Call from 0x223de1e to unimplemented function MSVCRT.dll._wtmpnam, aborting
For reference, the current state of the patch is pasted below.
Thanks, --Tim
diff -U 3 -r winecopy/wine-1.1.8/dlls/msvcrt/file.c wine-1.1.8/dlls/msvcrt/file.c --- winecopy/wine-1.1.8/dlls/msvcrt/file.c 2008-11-07 10:09:33.000000000 -0600 +++ wine-1.1.8/dlls/msvcrt/file.c 2008-11-29 10:16:03.000000000 -0600 @@ -88,6 +88,7 @@
/* INTERNAL: Static buffer for temp file name */ static char MSVCRT_tmpname[MAX_PATH]; +static MSVCRT_wchar_t MSVCRT_wtmpname[MAX_PATH];
static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e'; static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't'; @@ -2990,6 +2991,36 @@ }
/********************************************************************* + * wtmpnam (MSVCRT.@) + */ +extern int CDECL MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... ); /* Defined in wcs.c */ + +MSVCRT_wchar_t * CDECL MSVCRT_wtmpnam(MSVCRT_wchar_t *s) +{ + static int unique; + char tmpstr[16]; + MSVCRT_wchar_t wtmpstr[16]; + MSVCRT_wchar_t *p; + int count; + static const MSVCRT_wchar_t tmpFmt[] = { '\','s','%','s','.',0 }; + + if (s == 0) + s = MSVCRT_wtmpname; + msvcrt_int_to_base32(GetCurrentProcessId(), tmpstr); + p = s + MSVCRT_swprintf(s, tmpFmt, tmpstr); + for (count = 0; count < MSVCRT_TMP_MAX; count++) + { + msvcrt_int_to_base32(unique++, tmpstr); + MultiByteToWideChar(CP_ACP, 0, tmpstr, strlen(tmpstr), wtmpstr, 16); + strcpyW(p, wtmpstr); + if (GetFileAttributesW(s) == INVALID_FILE_ATTRIBUTES && + GetLastError() == ERROR_FILE_NOT_FOUND) + break; + } + return s; +} + +/********************************************************************* * tmpfile (MSVCRT.@) */ MSVCRT_FILE* CDECL MSVCRT_tmpfile(void) diff -U 3 -r winecopy/wine-1.1.8/dlls/msvcrt/msvcrt.spec wine-1.1.8/dlls/msvcrt/msvcrt.spec --- winecopy/wine-1.1.8/dlls/msvcrt/msvcrt.spec 2008-11-07 10:09:33.000000000 -0600 +++ wine-1.1.8/dlls/msvcrt/msvcrt.spec 2008-11-29 07:12:10.000000000 -0600 @@ -579,7 +579,7 @@ @ cdecl _wstrtime(ptr) @ cdecl _wsystem(wstr) @ cdecl _wtempnam(wstr wstr) -@ stub _wtmpnam #(ptr) +@ cdecl wtmpnam(ptr) MSVCRT_wtmpnam @ cdecl _wtoi(wstr) ntdll._wtoi @ cdecl _wtoi64(wstr) ntdll._wtoi64 @ cdecl _wtol(wstr) ntdll._wtol
On Saturday 29 November 2008 10:00:00 am Juan Lang wrote:
Hi Tim,
- p = s + MSVCRT_swprintf(s, "\s%s.", tmpstr); // "implicit
declaration" error, function is defined in wcs (but no wcs.h); but how to convert format string to MSVCRT_wchar_t?
Declare the format string as a const buffer, e.g.: static const MSVCRT_wchar_t tmpFmt[] = { '\','s','%','s','.',0 };
- mbstowcs(wtmpstr,tmpstr,strlen(tmpstr)); // need a MSVCRT_wchar
version
MultiByteToWideChar should be enough.
- wcscpy(p, wtmpstr); // need a MSVCRT_wchar version
Just use strcpyW, as other files in msvcrt do.
+@ cdecl wtmpnam(ptr) MSVCRT_wtmpnam // needs an underscore?
The name in the .spec file must match the name in the .c file, that's all. --Juan
Hi Tim,
Many thanks for your help. This compiles now. I think I must not have something else defined, though, because when I run the program I still get a message saying wtmpnam is not implemented. Do I have to do something else to "register" the function?
No, you've just got a typo:
-@ stub _wtmpnam #(ptr) +@ cdecl wtmpnam(ptr) MSVCRT_wtmpnam
You removed an underscore from the _wtmpnam function. Don't, and the function should be called. --Juan
Hi Juan,
Thanks again---that did the trick (it wasn't so much a typo as I didn't know what I was doing...)
So wtmpnam seems to work. Sadly, another line in the output indicates there's another error: err:listview:LISTVIEW_WindowProc unknown msg 3e9d wp=0032ef78 lp=00000000 and that prevents the program from executing. Any ideas?
At what point & how should the wtmpnam patch (or does my last email + your suggestion about the _ effectively do that?)
Thanks, --Tim
On Saturday 29 November 2008 10:30:20 am Juan Lang wrote:
Hi Tim,
Many thanks for your help. This compiles now. I think I must not have something else defined, though, because when I run the program I still get a message saying wtmpnam is not implemented. Do I have to do something else to "register" the function?
No, you've just got a typo:
-@ stub _wtmpnam #(ptr) +@ cdecl wtmpnam(ptr) MSVCRT_wtmpnam
You removed an underscore from the _wtmpnam function. Don't, and the function should be called. --Juan
Hi Tim,
So wtmpnam seems to work. Sadly, another line in the output indicates there's another error: err:listview:LISTVIEW_WindowProc unknown msg 3e9d wp=0032ef78 lp=00000000 and that prevents the program from executing. Any ideas?
Sorry, don't know about this one. What program is this? Perhaps you could open a bug?
At what point & how should the wtmpnam patch (or does my last email + your suggestion about the _ effectively do that?)
Missing a verb here. I assume you're asking at what point you should send your wtmpnam patch? That should be sent to wine-patches. One style suggestion I'd make though: +extern int CDECL MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... ); /* Defined in wcs.c */
This is ugly. Possible approaches that aren't as jarring: 1. Add this declaration to msvcrt.h 2. Use MSVRT_vsnwprintf instead, since it's already declared in msvcrt.h 3. Use sprintfW instead.
--Juan
Am Samstag, den 29.11.2008, 10:27 -0600 schrieb Tim Holy:
Hi Juan,
Many thanks for your help. This compiles now. I think I must not have something else defined, though, because when I run the program I still get a message saying wtmpnam is not implemented.
No. But Juan Lang misunderstood your question about the underscore. In the line
@ cdecl wtmpnam(ptr) MSVCRT_wtmpnam // needs an underscore?
"wtmpnam" does need an underscore, as the undefined function is named "_wtmpnam", see the log you posted. Juan said, it just has to match you C file. This is true for the "MSVCRT_wtmpnam" part of the same line.
Regards, Michael Karcher