From 3a88fe367be852775d82cc573a2e5f9c3464a2db Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Tue, 10 Aug 2004 10:57:54 +0000 Subject: [PATCH] Added a few helper functions for easier usage of strings in resources svn path=/trunk/; revision=10468 --- reactos/include/rosrtl/string.h | 27 +++- reactos/lib/rosrtl/makefile | 5 +- reactos/lib/rosrtl/string/resstr.c | 225 +++++++++++++++++++++++++++++ 3 files changed, 254 insertions(+), 3 deletions(-) create mode 100644 reactos/lib/rosrtl/string/resstr.c diff --git a/reactos/include/rosrtl/string.h b/reactos/include/rosrtl/string.h index 5822658eace..efef777b1aa 100644 --- a/reactos/include/rosrtl/string.h +++ b/reactos/include/rosrtl/string.h @@ -1,4 +1,4 @@ -/* $Id: string.h,v 1.2 2004/02/15 01:08:54 arty Exp $ +/* $Id: string.h,v 1.3 2004/08/10 10:57:54 weiden Exp $ */ #ifndef ROSRTL_STRING_H__ @@ -46,6 +46,31 @@ NTSTATUS NTAPI RosAppendUnicodeString( PUNICODE_STRING ResultFirst, PUNICODE_STRING Second, BOOL Deallocate ); +int +RosLenOfStrResource(HINSTANCE hInst, UINT uID); +int +RosAllocAndLoadStringA(LPSTR *lpTarget, HINSTANCE hInst, UINT uID); +int +RosAllocAndLoadStringW(LPWSTR *lpTarget, HINSTANCE hInst, UINT uID); +DWORD +RosFormatStrA(LPSTR *lpTarget, LPSTR lpFormat, ...); +DWORD +RosFormatStrW(LPWSTR *lpTarget, LPWSTR lpFormat, ...); +DWORD +RosLoadAndFormatStrA(HINSTANCE hInst, UINT uID, LPSTR *lpTarget, ...); +DWORD +RosLoadAndFormatStrW(HINSTANCE hInst, UINT uID, LPWSTR *lpTarget, ...); + +#ifdef UNICODE +# define RosFmtString RosFmtStringW +# define RosAllocAndLoadString RosAllocAndLoadStringW +# define RosLoadAndFormatStr RosLoadAndFormatStrW +#else +# define RosFmtString RosFmtStringA +# define RosAllocAndLoadString RosAllocAndLoadStringA +# define RosLoadAndFormatStr RosLoadAndFormatStrA +#endif + #ifdef __cplusplus } #endif diff --git a/reactos/lib/rosrtl/makefile b/reactos/lib/rosrtl/makefile index 730eaeef134..9db46aeade8 100644 --- a/reactos/lib/rosrtl/makefile +++ b/reactos/lib/rosrtl/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.12 2004/02/15 00:04:07 arty Exp $ +# $Id: makefile,v 1.13 2004/08/10 10:57:54 weiden Exp $ PATH_TO_TOP = ../.. @@ -16,7 +16,8 @@ THREAD_OBJECTS = \ thread/stack.o STRING_OBJECTS = \ - string/append.o + string/append.o \ + string/resstr.o REGISTRY_OBJECTS = \ registry/registry.o diff --git a/reactos/lib/rosrtl/string/resstr.c b/reactos/lib/rosrtl/string/resstr.c new file mode 100644 index 00000000000..24bab660a80 --- /dev/null +++ b/reactos/lib/rosrtl/string/resstr.c @@ -0,0 +1,225 @@ +#define NTOS_MODE_USER +#include + +/* + * Utility to measure the length of a string resource + * + * IN HINSTANCE hInst -> Instance of the module + * IN UINT uID -> ID of the string to measure + * + * Returns the number of characters not including the null-terminator. + * Returns -1 on failure. + */ +int +RosLenOfStrResource(HINSTANCE hInst, UINT uID) +{ + HRSRC hrSrc; + HGLOBAL hRes; + LPWSTR lpName, lpStr; + + if(hInst == NULL) + { + return -1; + } + + /* There are always blocks of 16 strings */ + lpName = (LPWSTR)MAKEINTRESOURCE((uID >> 4) + 1); + + /* Find the string table block */ + if((hrSrc = FindResourceW(hInst, lpName, (LPWSTR)RT_STRING)) && + (hRes = LoadResource(hInst, hrSrc)) && + (lpStr = LockResource(hRes))) + { + UINT x; + + /* Find the string we're looking for */ + uID &= 0xF; /* position in the block, same as % 16 */ + for(x = 0; x < uID; x++) + { + lpStr += (*lpStr) + 1; + } + + /* Found the string */ + return (int)(*lpStr); + } + return -1; +} + +/* + * Utility to allocate and load a string from the string table + * + * OUT LPSTR *lpTarget -> Address to a variable that will get the address to the string allocated + * IN HINSTANCE hInst -> Instance of the module + * IN UINT uID -> ID of the string to measure + * + * Returns the number of characters not including the null-terminator. + * Returns 0 on failure. Use LocalFree() to free the memory allocated. + */ +int +RosAllocAndLoadStringA(LPSTR *lpTarget, HINSTANCE hInst, UINT uID) +{ + int ln; + + ln = RosLenOfStrResource(hInst, uID); + if(ln++ > 0) + { + (*lpTarget) = (LPSTR)LocalAlloc(LHND, ln * sizeof(CHAR)); + if((*lpTarget) != NULL) + { + int Ret; + if(!(Ret = LoadStringA(hInst, uID, *lpTarget, ln))) + { + LocalFree((HLOCAL)(*lpTarget)); + } + return Ret; + } + } + return 0; +} + +/* + * Utility to allocate and load a string from the string table + * + * OUT LPSTR *lpTarget -> Address to a variable that will get the address to the string allocated + * IN HINSTANCE hInst -> Instance of the module + * IN UINT uID -> ID of the string to measure + * + * Returns the number of characters not including the null-terminator. + * Returns 0 on failure. Use LocalFree() to free the memory allocated. + */ +int +RosAllocAndLoadStringW(LPWSTR *lpTarget, HINSTANCE hInst, UINT uID) +{ + int ln; + + ln = RosLenOfStrResource(hInst, uID); + if(ln++ > 0) + { + (*lpTarget) = (LPWSTR)LocalAlloc(LHND, ln * sizeof(WCHAR)); + if((*lpTarget) != NULL) + { + int Ret; + if(!(Ret = LoadStringW(hInst, uID, *lpTarget, ln))) + { + LocalFree((HLOCAL)(*lpTarget)); + } + return Ret; + } + } + return 0; +} + +/* + * Utility to allocate memory and format a string + * + * OUT LPSTR *lpTarget -> Address to a variable that will get the address to the string allocated + * IN LPSTR lpFormat -> String which is to be formatted with the arguments given + * + * Returns the number of characters in lpTarget not including the null-terminator. + * Returns 0 on failure. Use LocalFree() to free the memory allocated. + */ +DWORD +RosFormatStrA(LPSTR *lpTarget, LPSTR lpFormat, ...) +{ + DWORD Ret; + va_list lArgs; + + va_start(lArgs, lpFormat); + /* let's use FormatMessage to format it because it has the ability to allocate + memory automatically */ + Ret = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, + lpFormat, 0, 0, (LPSTR)lpTarget, 0, &lArgs); + va_end(lArgs); + + return Ret; +} + +/* + * Utility to allocate memory and format a string + * + * OUT LPSTR *lpTarget -> Address to a variable that will get the address to the string allocated + * IN LPSTR lpFormat -> String which is to be formatted with the arguments given + * + * Returns the number of characters in lpTarget not including the null-terminator. + * Returns 0 on failure. Use LocalFree() to free the memory allocated. + */ +DWORD +RosFormatStrW(LPWSTR *lpTarget, LPWSTR lpFormat, ...) +{ + DWORD Ret; + va_list lArgs; + + va_start(lArgs, lpFormat); + /* let's use FormatMessage to format it because it has the ability to allocate + memory automatically */ + Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, + lpFormat, 0, 0, (LPWSTR)lpTarget, 0, &lArgs); + va_end(lArgs); + + return Ret; +} + +/* + * Utility to allocate memory, load a string from the resources and format it + * + * IN HINSTANCE hInst -> Instance of the module + * IN UINT uID -> ID of the string to measure + * OUT LPSTR *lpTarget -> Address to a variable that will get the address to the string allocated + * + * Returns the number of characters in lpTarget not including the null-terminator. + * Returns 0 on failure. Use LocalFree() to free the memory allocated. + */ +DWORD +RosLoadAndFormatStrA(HINSTANCE hInst, UINT uID, LPSTR *lpTarget, ...) +{ + DWORD Ret = 0; + LPSTR lpFormat; + va_list lArgs; + + if(RosAllocAndLoadStringA(&lpFormat, hInst, uID) > 0) + { + va_start(lArgs, lpTarget); + /* let's use FormatMessage to format it because it has the ability to allocate + memory automatically */ + Ret = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, + lpFormat, 0, 0, (LPSTR)lpTarget, 0, &lArgs); + va_end(lArgs); + + LocalFree((HLOCAL)lpFormat); + } + + return Ret; +} + +/* + * Utility to allocate memory, load a string from the resources and format it + * + * IN HINSTANCE hInst -> Instance of the module + * IN UINT uID -> ID of the string to measure + * OUT LPSTR *lpTarget -> Address to a variable that will get the address to the string allocated + * + * Returns the number of characters in lpTarget not including the null-terminator. + * Returns 0 on failure. Use LocalFree() to free the memory allocated. + */ +DWORD +RosLoadAndFormatStrW(HINSTANCE hInst, UINT uID, LPWSTR *lpTarget, ...) +{ + DWORD Ret = 0; + LPWSTR lpFormat; + va_list lArgs; + + if(RosAllocAndLoadStringW(&lpFormat, hInst, uID) > 0) + { + va_start(lArgs, lpTarget); + /* let's use FormatMessage to format it because it has the ability to allocate + memory automatically */ + Ret = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, + lpFormat, 0, 0, (LPWSTR)lpTarget, 0, &lArgs); + va_end(lArgs); + + LocalFree((HLOCAL)lpFormat); + } + + return Ret; +} +