>>> 1. please do not leave any unnecessary casting like:
>>>     ( LPCTSTR ) HB_PARSTRDEF( ... )
>>>  such casting does not give anything (it cannot converts strings
>>>  between different formats) but can hide very serious bugs like wrong
>>>  HB_PARSTRDEF() body.
>> I know about this, but if I don't cast, MSVC (C++ mode) gives me errors 
>> on compile. (const WCHAR * cannot be converted to LPCWSTR or something 
>> like it)
> 
> It was enough to tell me about it :)
> Last night I committed modification which should resolve it:
> 
> 2009-12-11 04:13 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
>  * harbour/include/hbapicdp.h
>    * define HB_WCHAR as wchar_t on Windows platforms for compilers which
>      refuse to make conversions between types using the same base type.

I saw it, deleted those casts. For good, because they revealed 
some problems.

>> I didn't reevaluate all of them, although I did serious cleanup 
>> of parcx usage in the past. I was also thinking to fully drop it 
>> for winapi calls, as I'm sure Windows won't BSOD or crash by 
>> passing NULL wherever a pointer is required. That's why I didn't 
>> add yet any special logic to HB_PARSTRDEF() yet. All I wanted 
>> to do is to keep this information for now.
> 
> Windows API is set of functions implemented on different levels
> and some of them can crash so it's necessary to check each of
> them. We cannot make any global assumption about validation of
> NULL pointers. It's even possible that the behavior is different
> in Win9x and WinXP, etc.

That's right. I remember when Mark Russinovich created a little 
tools which made XP (or was it 2000?) BSOD at will, because of 
unchecked parameters. MS fixed these in an SP, but older versions 
I'm not so sure.

>>>  If you will make mechanical translations all hb_parcx() to HB_PARSTRDEF()
>>>  then I will have to also verify HB_PARSTRDEF() calls. So please try
>>>  to already clean it at least for such basic things like:
>>>     if( HB_ISCHAR( 1 ) )
>>>     {
>>>        void * hName;
>>>        xec->hDLL = LoadLibrary( HB_PARSTRDEF( 1, &hName, NULL ) );
>>>        hb_strfree( hName );
>>>     }
>> This was just out of scope of these modification. To be honest 
>> I can't easily see how above could be cleaned. In this case the 
>> winapi docs doesn't mark the parameter as optional, which to me 
>> means that NULL is not an accepted input. (okay it won't crash 
>> if passed, so HB_PARSTRDEF() is almost surely unnecessary)
> 
> In this case I wanted to show that this code checks HB_ISCHAR( 1 )
> so the parameter cannot be NULL and it's not necessary to use
> HB_PARSTRDEF() but we can simply use HB_PARSTR()

Didn't spot it, but you're right.

Anyhow we can make this revision based on PARSTRDEF usage, 
that was my goal.

>>> BTW We can add to strapi.c two very simple functions:
>>>  const char * hb_strnull( const char * str )
>>>  {
>>>     return str ? str : "";
>>>  }
>>>  const HB_WCHAR * hb_strnull_u16( const HB_WCHAR * str )
>>>  {
>>>     return str ? str : s_szConstStr;
>>>  }
>>> which can be used in HB_PARSTRDEF() macro.
>> Yes, this would be the perfect solution. Anyhow I didn't 
>> bother to add default value to HB_PARSTRDEF() yet, as 
>> in 99% of cases the default is empty string, only one 
>> was passed some other value, but it's not a requirement 
>> for WAPI_*() functions to give such extra features so 
>> it wasn't crucial.
> 
> I think that it's necessary in code like:
>   hb_retnint( ( HB_PTRDIFF ) LoadLibrary( HB_PARSTRDEF( 1, &hName, NULL ) ) );
> or at least this code should be fixed.

If not protected with HB_ISCHAR() it sure has to be.

>> If we're at this topic, I've found a few places which 
>> couldn't be covered by these macros, It'd be very nice 
>> if you could take a look at them and suggest the 
>> cleanest way to resolve them. F.e. there are cases 
>> when retrieved parameter is assigned to win structure, 
> 
> I do not see the problem, Can you show me the exact code place
> where it was problematic?

