Implement setupapi stringtable functions.

This commit is contained in:
Eric Kohl 2005-09-21 14:12:15 +00:00 committed by Alexandre Julliard
parent 2aae74dff0
commit 8196e2d0d0
4 changed files with 749 additions and 12 deletions

View File

@ -18,6 +18,7 @@ C_SRCS = \
parser.c \ parser.c \
queue.c \ queue.c \
setupcab.c \ setupcab.c \
stringtable.c \
stubs.c stubs.c
C_SRCS16 = \ C_SRCS16 = \
@ -30,6 +31,8 @@ SPEC_SRCS16 = setupx.spec
RC_SRCS= setupapi.rc RC_SRCS= setupapi.rc
SUBDIRS = tests
@MAKE_DLL_RULES@ @MAKE_DLL_RULES@
### Dependencies: ### Dependencies:

View File

@ -513,19 +513,20 @@
@ stdcall SetupTerminateFileLog(long) @ stdcall SetupTerminateFileLog(long)
@ stub ShouldDeviceBeExcluded @ stub ShouldDeviceBeExcluded
@ stdcall StampFileSecurity(wstr ptr) @ stdcall StampFileSecurity(wstr ptr)
@ stub StringTableAddString @ stdcall StringTableAddString(ptr wstr long)
@ stub StringTableAddStringEx @ stdcall StringTableAddStringEx(ptr wstr long ptr long)
@ stub StringTableDestroy @ stdcall StringTableDestroy(ptr)
@ stub StringTableDuplicate @ stdcall StringTableDuplicate(ptr)
@ stub StringTableEnum @ stub StringTableEnum
@ stub StringTableGetExtraData @ stdcall StringTableGetExtraData(ptr long ptr long)
@ stub StringTableInitialize @ stdcall StringTableInitialize()
@ stub StringTableInitializeEx @ stdcall StringTableInitializeEx(long long)
@ stub StringTableLookUpString @ stdcall StringTableLookUpString(ptr wstr long)
@ stub StringTableLookUpStringEx @ stdcall StringTableLookUpStringEx(ptr wstr long ptr ptr)
@ stub StringTableSetExtraData @ stdcall StringTableSetExtraData(ptr long ptr long)
@ stub StringTableStringFromId @ stdcall StringTableStringFromId(ptr long)
@ stub StringTableTrim @ stdcall StringTableStringFromIdEx(ptr long ptr ptr)
@ stdcall StringTableTrim(ptr)
@ stdcall TakeOwnershipOfFile(wstr) @ stdcall TakeOwnershipOfFile(wstr)
@ stdcall UnicodeToMultiByte(wstr long) @ stdcall UnicodeToMultiByte(wstr long)
@ stdcall UnmapAndCloseFile(long long ptr) @ stdcall UnmapAndCloseFile(long long ptr)
@ -549,4 +550,15 @@
@ stub pSetupSetQueueFlags @ stub pSetupSetQueueFlags
@ stub pSetupSetSystemSourceFlags @ stub pSetupSetSystemSourceFlags
@ stub pSetupStringFromGuid @ 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 @ stub pSetupVerifyQueuedCatalogs

709
dlls/setupapi/stringtable.c Normal file
View File

@ -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 <stdarg.h>
#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);
}

View File

@ -158,6 +158,8 @@ DECL_WINELIB_SETUPAPI_TYPE_AW(PSP_FILE_CALLBACK)
typedef UINT DI_FUNCTION; typedef UINT DI_FUNCTION;
DECLARE_HANDLE(HSTRING_TABLE);
typedef struct _SP_CLASSINSTALL_HEADER typedef struct _SP_CLASSINSTALL_HEADER
{ {
DWORD cbSize; DWORD cbSize;
@ -415,6 +417,9 @@ DECL_WINELIB_SETUPAPI_TYPE_AW(PFILEPATHS)
#define SP_COPY_NOPRUNE 0x00100000 #define SP_COPY_NOPRUNE 0x00100000
#define SP_COPY_OEM_F6_INF 0x00200000 #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_DELREG_BIT 0x00008000
#define FLG_ADDREG_BINVALUETYPE 0x00000001 #define FLG_ADDREG_BINVALUETYPE 0x00000001
#define FLG_ADDREG_NOCLOBBER 0x00000002 #define FLG_ADDREG_NOCLOBBER 0x00000002
@ -858,6 +863,14 @@ BOOL WINAPI SetupSetFileQueueAlternatePlatformW( HSPFILEQ, PSP_ALTPLATFORM_I
BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ, DWORD, DWORD ); BOOL WINAPI SetupSetFileQueueFlags( HSPFILEQ, DWORD, DWORD );
void WINAPI SetupTermDefaultQueueCallback( PVOID ); void WINAPI SetupTermDefaultQueueCallback( PVOID );
DWORD WINAPI StampFileSecurity(PCWSTR, PSECURITY_DESCRIPTOR); 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); DWORD WINAPI TakeOwnershipOfFile(PCWSTR);
PSTR WINAPI UnicodeToMultiByte(PCWSTR lpUnicodeStr, UINT uCodePage); PSTR WINAPI UnicodeToMultiByte(PCWSTR lpUnicodeStr, UINT uCodePage);
BOOL WINAPI UnmapAndCloseFile(HANDLE, HANDLE, PVOID); BOOL WINAPI UnmapAndCloseFile(HANDLE, HANDLE, PVOID);