From 8196e2d0d0dbd04325201e14d95f88cad3cfd00f Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Wed, 21 Sep 2005 14:12:15 +0000 Subject: [PATCH] Implement setupapi stringtable functions. --- dlls/setupapi/Makefile.in | 3 + dlls/setupapi/setupapi.spec | 36 +- dlls/setupapi/stringtable.c | 709 ++++++++++++++++++++++++++++++++++++ include/setupapi.h | 13 + 4 files changed, 749 insertions(+), 12 deletions(-) create mode 100644 dlls/setupapi/stringtable.c diff --git a/dlls/setupapi/Makefile.in b/dlls/setupapi/Makefile.in index 676c3ce9a8c..fb36bd1f513 100644 --- a/dlls/setupapi/Makefile.in +++ b/dlls/setupapi/Makefile.in @@ -18,6 +18,7 @@ C_SRCS = \ parser.c \ queue.c \ setupcab.c \ + stringtable.c \ stubs.c C_SRCS16 = \ @@ -30,6 +31,8 @@ SPEC_SRCS16 = setupx.spec RC_SRCS= setupapi.rc +SUBDIRS = tests + @MAKE_DLL_RULES@ ### Dependencies: diff --git a/dlls/setupapi/setupapi.spec b/dlls/setupapi/setupapi.spec index 9709aff4911..8ccbafbee9d 100644 --- a/dlls/setupapi/setupapi.spec +++ b/dlls/setupapi/setupapi.spec @@ -513,19 +513,20 @@ @ stdcall SetupTerminateFileLog(long) @ stub ShouldDeviceBeExcluded @ stdcall StampFileSecurity(wstr ptr) -@ stub StringTableAddString -@ stub StringTableAddStringEx -@ stub StringTableDestroy -@ stub StringTableDuplicate +@ stdcall StringTableAddString(ptr wstr long) +@ stdcall StringTableAddStringEx(ptr wstr long ptr long) +@ stdcall StringTableDestroy(ptr) +@ stdcall StringTableDuplicate(ptr) @ stub StringTableEnum -@ stub StringTableGetExtraData -@ stub StringTableInitialize -@ stub StringTableInitializeEx -@ stub StringTableLookUpString -@ stub StringTableLookUpStringEx -@ stub StringTableSetExtraData -@ stub StringTableStringFromId -@ stub StringTableTrim +@ stdcall StringTableGetExtraData(ptr long ptr long) +@ stdcall StringTableInitialize() +@ stdcall StringTableInitializeEx(long long) +@ stdcall StringTableLookUpString(ptr wstr long) +@ stdcall StringTableLookUpStringEx(ptr wstr long ptr ptr) +@ stdcall StringTableSetExtraData(ptr long ptr long) +@ stdcall StringTableStringFromId(ptr long) +@ stdcall StringTableStringFromIdEx(ptr long ptr ptr) +@ stdcall StringTableTrim(ptr) @ stdcall TakeOwnershipOfFile(wstr) @ stdcall UnicodeToMultiByte(wstr long) @ stdcall UnmapAndCloseFile(long long ptr) @@ -549,4 +550,15 @@ @ stub pSetupSetQueueFlags @ stub pSetupSetSystemSourceFlags @ stub pSetupStringFromGuid +@ stdcall pSetupStringTableAddString(ptr wstr long) StringTableAddString +@ stdcall pSetupStringTableAddStringEx(ptr wstr long ptr long) StringTableAddStringEx +@ stdcall pSetupStringTableDestroy(ptr) StringTableDestroy +@ stdcall pSetupStringTableDuplicate(ptr) StringTableDuplicate +@ stub pSetupStringTableEnum +@ stdcall pSetupStringTableGetExtraData(ptr long ptr long) StringTableGetExtraData +@ stdcall pSetupStringTableInitialize() StringTableInitialize +@ stdcall pSetupStringTableInitializeEx(long long) StringTableInitializeEx +@ stdcall pSetupStringTableLookUpString(ptr wstr long) StringTableLookUpString +@ stdcall pSetupStringTableLookUpStringEx(ptr wstr long ptr ptr) StringTableLookUpStringEx +@ stdcall pSetupStringTableSetExtraData(ptr long ptr long) StringTableSetExtraData @ stub pSetupVerifyQueuedCatalogs diff --git a/dlls/setupapi/stringtable.c b/dlls/setupapi/stringtable.c new file mode 100644 index 00000000000..1f463ab82c0 --- /dev/null +++ b/dlls/setupapi/stringtable.c @@ -0,0 +1,709 @@ +/* + * Setupapi string table functions + * + * Copyright 2005 Eric Kohl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winreg.h" +#include "setupapi.h" + +#include "wine/debug.h" + + +#define TABLE_DEFAULT_SIZE 256 + +WINE_DEFAULT_DEBUG_CHANNEL(setupapi); + +typedef struct _TABLE_SLOT +{ + LPWSTR pString; + LPVOID pData; + DWORD dwSize; +} TABLE_SLOT, *PTABLE_SLOT; + +typedef struct _STRING_TABLE +{ + PTABLE_SLOT pSlots; + DWORD dwUsedSlots; + DWORD dwMaxSlots; + DWORD dwMaxDataSize; +} STRING_TABLE, *PSTRING_TABLE; + + +/************************************************************************** + * StringTableInitialize [SETUPAPI.@] + * + * Creates a new string table and initializes it. + * + * PARAMS + * None + * + * RETURNS + * Success: Handle to the string table + * Failure: NULL + */ +HSTRING_TABLE WINAPI +StringTableInitialize(VOID) +{ + PSTRING_TABLE pStringTable; + + TRACE("\n"); + + pStringTable = MyMalloc(sizeof(STRING_TABLE)); + if (pStringTable == NULL) + { + ERR("Invalid hStringTable!\n"); + return NULL; + } + + memset(pStringTable, 0, sizeof(STRING_TABLE)); + + pStringTable->pSlots = MyMalloc(sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE); + if (pStringTable->pSlots == NULL) + { + MyFree(pStringTable->pSlots); + return NULL; + } + + memset(pStringTable->pSlots, 0, sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE); + + pStringTable->dwUsedSlots = 0; + pStringTable->dwMaxSlots = TABLE_DEFAULT_SIZE; + pStringTable->dwMaxDataSize = 0; + + TRACE("Done\n"); + + return (HSTRING_TABLE)pStringTable; +} + + +/************************************************************************** + * StringTableInitializeEx [SETUPAPI.@] + * + * Creates a new string table and initializes it. + * + * PARAMS + * dwMaxExtraDataSize [I] Maximum extra data size + * dwReserved [I] Unused + * + * RETURNS + * Success: Handle to the string table + * Failure: NULL + */ +HSTRING_TABLE WINAPI +StringTableInitializeEx(DWORD dwMaxExtraDataSize, + DWORD dwReserved) +{ + PSTRING_TABLE pStringTable; + + TRACE("\n"); + + pStringTable = MyMalloc(sizeof(STRING_TABLE)); + if (pStringTable == NULL) return NULL; + + memset(pStringTable, 0, sizeof(STRING_TABLE)); + + pStringTable->pSlots = MyMalloc(sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE); + if (pStringTable->pSlots == NULL) + { + MyFree(pStringTable->pSlots); + return NULL; + } + + memset(pStringTable->pSlots, 0, sizeof(TABLE_SLOT) * TABLE_DEFAULT_SIZE); + + pStringTable->dwUsedSlots = 0; + pStringTable->dwMaxSlots = TABLE_DEFAULT_SIZE; + pStringTable->dwMaxDataSize = dwMaxExtraDataSize; + + TRACE("Done\n"); + + return (HSTRING_TABLE)pStringTable; +} + + +/************************************************************************** + * StringTableDestroy [SETUPAPI.@] + * + * Destroys a string table. + * + * PARAMS + * hStringTable [I] Handle to the string table to be destroyed + * + * RETURNS + * None + */ +VOID WINAPI +StringTableDestroy(HSTRING_TABLE hStringTable) +{ + PSTRING_TABLE pStringTable; + DWORD i; + + TRACE("%p\n", hStringTable); + + pStringTable = (PSTRING_TABLE)hStringTable; + if (pStringTable == NULL) + return; + + if (pStringTable->pSlots != NULL) + { + for (i = 0; i < pStringTable->dwMaxSlots; i++) + { + if (pStringTable->pSlots[i].pString != NULL) + { + MyFree(pStringTable->pSlots[i].pString); + pStringTable->pSlots[i].pString = NULL; + } + + if (pStringTable->pSlots[i].pData != NULL) + { + MyFree(pStringTable->pSlots[i].pData); + pStringTable->pSlots[i].pData = NULL; + pStringTable->pSlots[i].dwSize = 0; + } + } + + MyFree(pStringTable->pSlots); + } + + MyFree(pStringTable); +} + + +/************************************************************************** + * StringTableAddString [SETUPAPI.@] + * + * Adds a new string to the string table. + * + * PARAMS + * hStringTable [I] Handle to the string table + * lpString [I] String to be added to the string table + * dwFlags [I] Flags + * 1: case sensitive compare + * + * RETURNS + * Success: String ID + * Failure: -1 + * + * NOTES + * If the given string already exists in the string table it will not + * be added again. The ID of the existing string will be returned in + * this case. + */ +DWORD WINAPI +StringTableAddString(HSTRING_TABLE hStringTable, + LPWSTR lpString, + DWORD dwFlags) +{ + PSTRING_TABLE pStringTable; + DWORD i; + + TRACE("%p %s %lx\n", hStringTable, debugstr_w(lpString), dwFlags); + + pStringTable = (PSTRING_TABLE)hStringTable; + if (pStringTable == NULL) + { + ERR("Invalid hStringTable!\n"); + return (DWORD)-1; + } + + /* Search for existing string in the string table */ + for (i = 0; i < pStringTable->dwMaxSlots; i++) + { + if (pStringTable->pSlots[i].pString != NULL) + { + if (dwFlags & 1) + { + if (!lstrcmpW(pStringTable->pSlots[i].pString, lpString)) + { + return i; + } + } + else + { + if (!lstrcmpiW(pStringTable->pSlots[i].pString, lpString)) + { + return i; + } + } + } + } + + /* Check for filled slot table */ + if (pStringTable->dwUsedSlots == pStringTable->dwMaxSlots) + { + FIXME("Resize the string table!\n"); + return (DWORD)-1; + } + + /* Search for an empty slot */ + for (i = 0; i < pStringTable->dwMaxSlots; i++) + { + if (pStringTable->pSlots[i].pString == NULL) + { + pStringTable->pSlots[i].pString = MyMalloc((lstrlenW(lpString) + 1) * sizeof(WCHAR)); + if (pStringTable->pSlots[i].pString == NULL) + { + TRACE("Couldn't allocate memory for a new string!\n"); + return (DWORD)-1; + } + + lstrcpyW(pStringTable->pSlots[i].pString, lpString); + + pStringTable->dwUsedSlots++; + + return i; + } + } + + TRACE("Couldn't find an empty slot!\n"); + + return (DWORD)-1; +} + + +/************************************************************************** + * StringTableAddStringEx [SETUPAPI.@] + * + * Adds a new string plus extra data to the string table. + * + * PARAMS + * hStringTable [I] Handle to the string table + * lpString [I] String to be added to the string table + * dwFlags [I] Flags + * 1: case sensitive compare + * lpExtraData [I] Pointer to the extra data + * dwExtraDataSize [I] Size of the extra data + * + * RETURNS + * Success: String ID + * Failure: -1 + * + * NOTES + * If the given string already exists in the string table it will not + * be added again. The ID of the existing string will be returned in + * this case. + */ +DWORD WINAPI +StringTableAddStringEx(HSTRING_TABLE hStringTable, + LPWSTR lpString, + DWORD dwFlags, + LPVOID lpExtraData, + DWORD dwExtraDataSize) +{ + FIXME("\n"); + return (DWORD)-1; +} + + +/************************************************************************** + * StringTableDuplicate [SETUPAPI.@] + * + * Duplicates a given string table. + * + * PARAMS + * hStringTable [I] Handle to the string table + * + * RETURNS + * Success: Handle to the duplicated string table + * Failure: NULL + * + */ +HSTRING_TABLE WINAPI +StringTableDuplicate(HSTRING_TABLE hStringTable) +{ + PSTRING_TABLE pSourceTable; + PSTRING_TABLE pDestinationTable; + DWORD i; + DWORD length; + + TRACE("%p\n", hStringTable); + + pSourceTable = (PSTRING_TABLE)hStringTable; + if (pSourceTable == NULL) + { + ERR("Invalid hStringTable!\n"); + return (HSTRING_TABLE)NULL; + } + + pDestinationTable = MyMalloc(sizeof(STRING_TABLE)); + if (pDestinationTable == NULL) + { + ERR("Cound not allocate a new string table!\n"); + return (HSTRING_TABLE)NULL; + } + + memset(pDestinationTable, 0, sizeof(STRING_TABLE)); + + pDestinationTable->pSlots = MyMalloc(sizeof(TABLE_SLOT) * pSourceTable->dwMaxSlots); + if (pDestinationTable->pSlots == NULL) + { + MyFree(pDestinationTable); + return (HSTRING_TABLE)NULL; + } + + memset(pDestinationTable->pSlots, 0, sizeof(TABLE_SLOT) * pSourceTable->dwMaxSlots); + + pDestinationTable->dwUsedSlots = 0; + pDestinationTable->dwMaxSlots = pSourceTable->dwMaxSlots; + + for (i = 0; i < pSourceTable->dwMaxSlots; i++) + { + if (pSourceTable->pSlots[i].pString != NULL) + { + length = (lstrlenW(pSourceTable->pSlots[i].pString) + 1) * sizeof(WCHAR); + pDestinationTable->pSlots[i].pString = MyMalloc(length); + if (pDestinationTable->pSlots[i].pString != NULL) + { + memcpy(pDestinationTable->pSlots[i].pString, + pSourceTable->pSlots[i].pString, + length); + pDestinationTable->dwUsedSlots++; + } + + if (pSourceTable->pSlots[i].pData != NULL) + { + length = pSourceTable->pSlots[i].dwSize; + pDestinationTable->pSlots[i].pData = MyMalloc(length); + if (pDestinationTable->pSlots[i].pData) + { + memcpy(pDestinationTable->pSlots[i].pData, + pSourceTable->pSlots[i].pData, + length); + pDestinationTable->pSlots[i].dwSize = length; + } + } + } + } + + return (HSTRING_TABLE)pDestinationTable; +} + + +/************************************************************************** + * StringTableGetExtraData [SETUPAPI.@] + * + * Retrieves extra data from a given string table entry. + * + * PARAMS + * hStringTable [I] Handle to the string table + * dwId [I] String ID + * lpExtraData [I] Pointer a buffer that receives the extra data + * dwExtraDataSize [I] Size of the buffer + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI +StringTableGetExtraData(HSTRING_TABLE hStringTable, + DWORD dwId, + LPVOID lpExtraData, + DWORD dwExtraDataSize) +{ + PSTRING_TABLE pStringTable; + + TRACE("%p %lx %p %lu\n", + hStringTable, dwId, lpExtraData, dwExtraDataSize); + + pStringTable = (PSTRING_TABLE)hStringTable; + if (pStringTable == NULL) + { + ERR("Invalid hStringTable!\n"); + return FALSE; + } + + if (dwId >= pStringTable->dwMaxSlots) + { + ERR("Invalid Slot id!\n"); + return FALSE; + } + + if (pStringTable->pSlots[dwId].dwSize < dwExtraDataSize) + { + ERR("Data size is too large!\n"); + return FALSE; + } + + memcpy(lpExtraData, + pStringTable->pSlots[dwId].pData, + dwExtraDataSize); + + return TRUE; +} + + +/************************************************************************** + * StringTableLookUpString [SETUPAPI.@] + * + * Searches a string table for a given string. + * + * PARAMS + * hStringTable [I] Handle to the string table + * lpString [I] String to be searched for + * dwFlags [I] Flags + * 1: case sensitive compare + * + * RETURNS + * Success: String ID + * Failure: -1 + */ +DWORD WINAPI +StringTableLookUpString(HSTRING_TABLE hStringTable, + LPWSTR lpString, + DWORD dwFlags) +{ + PSTRING_TABLE pStringTable; + DWORD i; + + TRACE("%p %s %lx\n", hStringTable, debugstr_w(lpString), dwFlags); + + pStringTable = (PSTRING_TABLE)hStringTable; + if (pStringTable == NULL) + { + ERR("Invalid hStringTable!\n"); + return (DWORD)-1; + } + + /* Search for existing string in the string table */ + for (i = 0; i < pStringTable->dwMaxSlots; i++) + { + if (pStringTable->pSlots[i].pString != NULL) + { + if (dwFlags & 1) + { + if (!lstrcmpW(pStringTable->pSlots[i].pString, lpString)) + return i; + } + else + { + if (!lstrcmpiW(pStringTable->pSlots[i].pString, lpString)) + return i; + } + } + } + + return (DWORD)-1; +} + + +/************************************************************************** + * StringTableLookUpStringEx [SETUPAPI.@] + * + * Searches a string table and extra data for a given string. + * + * PARAMS + * hStringTable [I] Handle to the string table + * lpString [I] String to be searched for + * dwFlags [I] Flags + * 1: case sensitive compare + * lpExtraData [O] Pointer to the buffer that receives the extra data + * lpReserved [I/O] Unused + * + * RETURNS + * Success: String ID + * Failure: -1 + */ +DWORD WINAPI +StringTableLookUpStringEx(HSTRING_TABLE hStringTable, + LPWSTR lpString, + DWORD dwFlags, + LPVOID lpExtraData, + LPDWORD lpReserved) +{ + FIXME("\n"); + return (DWORD)-1; +} + + +/************************************************************************** + * StringTableSetExtraData [SETUPAPI.@] + * + * Sets extra data for a given string table entry. + * + * PARAMS + * hStringTable [I] Handle to the string table + * dwId [I] String ID + * lpExtraData [I] Pointer to the extra data + * dwExtraDataSize [I] Size of the extra data + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI +StringTableSetExtraData(HSTRING_TABLE hStringTable, + DWORD dwId, + LPVOID lpExtraData, + DWORD dwExtraDataSize) +{ + PSTRING_TABLE pStringTable; + + TRACE("%p %lx %p %lu\n", + hStringTable, dwId, lpExtraData, dwExtraDataSize); + + pStringTable = (PSTRING_TABLE)hStringTable; + if (pStringTable == NULL) + { + ERR("Invalid hStringTable!\n"); + return FALSE; + } + + if (dwId >= pStringTable->dwMaxSlots) + { + ERR("Invalid Slot id!\n"); + return FALSE; + } + + if (pStringTable->dwMaxDataSize < dwExtraDataSize) + { + ERR("Data size is too large!\n"); + return FALSE; + } + + pStringTable->pSlots[dwId].pData = MyMalloc(dwExtraDataSize); + if (pStringTable->pSlots[dwId].pData == NULL) + { + ERR("\n"); + return FALSE; + } + + memcpy(pStringTable->pSlots[dwId].pData, + lpExtraData, + dwExtraDataSize); + pStringTable->pSlots[dwId].dwSize = dwExtraDataSize; + + return TRUE; +} + + +/************************************************************************** + * StringTableStringFromId [SETUPAPI.@] + * + * Returns a pointer to a string for the given string ID. + * + * PARAMS + * hStringTable [I] Handle to the string table. + * dwId [I] String ID + * + * RETURNS + * Success: Pointer to the string + * Failure: NULL + */ +LPWSTR WINAPI +StringTableStringFromId(HSTRING_TABLE hStringTable, + DWORD dwId) +{ + PSTRING_TABLE pStringTable; + + TRACE("%p %lx\n", hStringTable, dwId); + + pStringTable = (PSTRING_TABLE)hStringTable; + if (pStringTable == NULL) + { + ERR("Invalid hStringTable!\n"); + return NULL; + } + + if (dwId >= pStringTable->dwMaxSlots) + return NULL; + + return pStringTable->pSlots[dwId].pString; +} + + +/************************************************************************** + * StringTableStringFromIdEx [SETUPAPI.@] + * + * Returns a string for the given string ID. + * + * PARAMS + * hStringTable [I] Handle to the string table + * dwId [I] String ID + * lpBuffer [I] Pointer to string buffer + * lpBufferSize [I/O] Pointer to the size of the string buffer + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI +StringTableStringFromIdEx(HSTRING_TABLE hStringTable, + DWORD dwId, + LPWSTR lpBuffer, + LPDWORD lpBufferLength) +{ + PSTRING_TABLE pStringTable; + DWORD dwLength; + BOOL bResult = FALSE; + + TRACE("%p %lx %p %p\n", hStringTable, dwId, lpBuffer, lpBufferLength); + + pStringTable = (PSTRING_TABLE)hStringTable; + if (pStringTable == NULL) + { + ERR("Invalid hStringTable!\n"); + *lpBufferLength = 0; + return FALSE; + } + + if (dwId >= pStringTable->dwMaxSlots || + pStringTable->pSlots[dwId].pString == NULL) + { + WARN("Invalid string ID!\n"); + *lpBufferLength = 0; + return FALSE; + } + + dwLength = (lstrlenW(pStringTable->pSlots[dwId].pString) + 1) * sizeof(WCHAR); + if (dwLength <= *lpBufferLength) + { + lstrcpyW(lpBuffer, pStringTable->pSlots[dwId].pString); + bResult = TRUE; + } + + *lpBufferLength = dwLength; + + return bResult; +} + + +/************************************************************************** + * StringTableTrim [SETUPAPI.@] + * + * ... + * + * PARAMS + * hStringTable [I] Handle to the string table + * + * RETURNS + * None + */ +VOID WINAPI +StringTableTrim(HSTRING_TABLE hStringTable) +{ + FIXME("%p\n", hStringTable); +} diff --git a/include/setupapi.h b/include/setupapi.h index 1cf61f948f8..adbdfdfbdd5 100644 --- a/include/setupapi.h +++ b/include/setupapi.h @@ -158,6 +158,8 @@ DECL_WINELIB_SETUPAPI_TYPE_AW(PSP_FILE_CALLBACK) typedef UINT DI_FUNCTION; +DECLARE_HANDLE(HSTRING_TABLE); + typedef struct _SP_CLASSINSTALL_HEADER { DWORD cbSize; @@ -415,6 +417,9 @@ DECL_WINELIB_SETUPAPI_TYPE_AW(PFILEPATHS) #define SP_COPY_NOPRUNE 0x00100000 #define SP_COPY_OEM_F6_INF 0x00200000 +/* Flags for StringTableAddString and StringTableLookUpString */ +#define ST_CASE_SENSITIVE_COMPARE 0x00000001 + #define FLG_ADDREG_DELREG_BIT 0x00008000 #define FLG_ADDREG_BINVALUETYPE 0x00000001 #define FLG_ADDREG_NOCLOBBER 0x00000002 @@ -858,6 +863,14 @@ BOOL WINAPI SetupSetFileQueueAlternatePlatformW( HSPFILEQ, PSP_ALTPLATFORM_I BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ, DWORD, DWORD ); void WINAPI SetupTermDefaultQueueCallback( PVOID ); DWORD WINAPI StampFileSecurity(PCWSTR, PSECURITY_DESCRIPTOR); +DWORD WINAPI StringTableAddString(HSTRING_TABLE, LPWSTR, DWORD); +VOID WINAPI StringTableDestroy(HSTRING_TABLE); +HSTRING_TABLE WINAPI StringTableDuplicate(HSTRING_TABLE hStringTable); +HSTRING_TABLE WINAPI StringTableInitialize(VOID); +DWORD WINAPI StringTableLookUpString(HSTRING_TABLE, LPWSTR, DWORD); +LPWSTR WINAPI StringTableStringFromId(HSTRING_TABLE, DWORD); +BOOL WINAPI StringTableStringFromIdEx(HSTRING_TABLE, DWORD, LPWSTR, LPDWORD); +VOID WINAPI StringTableTrim(HSTRING_TABLE); DWORD WINAPI TakeOwnershipOfFile(PCWSTR); PSTR WINAPI UnicodeToMultiByte(PCWSTR lpUnicodeStr, UINT uCodePage); BOOL WINAPI UnmapAndCloseFile(HANDLE, HANDLE, PVOID);