Here's a list of remaining HB_TCHAR* occurrences in hbwin:
---
wapi_commctrl.c:480:   LPTSTR szText = HB_TCHAR_CONVTO( hb_parcx( 3 ) );
wapi_commctrl.c:488:   HB_TCHAR_FREE( szText );
wapi_commctrl.c:563:   LPTSTR szText = HB_TCHAR_CONVTO( hb_parcx( 3 ) );
wapi_commctrl.c:571:   HB_TCHAR_FREE( szText );
wapi_commctrl.c:783:   LPTSTR  szText = HB_TCHAR_CONVTO( hb_parcx( 2 ) );
wapi_commctrl.c:791:   HB_TCHAR_FREE( szText );
wce_simc.c:99:   szAddress = HB_TCHAR_CONVFROM( PhoneEntry.lpszAddress );
wce_simc.c:100:   szText = HB_TCHAR_CONVFROM( PhoneEntry.lpszText );
wce_simc.c:113:   HB_TCHAR_FREE( szAddress );
wce_simc.c:114:   HB_TCHAR_FREE( szText );
wce_simc.c:120:   wchar_t * lpwszAddress = HB_TCHAR_CONVTO( hb_parcx( 4 ) );
wce_simc.c:121:   wchar_t * lpwszText = HB_TCHAR_CONVTO( hb_parcx( 5 ) );
wce_simc.c:132:   HB_TCHAR_FREE( lpwszAddress );
wce_simc.c:133:   HB_TCHAR_FREE( lpwszText );
wce_smsc.c:72:      wchar_t * sztMessage     = HB_TCHAR_CONVTO( hb_parcx( 1 ) );
wce_smsc.c:73:      wchar_t * sztPhoneNumber = HB_TCHAR_CONVTO( hb_parcx( 2 ) );
wce_smsc.c:102:      HB_TCHAR_FREE( sztMessage );
wce_smsc.c:103:      HB_TCHAR_FREE( sztPhoneNumber );
win_com.c:92:      HB_TCHAR_CPTO( tszName, szName, sizeof( tszName ) - 1 );
win_misc.c:166:   char * buffer = HB_TCHAR_CONVFROM( GetCommandLine() );
win_misc.c:204:   HB_TCHAR_FREE( buffer );
win_osc.c:195:   szCSDVersion = HB_TCHAR_CONVFROM( osvi.szCSDVersion );
win_osc.c:197:   HB_TCHAR_FREE( szCSDVersion );
win_prn1.c:189:      LPTSTR lpDocName = szDocName ? HB_TCHAR_CONVTO( szDocName 
) : NULL;
win_prn1.c:198:         HB_TCHAR_FREE( lpDocName );
win_prn1.c:267:         LPTSTR lpData = HB_TCHAR_CONVNTO( hb_parc( 4 ), iLen );
win_prn1.c:294:         HB_TCHAR_FREE( lpData );
win_prn1.c:316:      lpData = HB_TCHAR_CONVNTO( hb_parc( 2 ), iLen );
win_prn1.c:325:      HB_TCHAR_FREE( lpData );
win_prn1.c:377:      LPTSTR lpFont = pszFont ? HB_TCHAR_CONVTO( pszFont ) : 
NULL;
win_prn1.c:410:         HB_TCHAR_FREE( lpFont );
win_prn1.c:448:      LPTSTR lpPrinterName = pszPrinterName ? HB_TCHAR_CONVTO( 
pszPrinterName ) : NULL;
win_prn1.c:487:         HB_TCHAR_FREE( lpPrinterName );
win_prn1.c:498:   LPTSTR lpPrinterName = pszPrinterName ? HB_TCHAR_CONVTO( 
pszPrinterName ) : NULL;
win_prn1.c:525:      HB_TCHAR_FREE( lpPrinterName );
win_prn1.c:598:   char * pszFaceName = HB_TCHAR_CONVFROM( lplf->lfFaceName );
win_prn1.c:608:   HB_TCHAR_FREE( pszFaceName );
win_prn2.c:113:                  char * pszData = HB_TCHAR_CONVFROM( 
pPrinterEnum->pPrinterName );
win_prn2.c:115:                  HB_TCHAR_FREE( pszData );
win_prn2.c:160:               HB_TCHAR_GETFROM( pszPrinterName, lpPrinterName, 
*pnBufferSize );
win_prn2.c:175:         HB_TCHAR_GETFROM( pszPrinterName, lpPrinterName, 
*pnBufferSize );
win_prn2.c:222:                     HB_TCHAR_GETFROM( pszPrinterName, 
pPrinterInfo->pPrinterName, lstrlen( pPrinterInfo->pPrinterName ) );
win_prn2.c:298:      LPTSTR lpPrinterName = HB_TCHAR_CONVTO( pszPrinterName );
win_prn2.c:344:      HB_TCHAR_FREE( lpPrinterName );
win_prn2.c:375:               char * pszPortName = HB_TCHAR_CONVFROM( 
pPrinterEnum->pPortName );
win_prn2.c:382:               HB_TCHAR_FREE( pszPortName );
win_prn2.c:386:                  char * pszPrinterName = HB_TCHAR_CONVFROM( 
pPrinterEnum->pPrinterName );
win_prn2.c:388:                  HB_TCHAR_FREE( pszPrinterName );
win_prn2.c:409:      LPTSTR lpPrinterName = HB_TCHAR_CONVTO( pszPrinterName );
win_prn2.c:413:         LPTSTR lpDocName = HB_TCHAR_CONVTO( pszDocName );
win_prn2.c:457:         HB_TCHAR_FREE( lpDocName );
win_prn2.c:463:      HB_TCHAR_FREE( lpPrinterName );
win_prn2.c:504:                  pszData = HB_TCHAR_CONVFROM( 
pPrinterEnum->pPrinterName );
win_prn2.c:506:                  HB_TCHAR_FREE( pszData );
win_prn2.c:520:                        pszData = HB_TCHAR_CONVFROM( 
pPrinterEnum->pPrinterName );
win_prn2.c:522:                        HB_TCHAR_FREE( pszData );
win_prn2.c:529:                              pszData = HB_TCHAR_CONVFROM( 
pPrinterInfo2->pPortName );
win_prn2.c:531:                              HB_TCHAR_FREE( pszData );
win_prn2.c:532:                              pszData = HB_TCHAR_CONVFROM( 
pPrinterInfo2->pDriverName );
win_prn2.c:534:                              HB_TCHAR_FREE( pszData );
win_prn2.c:535:                              pszData = HB_TCHAR_CONVFROM( 
pPrinterInfo2->pShareName );
win_prn2.c:537:                              HB_TCHAR_FREE( pszData );
win_prn2.c:538:                              pszData = HB_TCHAR_CONVFROM( 
pPrinterInfo2->pServerName );
win_prn2.c:540:                              HB_TCHAR_FREE( pszData );
win_regc.c:122:   LPTSTR lpKey = HB_TCHAR_CONVTO( hb_parcx( 2 ) );
win_regc.c:180:   HB_TCHAR_FREE( lpKey );
---

All of them were problematic (to me) for some reason (except WIN_CREATEFONT(), 
which I'll commit ASAP.)

>> there are cases when win return value is returned 
>> in array elements (win_prn),
> 
> We can add hb_array[SG]etStr*() functions.
> You can also use hb_arrayGetItemPtr() and hb_itemPutStrLen*()
> but I do not like when users use hb_arrayGetItemPtr() function
> so in such case try to at least hide it by macros, i.e.:
> 
>   #if defined( UNICODE )
>      #define HB_ARRAYSETSTR( arr, n, str ) \
>         hb_itemPutStrLenU16( hb_arrayGetItemPtr( arr, n ), \
>                              HB_CDP_ENDIAN_NATIVE, str, lstrlenW( str ) )
>      #define HB_ARRAYSETSTRLEN( arr, n, str, len ) \
>         hb_itemPutStrLenU16( hb_arrayGetItemPtr( arr, n ), \
>                              HB_CDP_ENDIAN_NATIVE, str, len )
>   #else
>      #define HB_ARRAYSETSTR( arr, n, str ) \
>         hb_itemPutStrLen( hb_arrayGetItemPtr( arr, n ), \
>                           hb_setGetOSCP(), str, strlen( str ) )
>      #define HB_ARRAYSETSTRLEN( arr, n, str, len ) \
>         hb_itemPutStrLen( hb_arrayGetItemPtr( arr, n ), \
>                           hb_setGetOSCP(), str, len )
>   #endif
> 
> Please only note that unlike hb_arraySetC[L]() these macros do not
> check array size and cannot be safely used with wrong indexes and
> HB_ARRAYSETSTRLEN() uses str twice so you should avoid using complex
> expressions passing it. It's a problem until we won't have added
> hb_arraySetStr*() functions. When we do that then we simply modify
> above macros to use new functions.

Thanks, I'll add them as a start. This clears up some of 
my above listed "problematic" cases.

>> there is one case which needs to 
>> use the retrieved parameter in two places (win_reg), 
> 
> I do not see nay problem in win_regc.c but maybe I'm missing sth.
> Now HB_TCHAR_*() macros are use only in one function:
>   HB_FUNC( WIN_REGQUERYVALUEEX )
>   {
>      LPTSTR lpKey = HB_TCHAR_CONVTO( hb_parcx( 2 ) );
>      [...]
>      HB_TCHAR_FREE( lpKey );
>   }
> 
> and should be simply replaced with:
>   HB_FUNC( WIN_REGQUERYVALUEEX )
>   {
>      void * hKey;
>      LPCTSTR lpKey = HB_PARSTRDEF( 2, &hKey, NULL );
>      [...]
>      hb_strfree( hKey );
>   }
> 
> or better by:
>   HB_FUNC( WIN_REGQUERYVALUEEX )
>   {
>      void * hKey;
>      LPCTSTR lpKey = HB_PARSTR( 2, &hKey, NULL );
>      [...]
>      if( lpKey && RegQueryValueEx( ( HKEY ) hb_parptr( 1 ),
>      [...]
>      hb_strfree( hKey );
>   }

That's fine, thanks.

>> and some more. Probably some additional macros are 
>> needed?
> 
> Probably yes but without exact real life examples it's hard for me
> to guess which ones.

I'll try to modify everything which I can, and pls 
check remaining ones.

Brgds,
Viktor

_______________________________________________
Harbour mailing list (attachment size limit: 40KB)
[email protected]
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to