Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
8802f84c
Commit
8802f84c
authored
May 04, 2014
by
Nikolay Sivov
Committed by
Alexandre Julliard
May 06, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
setupapi: Implement a binary compatible string table.
parent
351fae12
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
423 additions
and
504 deletions
+423
-504
stringtable.c
dlls/setupapi/stringtable.c
+332
-447
stringtable.c
dlls/setupapi/tests/stringtable.c
+91
-57
No files found.
dlls/setupapi/stringtable.c
View file @
8802f84c
...
...
@@ -2,6 +2,7 @@
* Setupapi string table functions
*
* Copyright 2005 Eric Kohl
* Copyright 2014 Nikolay Sivov for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -19,88 +20,103 @@
*/
#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 "winnls.h"
#include "setupapi.h"
#include "wine/debug.h"
#define TABLE_DEFAULT_SIZE 256
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
setupapi
);
DECLARE_HANDLE
(
HSTRING_TABLE
);
typedef
struct
_TABLE_SLOT
{
LPWSTR
pString
;
LPVOID
pData
;
DWORD
dwSize
;
}
TABLE_SLOT
,
*
PTABLE_SLOT
;
struct
stringtable
{
char
*
data
;
ULONG
nextoffset
;
ULONG
allocated
;
DWORD_PTR
unk
[
2
];
ULONG
max_extra_size
;
LCID
lcid
;
};
typedef
struct
_STRING_TABLE
{
PTABLE_SLOT
pSlots
;
DWORD
dwUsedSlots
;
DWORD
dwMaxSlots
;
DWORD
dwMaxDataSize
;
}
STRING_TABLE
,
*
PSTRING_TABLE
;
struct
stringentry
{
DWORD
nextoffset
;
WCHAR
data
[
1
];
};
#define BUCKET_COUNT 509
#define DEFAULT_ALLOC_SIZE 4096
/**************************************************************************
* 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
;
/*
String table details
TRACE
(
"
\n
"
);
Returned string table 'handle' is a pointer to 'struct stringtable' structure.
Data itself is allocated separately, pointer is stored in 'data' field.
pStringTable
=
MyMalloc
(
sizeof
(
STRING_TABLE
));
if
(
pStringTable
==
NULL
)
{
ERR
(
"Invalid hStringTable!
\n
"
);
return
NULL
;
}
Data starts with array of 509 DWORDs - lookup table. Initially all offsets in that
array are set to -1. Right after lookup table goes data itself, stored in linked lists.
Lookup table offset points to first record of 'struct stringentry' type. When more
than one record is present in a bucket, first record links to next one with 'nextoffset'
field. Last record has nextoffset == -1, same when there's only one record. String data
is placed right after offset, and is followed by extra data. Each record has reserved
'max_extra_size' bytes to store extra data, it's not compacted in any way.
memset
(
pStringTable
,
0
,
sizeof
(
STRING_TABLE
));
A simple hash function is used to determine which bucket a given string belongs to (see below).
pStringTable
->
pSlots
=
MyMalloc
(
sizeof
(
TABLE_SLOT
)
*
TABLE_DEFAULT_SIZE
);
if
(
pStringTable
->
pSlots
==
NULL
)
{
MyFree
(
pStringTable
);
return
NULL
;
All offsets including returned string ids are relative to 'data' pointer. When table
needs to grow 'allocated' size is doubled, but offsets are always valid and preserved.
*/
static
inline
DWORD
get_string_hash
(
const
WCHAR
*
str
,
BOOL
case_sensitive
)
{
DWORD
hash
=
0
;
while
(
*
str
)
{
WCHAR
ch
=
case_sensitive
?
*
str
:
tolowerW
(
*
str
);
hash
+=
ch
;
if
(
ch
&
~
0xff
)
hash
|=
1
;
str
++
;
}
memset
(
pStringTable
->
pSlots
,
0
,
sizeof
(
TABLE_SLOT
)
*
TABLE_DEFAULT_SIZE
);
return
hash
%
BUCKET_COUNT
;
}
static
inline
DWORD
*
get_bucket_ptr
(
struct
stringtable
*
table
,
const
WCHAR
*
string
,
BOOL
case_sensitive
)
{
DWORD
hash
=
get_string_hash
(
string
,
case_sensitive
);
return
(
DWORD
*
)(
table
->
data
+
hash
*
sizeof
(
DWORD
));
}
pStringTable
->
dwUsedSlots
=
0
;
pStringTable
->
dwMaxSlots
=
TABLE_DEFAULT_SIZE
;
pStringTable
->
dwMaxDataSize
=
0
;
static
inline
WCHAR
*
get_string_ptr
(
struct
stringtable
*
table
,
DWORD
id
)
{
return
(
WCHAR
*
)(
table
->
data
+
id
+
sizeof
(
DWORD
));
}
TRACE
(
"Done
\n
"
);
static
inline
char
*
get_extradata_ptr
(
struct
stringtable
*
table
,
DWORD
id
)
{
WCHAR
*
ptrW
=
get_string_ptr
(
table
,
id
);
/* skip string itself */
return
(
char
*
)(
ptrW
+
strlenW
(
ptrW
)
+
1
);
}
return
(
HSTRING_TABLE
)
pStringTable
;
static
inline
BOOL
is_valid_string_id
(
struct
stringtable
*
table
,
DWORD
id
)
{
return
(
id
>=
BUCKET_COUNT
*
sizeof
(
DWORD
))
&&
(
id
<
table
->
allocated
);
}
static
inline
int
get_aligned16_size
(
int
size
)
{
return
(
size
+
15
)
&
~
15
;
}
/**************************************************************************
* StringTableInitializeEx [SETUPAPI.@]
...
...
@@ -108,433 +124,340 @@ StringTableInitialize(VOID)
* Creates a new string table and initializes it.
*
* PARAMS
*
dwMaxExtraDataSize
[I] Maximum extra data size
*
dwR
eserved [I] Unused
*
max_extra_size
[I] Maximum extra data size
*
r
eserved [I] Unused
*
* RETURNS
* Success: Handle to the string table
* Failure: NULL
*/
HSTRING_TABLE
WINAPI
StringTableInitializeEx
(
DWORD
dwMaxExtraDataSize
,
DWORD
dwReserved
)
HSTRING_TABLE
WINAPI
StringTableInitializeEx
(
ULONG
max_extra_size
,
DWORD
reserved
)
{
PSTRING_TABLE
pStringTable
;
TRACE
(
"
\n
"
);
struct
stringtable
*
table
;
pStringTable
=
MyMalloc
(
sizeof
(
STRING_TABLE
));
if
(
pStringTable
==
NULL
)
return
NULL
;
TRACE
(
"(%d %x)
\n
"
,
max_extra_size
,
reserved
);
memset
(
pStringTable
,
0
,
sizeof
(
STRING_TABLE
));
table
=
MyMalloc
(
sizeof
(
*
table
));
if
(
!
table
)
return
NULL
;
pStringTable
->
pSlots
=
MyMalloc
(
sizeof
(
TABLE_SLOT
)
*
TABLE_DEFAULT
_SIZE
);
if
(
pStringTable
->
pSlots
==
NULL
)
{
MyFree
(
pStringT
able
);
table
->
allocated
=
get_aligned16_size
(
BUCKET_COUNT
*
sizeof
(
DWORD
)
+
DEFAULT_ALLOC
_SIZE
);
table
->
data
=
MyMalloc
(
table
->
allocated
);
if
(
!
table
->
data
)
{
MyFree
(
t
able
);
return
NULL
;
}
memset
(
pStringTable
->
pSlots
,
0
,
sizeof
(
TABLE_SLOT
)
*
TABLE_DEFAULT_SIZE
);
pStringTable
->
dwUsedSlots
=
0
;
pStringTable
->
dwMaxSlots
=
TABLE_DEFAULT_SIZE
;
pStringTable
->
dwMaxDataSize
=
dwMaxExtraDataSize
;
table
->
nextoffset
=
BUCKET_COUNT
*
sizeof
(
DWORD
);
/* FIXME: actually these two are not zero */
table
->
unk
[
0
]
=
table
->
unk
[
1
]
=
0
;
table
->
max_extra_size
=
max_extra_size
;
table
->
lcid
=
GetThreadLocale
()
;
TRACE
(
"Done
\n
"
);
/* bucket area is filled with 0xff, actual string data area is zeroed */
memset
(
table
->
data
,
0xff
,
table
->
nextoffset
);
memset
(
table
->
data
+
table
->
nextoffset
,
0
,
table
->
allocated
-
table
->
nextoffset
);
return
(
HSTRING_TABLE
)
pStringT
able
;
return
(
HSTRING_TABLE
)
t
able
;
}
/**************************************************************************
* StringTable
Destroy
[SETUPAPI.@]
* StringTable
Initialize
[SETUPAPI.@]
*
*
Destroys a string table
.
*
Creates a new string table and initializes it
.
*
* PARAMS
*
hStringTable [I] Handle to the string table to be destroyed
*
None
*
* RETURNS
* None
* Success: Handle to the string table
* Failure: NULL
*/
VOID
WINAPI
StringTableDestroy
(
HSTRING_TABLE
hStringTable
)
HSTRING_TABLE
WINAPI
StringTableInitialize
(
void
)
{
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
++
)
{
MyFree
(
pStringTable
->
pSlots
[
i
].
pString
);
pStringTable
->
pSlots
[
i
].
pString
=
NULL
;
MyFree
(
pStringTable
->
pSlots
[
i
].
pData
);
pStringTable
->
pSlots
[
i
].
pData
=
NULL
;
pStringTable
->
pSlots
[
i
].
dwSize
=
0
;
}
MyFree
(
pStringTable
->
pSlots
);
}
MyFree
(
pStringTable
);
return
StringTableInitializeEx
(
0
,
0
);
}
/**************************************************************************
* StringTable
AddStringEx
[SETUPAPI.@]
* StringTable
Destroy
[SETUPAPI.@]
*
*
Adds a new string plus extra data to the
string table.
*
Destroys a
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
* hTable [I] Handle to the string table to be destroyed
*
* RETURNS
* Success: String ID
* Failure: ~0u
*
* 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.
* None
*/
DWORD
WINAPI
StringTableAddStringEx
(
HSTRING_TABLE
hStringTable
,
LPWSTR
lpString
,
DWORD
dwFlags
,
LPVOID
lpExtraData
,
DWORD
dwExtraDataSize
)
void
WINAPI
StringTableDestroy
(
HSTRING_TABLE
hTable
)
{
PSTRING_TABLE
pStringTable
;
DWORD
i
;
TRACE
(
"%p %s %x %p, %u
\n
"
,
hStringTable
,
debugstr_w
(
lpString
),
dwFlags
,
lpExtraData
,
dwExtraDataSize
);
pStringTable
=
(
PSTRING_TABLE
)
hStringTable
;
if
(
!
pStringTable
)
{
ERR
(
"Invalid hStringTable!
\n
"
);
return
~
0u
;
}
/* Search for existing string in the string table */
for
(
i
=
0
;
i
<
pStringTable
->
dwMaxSlots
;
i
++
)
{
if
(
pStringTable
->
pSlots
[
i
].
pString
)
{
if
(
dwFlags
&
1
)
{
if
(
!
lstrcmpW
(
pStringTable
->
pSlots
[
i
].
pString
,
lpString
))
return
i
+
1
;
}
else
{
if
(
!
lstrcmpiW
(
pStringTable
->
pSlots
[
i
].
pString
,
lpString
))
return
i
+
1
;
}
}
}
struct
stringtable
*
table
=
(
struct
stringtable
*
)
hTable
;
/* Check for filled slot table */
if
(
pStringTable
->
dwUsedSlots
==
pStringTable
->
dwMaxSlots
)
{
FIXME
(
"Resize the string table!
\n
"
);
return
~
0u
;
}
TRACE
(
"%p
\n
"
,
table
);
/* Search for an empty slot */
for
(
i
=
0
;
i
<
pStringTable
->
dwMaxSlots
;
i
++
)
{
if
(
!
pStringTable
->
pSlots
[
i
].
pString
)
{
pStringTable
->
pSlots
[
i
].
pString
=
MyMalloc
((
lstrlenW
(
lpString
)
+
1
)
*
sizeof
(
WCHAR
));
if
(
!
pStringTable
->
pSlots
[
i
].
pString
)
{
WARN
(
"Couldn't allocate memory for a new string!
\n
"
);
return
~
0u
;
}
lstrcpyW
(
pStringTable
->
pSlots
[
i
].
pString
,
lpString
);
if
(
!
table
)
return
;
pStringTable
->
pSlots
[
i
].
pData
=
MyMalloc
(
dwExtraDataSize
);
if
(
!
pStringTable
->
pSlots
[
i
].
pData
)
{
TRACE
(
"Couldn't allocate memory for data!
\n
"
);
return
~
0u
;
}
memcpy
(
pStringTable
->
pSlots
[
i
].
pData
,
lpExtraData
,
dwExtraDataSize
);
pStringTable
->
pSlots
[
i
].
dwSize
=
dwExtraDataSize
;
pStringTable
->
dwUsedSlots
++
;
return
i
+
1
;
}
}
TRACE
(
"Couldn't find an empty slot!
\n
"
);
return
~
0u
;
MyFree
(
table
->
data
);
MyFree
(
table
);
}
/**************************************************************************
* 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: ~0u
*
* 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
)
{
return
StringTableAddStringEx
(
hStringTable
,
lpString
,
dwFlags
,
NULL
,
0
);
}
/**************************************************************************
* StringTableDuplicate [SETUPAPI.@]
*
* Duplicates a given string table.
*
* PARAMS
* h
String
Table [I] Handle to the string table
* hTable [I] Handle to the string table
*
* RETURNS
* Success: Handle to the duplicated string table
* Failure: NULL
*
*/
HSTRING_TABLE
WINAPI
StringTableDuplicate
(
HSTRING_TABLE
hStringTable
)
HSTRING_TABLE
WINAPI
StringTableDuplicate
(
HSTRING_TABLE
hTable
)
{
PSTRING_TABLE
pSourceTable
;
PSTRING_TABLE
pDestinationTable
;
DWORD
i
;
DWORD
length
;
struct
stringtable
*
src
=
(
struct
stringtable
*
)
hTable
,
*
dest
;
TRACE
(
"%p
\n
"
,
hStringTable
);
TRACE
(
"%p
\n
"
,
src
);
pSourceTable
=
(
PSTRING_TABLE
)
hStringTable
;
if
(
pSourceTable
==
NULL
)
{
ERR
(
"Invalid hStringTable!
\n
"
);
if
(
!
src
)
return
NULL
;
}
pDestinationTable
=
MyMalloc
(
sizeof
(
STRING_TABLE
));
if
(
pDestinationTable
==
NULL
)
{
ERR
(
"Could not allocate a new string table!
\n
"
);
dest
=
MyMalloc
(
sizeof
(
*
dest
));
if
(
!
dest
)
return
NULL
;
}
memset
(
pDestinationTable
,
0
,
sizeof
(
STRING_TABLE
));
pDestinationTable
->
pSlots
=
MyMalloc
(
sizeof
(
TABLE_SLOT
)
*
pSourceTable
->
dwMaxSlots
);
if
(
pDestinationTable
->
pSlots
==
NULL
)
{
MyFree
(
pDestinationTable
);
*
dest
=
*
src
;
dest
->
data
=
MyMalloc
(
src
->
allocated
);
if
(
!
dest
->
data
)
{
MyFree
(
dest
);
return
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
;
memcpy
(
dest
->
data
,
src
->
data
,
src
->
allocated
);
return
(
HSTRING_TABLE
)
dest
;
}
/**************************************************************************
* StringTableGetExtraData [SETUPAPI.@]
*
* Retrieves extra data from a given string table entry.
*
* PARAMS
* h
StringTable
[I] Handle to the string table
*
dwId
[I] String ID
*
lpExtraData
[I] Pointer a buffer that receives the extra data
*
dwExtraDataS
ize [I] Size of the buffer
* h
Table
[I] Handle to the string table
*
id
[I] String ID
*
extra
[I] Pointer a buffer that receives the extra data
*
extra_s
ize [I] Size of the buffer
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL
WINAPI
StringTableGetExtraData
(
HSTRING_TABLE
hStringTable
,
DWORD
dwId
,
LPVOID
lpExtraData
,
DWORD
dwExtraDataSize
)
BOOL
WINAPI
StringTableGetExtraData
(
HSTRING_TABLE
hTable
,
ULONG
id
,
void
*
extra
,
ULONG
extra_size
)
{
PSTRING_TABLE
pStringTable
;
struct
stringtable
*
table
=
(
struct
stringtable
*
)
hTable
;
char
*
extraptr
;
TRACE
(
"%p %x %p %u
\n
"
,
hStringTable
,
dwId
,
lpExtraData
,
dwExtraDataSize
);
TRACE
(
"%p %u %p %u
\n
"
,
table
,
id
,
extra
,
extra_size
);
pStringTable
=
(
PSTRING_TABLE
)
hStringTable
;
if
(
pStringTable
==
NULL
)
{
ERR
(
"Invalid hStringTable!
\n
"
);
if
(
!
table
)
return
FALSE
;
}
if
(
dwId
==
0
||
dwId
>
pStringTable
->
dwMaxSlots
)
{
ERR
(
"Invalid Slot id!
\n
"
);
if
(
!
is_valid_string_id
(
table
,
id
))
return
FALSE
;
}
if
(
pStringTable
->
pSlots
[
dwId
-
1
].
dwSize
>
dwExtraDataS
ize
)
if
(
table
->
max_extra_size
>
extra_s
ize
)
{
ERR
(
"
Data size is too large!
\n
"
);
ERR
(
"
data size is too large
\n
"
);
return
FALSE
;
}
memcpy
(
lpExtraData
,
pStringTable
->
pSlots
[
dwId
-
1
].
pData
,
dwExtraDataSize
);
extraptr
=
get_extradata_ptr
(
table
,
id
);
memcpy
(
extra
,
extraptr
,
extra_size
);
return
TRUE
;
}
/**************************************************************************
* StringTableLookUpStringEx [SETUPAPI.@]
*
* Searches a string table and extra data for a given string.
*
* PARAMS
* h
StringTable
[I] Handle to the string table
*
lpString
[I] String to be searched for
*
dwFlags
[I] Flags
* h
Table
[I] Handle to the string table
*
string
[I] String to be searched for
*
flags
[I] Flags
* 1: case sensitive compare
*
lpExtraData
[O] Pointer to the buffer that receives the extra data
*
dwReserved
[I/O] Unused
*
extra
[O] Pointer to the buffer that receives the extra data
*
extra_size
[I/O] Unused
*
* RETURNS
* Success: String ID
* Failure: -1
*/
DWORD
WINAPI
StringTableLookUpStringEx
(
HSTRING_TABLE
hStringTable
,
LPWSTR
lpString
,
DWORD
dwFlags
,
LPVOID
lpExtraData
,
DWORD
dwReserved
)
DWORD
WINAPI
StringTableLookUpStringEx
(
HSTRING_TABLE
hTable
,
LPWSTR
string
,
DWORD
flags
,
void
*
extra
,
ULONG
extra_size
)
{
PSTRING_TABLE
pStringTable
;
DWORD
i
;
TRACE
(
"%p %s %x %p, %x
\n
"
,
hStringTable
,
debugstr_w
(
lpString
),
dwFlags
,
lpExtraData
,
dwReserved
);
pStringTable
=
(
PSTRING_TABLE
)
hStringTable
;
if
(
pStringTable
==
NULL
)
{
ERR
(
"Invalid hStringTable!
\n
"
);
return
~
0u
;
}
/* 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
))
{
if
(
lpExtraData
)
memcpy
(
lpExtraData
,
pStringTable
->
pSlots
[
i
].
pData
,
dwReserved
);
return
i
+
1
;
}
}
struct
stringtable
*
table
=
(
struct
stringtable
*
)
hTable
;
BOOL
case_sensitive
=
flags
&
1
;
struct
stringentry
*
entry
;
DWORD
offset
;
int
cmp
;
TRACE
(
"%p->%p %s %x %p, %x
\n
"
,
table
,
table
->
data
,
debugstr_w
(
string
),
flags
,
extra
,
extra_size
);
if
(
!
table
)
return
-
1
;
/* get corresponding offset */
offset
=
*
get_bucket_ptr
(
table
,
string
,
case_sensitive
);
if
(
offset
==
-
1
)
return
-
1
;
/* now we're at correct bucket, do linear search for string */
while
(
1
)
{
entry
=
(
struct
stringentry
*
)(
table
->
data
+
offset
);
if
(
case_sensitive
)
cmp
=
lstrcmpW
(
entry
->
data
,
string
);
else
{
if
(
!
lstrcmpiW
(
pStringTable
->
pSlots
[
i
].
pString
,
lpString
))
{
if
(
lpExtraData
)
memcpy
(
lpExtraData
,
pStringTable
->
pSlots
[
i
].
pData
,
dwReserved
);
return
i
+
1
;
}
}
cmp
=
lstrcmpiW
(
entry
->
data
,
string
);
if
(
!
cmp
)
{
if
(
extra
)
memcpy
(
extra
,
get_extradata_ptr
(
table
,
offset
),
extra_size
);
return
offset
;
}
/* last entry */
if
(
entry
->
nextoffset
==
-
1
)
return
-
1
;
offset
=
entry
->
nextoffset
;
if
(
offset
>
table
->
allocated
)
return
-
1
;
}
return
~
0u
;
}
/**************************************************************************
* StringTableLookUpString [SETUPAPI.@]
*
* Searches a string table for a given string.
*
* PARAMS
* h
StringTable
[I] Handle to the string table
*
lpString
[I] String to be searched for
*
dwFlags
[I] Flags
* h
Table
[I] Handle to the string table
*
string
[I] String to be searched for
*
flags
[I] Flags
* 1: case sensitive compare
*
* RETURNS
* Success: String ID
* Failure:
~0u
* Failure:
-1
*/
DWORD
WINAPI
StringTableLookUpString
(
HSTRING_TABLE
hStringTable
,
LPWSTR
lpString
,
DWORD
dwFlags
)
DWORD
WINAPI
StringTableLookUpString
(
HSTRING_TABLE
hTable
,
LPWSTR
string
,
DWORD
flags
)
{
return
StringTableLookUpStringEx
(
h
StringTable
,
lpString
,
dwF
lags
,
NULL
,
0
);
return
StringTableLookUpStringEx
(
h
Table
,
string
,
f
lags
,
NULL
,
0
);
}
/**************************************************************************
* StringTableAddStringEx [SETUPAPI.@]
*
* Adds a new string plus extra data to the string table.
*
* PARAMS
* hTable [I] Handle to the string table
* string [I] String to be added to the string table
* flags [I] Flags
* 1: case sensitive compare
* extra [I] Pointer to the extra data
* extra_size [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
hTable
,
LPWSTR
string
,
DWORD
flags
,
void
*
extra
,
DWORD
extra_size
)
{
struct
stringtable
*
table
=
(
struct
stringtable
*
)
hTable
;
BOOL
case_sensitive
=
flags
&
1
;
struct
stringentry
*
entry
;
DWORD
id
,
*
offset
;
WCHAR
*
ptrW
;
int
len
;
TRACE
(
"%p %s %x %p, %u
\n
"
,
hTable
,
debugstr_w
(
string
),
flags
,
extra
,
extra_size
);
if
(
!
table
)
return
-
1
;
id
=
StringTableLookUpStringEx
(
hTable
,
string
,
flags
,
NULL
,
0
);
if
(
id
!=
-
1
)
return
id
;
/* needed space for new record */
len
=
sizeof
(
DWORD
)
+
(
strlenW
(
string
)
+
1
)
*
sizeof
(
WCHAR
)
+
table
->
max_extra_size
;
if
(
table
->
nextoffset
+
len
>=
table
->
allocated
)
{
table
->
allocated
<<=
1
;
table
->
data
=
HeapReAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
table
->
data
,
table
->
allocated
);
}
/* hash string */
offset
=
get_bucket_ptr
(
table
,
string
,
case_sensitive
);
if
(
*
offset
==
-
1
)
/* bucket used for a very first time */
*
offset
=
table
->
nextoffset
;
else
{
entry
=
(
struct
stringentry
*
)(
table
->
data
+
*
offset
);
/* link existing last entry to newly added */
while
(
entry
->
nextoffset
!=
-
1
)
entry
=
(
struct
stringentry
*
)(
table
->
data
+
entry
->
nextoffset
);
entry
->
nextoffset
=
table
->
nextoffset
;
}
entry
=
(
struct
stringentry
*
)(
table
->
data
+
table
->
nextoffset
);
entry
->
nextoffset
=
-
1
;
id
=
table
->
nextoffset
;
/* copy string */
ptrW
=
get_string_ptr
(
table
,
id
);
strcpyW
(
ptrW
,
string
);
if
(
!
case_sensitive
)
strlwrW
(
ptrW
);
/* copy extra data */
if
(
extra
)
memcpy
(
get_extradata_ptr
(
table
,
id
),
extra
,
extra_size
);
table
->
nextoffset
+=
len
;
return
id
;
}
/**************************************************************************
* StringTableAddString [SETUPAPI.@]
*
* Adds a new string to the string table.
*
* PARAMS
* hTable [I] Handle to the string table
* string [I] String to be added to the string table
* flags [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
hTable
,
LPWSTR
string
,
DWORD
flags
)
{
return
StringTableAddStringEx
(
hTable
,
string
,
flags
,
NULL
,
0
);
}
/**************************************************************************
* StringTableSetExtraData [SETUPAPI.@]
...
...
@@ -542,166 +465,128 @@ StringTableLookUpString(HSTRING_TABLE hStringTable,
* Sets extra data for a given string table entry.
*
* PARAMS
* h
StringTable
[I] Handle to the string table
*
dwId
[I] String ID
*
lpExtraData
[I] Pointer to the extra data
*
dwExtraDataS
ize [I] Size of the extra data
* h
Table
[I] Handle to the string table
*
id
[I] String ID
*
extra
[I] Pointer to the extra data
*
extra_s
ize [I] Size of the extra data
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL
WINAPI
StringTableSetExtraData
(
HSTRING_TABLE
hStringTable
,
DWORD
dwId
,
LPVOID
lpExtraData
,
DWORD
dwExtraDataSize
)
BOOL
WINAPI
StringTableSetExtraData
(
HSTRING_TABLE
hTable
,
DWORD
id
,
void
*
extra
,
ULONG
extra_size
)
{
PSTRING_TABLE
pStringTable
;
struct
stringtable
*
table
=
(
struct
stringtable
*
)
hTable
;
char
*
extraptr
;
TRACE
(
"%p %x %p %u
\n
"
,
hStringTable
,
dwId
,
lpExtraData
,
dwExtraDataSize
);
TRACE
(
"%p %d %p %u
\n
"
,
hTable
,
id
,
extra
,
extra_size
);
pStringTable
=
(
PSTRING_TABLE
)
hStringTable
;
if
(
pStringTable
==
NULL
)
{
ERR
(
"Invalid hStringTable!
\n
"
);
if
(
!
table
)
return
FALSE
;
}
if
(
dwId
==
0
||
dwId
>
pStringTable
->
dwMaxSlots
)
{
ERR
(
"Invalid Slot id!
\n
"
);
if
(
!
is_valid_string_id
(
table
,
id
))
return
FALSE
;
}
if
(
pStringTable
->
dwMaxDataSize
<
dwExtraDataS
ize
)
if
(
table
->
max_extra_size
<
extra_s
ize
)
{
ERR
(
"
Data size is too large!
\n
"
);
ERR
(
"
data size is too large
\n
"
);
return
FALSE
;
}
pStringTable
->
pSlots
[
dwId
-
1
].
pData
=
MyMalloc
(
dwExtraDataSize
);
if
(
pStringTable
->
pSlots
[
dwId
-
1
].
pData
==
NULL
)
{
ERR
(
"
\n
"
);
return
FALSE
;
}
memcpy
(
pStringTable
->
pSlots
[
dwId
-
1
].
pData
,
lpExtraData
,
dwExtraDataSize
);
pStringTable
->
pSlots
[
dwId
-
1
].
dwSize
=
dwExtraDataSize
;
extraptr
=
get_extradata_ptr
(
table
,
id
);
memset
(
extraptr
,
0
,
table
->
max_extra_size
);
memcpy
(
extraptr
,
extra
,
extra_size
);
return
TRUE
;
}
/**************************************************************************
* StringTableStringFromId [SETUPAPI.@]
*
* Returns a pointer to a string for the given string ID.
*
* PARAMS
* h
String
Table [I] Handle to the string table.
*
dwId
[I] String ID
* hTable [I] Handle to the string table.
*
id
[I] String ID
*
* RETURNS
* Success: Pointer to the string
* Failure: NULL
*/
LPWSTR
WINAPI
StringTableStringFromId
(
HSTRING_TABLE
hStringTable
,
DWORD
dwId
)
LPWSTR
WINAPI
StringTableStringFromId
(
HSTRING_TABLE
hTable
,
ULONG
id
)
{
PSTRING_TABLE
pString
Table
;
struct
stringtable
*
table
=
(
struct
stringtable
*
)
h
Table
;
static
WCHAR
empty
[]
=
{
0
};
TRACE
(
"%p %
x
\n
"
,
hStringTable
,
dwI
d
);
TRACE
(
"%p %
d
\n
"
,
table
,
i
d
);
pStringTable
=
(
PSTRING_TABLE
)
hStringTable
;
if
(
pStringTable
==
NULL
)
{
ERR
(
"Invalid hStringTable!
\n
"
);
if
(
!
table
)
return
NULL
;
}
if
(
dwId
==
0
||
dwId
>
pStringTable
->
dwMaxSlots
)
if
(
!
is_valid_string_id
(
table
,
id
)
)
return
empty
;
return
pStringTable
->
pSlots
[
dwId
-
1
].
pString
;
return
get_string_ptr
(
table
,
id
)
;
}
/**************************************************************************
* StringTableStringFromIdEx [SETUPAPI.@]
*
* Returns a string for the given string ID.
*
* PARAMS
* h
StringTable
[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
* h
Table
[I] Handle to the string table
*
id
[I] String ID
*
buff
[I] Pointer to string buffer
*
buflen
[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
)
BOOL
WINAPI
StringTableStringFromIdEx
(
HSTRING_TABLE
hTable
,
ULONG
id
,
LPWSTR
buff
,
DWORD
*
buflen
)
{
PSTRING_TABLE
pStringTable
;
DWORD
dwLength
;
BOOL
bResult
=
FALSE
;
struct
stringtable
*
table
=
(
struct
stringtable
*
)
hTable
;
BOOL
ret
=
TRUE
;
WCHAR
*
ptrW
;
int
len
;
TRACE
(
"%p %x %p %p
\n
"
,
hStringTable
,
dwId
,
lpBuffer
,
lpBufferLength
);
TRACE
(
"%p %x %p %p
\n
"
,
table
,
id
,
buff
,
buflen
);
pStringTable
=
(
PSTRING_TABLE
)
hStringTable
;
if
(
pStringTable
==
NULL
)
{
ERR
(
"Invalid hStringTable!
\n
"
);
*
lpBufferLength
=
0
;
if
(
!
table
)
{
*
buflen
=
0
;
return
FALSE
;
}
if
(
dwId
==
0
||
dwId
>
pStringTable
->
dwMaxSlots
||
pStringTable
->
pSlots
[
dwId
-
1
].
pString
==
NULL
)
{
WARN
(
"Invalid string ID!
\n
"
);
*
lpBufferLength
=
0
;
if
(
!
is_valid_string_id
(
table
,
id
))
{
WARN
(
"invalid string id
\n
"
);
*
buflen
=
0
;
return
FALSE
;
}
dwLength
=
(
lstrlenW
(
pStringTable
->
pSlots
[
dwId
-
1
].
pString
)
+
1
)
*
sizeof
(
WCHAR
);
if
(
dwLength
<=
*
lpBufferLength
)
{
lstrcpyW
(
lpBuffer
,
pStringTable
->
pSlots
[
dwId
-
1
].
pString
);
bResult
=
TRUE
;
}
*
lpBufferLength
=
dwLength
;
ptrW
=
get_string_ptr
(
table
,
id
);
len
=
(
strlenW
(
ptrW
)
+
1
)
*
sizeof
(
WCHAR
);
if
(
len
<=
*
buflen
)
strcpyW
(
buff
,
ptrW
);
else
ret
=
FALSE
;
return
bResult
;
*
buflen
=
len
;
return
ret
;
}
/**************************************************************************
* StringTableTrim [SETUPAPI.@]
*
* ...
*
* PARAMS
* h
String
Table [I] Handle to the string table
* hTable [I] Handle to the string table
*
* RETURNS
* None
*/
VOID
WINAPI
StringTableTrim
(
HSTRING_TABLE
hStringTable
)
void
WINAPI
StringTableTrim
(
HSTRING_TABLE
hTable
)
{
FIXME
(
"%p
\n
"
,
h
String
Table
);
FIXME
(
"%p
\n
"
,
hTable
);
}
dlls/setupapi/tests/stringtable.c
View file @
8802f84c
...
...
@@ -29,11 +29,11 @@
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
#include "winnls.h"
#include "setupapi.h"
#include "wine/test.h"
DECLARE_HANDLE
(
HSTRING_TABLE
);
/* Flags for StringTableAddString and StringTableLookUpString */
...
...
@@ -48,57 +48,35 @@ static HSTRING_TABLE (WINAPI *pStringTableInitializeEx)(DWORD, DWORD);
static
DWORD
(
WINAPI
*
pStringTableLookUpString
)(
HSTRING_TABLE
,
LPWSTR
,
DWORD
);
static
DWORD
(
WINAPI
*
pStringTableLookUpStringEx
)(
HSTRING_TABLE
,
LPWSTR
,
DWORD
,
LPVOID
,
DWORD
);
static
LPWSTR
(
WINAPI
*
pStringTableStringFromId
)(
HSTRING_TABLE
,
DWORD
);
static
BOOL
(
WINAPI
*
pStringTableGetExtraData
)(
HSTRING_TABLE
,
ULONG
,
void
*
,
ULONG
);
static
HMODULE
hdll
;
static
WCHAR
string
[]
=
{
's'
,
't'
,
'r'
,
'i'
,
'n'
,
'g'
,
0
};
static
WCHAR
String
[]
=
{
'S'
,
't'
,
'r'
,
'i'
,
'n'
,
'g'
,
0
};
static
WCHAR
foo
[]
=
{
'f'
,
'o'
,
'o'
,
0
};
static
void
load_it_up
(
void
)
{
hdll
=
GetModuleHandleA
(
"setupapi.dll"
);
pStringTableInitialize
=
(
void
*
)
GetProcAddress
(
hdll
,
"StringTableInitialize"
);
if
(
!
pStringTableInitialize
)
pStringTableInitialize
=
(
void
*
)
GetProcAddress
(
hdll
,
"pSetupStringTableInitialize"
);
pStringTableInitializeEx
=
(
void
*
)
GetProcAddress
(
hdll
,
"StringTableInitializeEx"
);
if
(
!
pStringTableInitializeEx
)
pStringTableInitializeEx
=
(
void
*
)
GetProcAddress
(
hdll
,
"pSetupStringTableInitializeEx"
);
pStringTableAddString
=
(
void
*
)
GetProcAddress
(
hdll
,
"StringTableAddString"
);
if
(
!
pStringTableAddString
)
pStringTableAddString
=
(
void
*
)
GetProcAddress
(
hdll
,
"pSetupStringTableAddString"
);
pStringTableAddStringEx
=
(
void
*
)
GetProcAddress
(
hdll
,
"StringTableAddStringEx"
);
if
(
!
pStringTableAddStringEx
)
pStringTableAddStringEx
=
(
void
*
)
GetProcAddress
(
hdll
,
"pSetupStringTableAddStringEx"
);
pStringTableDuplicate
=
(
void
*
)
GetProcAddress
(
hdll
,
"StringTableDuplicate"
);
if
(
!
pStringTableDuplicate
)
pStringTableDuplicate
=
(
void
*
)
GetProcAddress
(
hdll
,
"pSetupStringTableDuplicate"
);
pStringTableDestroy
=
(
void
*
)
GetProcAddress
(
hdll
,
"StringTableDestroy"
);
if
(
!
pStringTableDestroy
)
pStringTableDestroy
=
(
void
*
)
GetProcAddress
(
hdll
,
"pSetupStringTableDestroy"
);
pStringTableLookUpString
=
(
void
*
)
GetProcAddress
(
hdll
,
"StringTableLookUpString"
);
if
(
!
pStringTableLookUpString
)
pStringTableLookUpString
=
(
void
*
)
GetProcAddress
(
hdll
,
"pSetupStringTableLookUpString"
);
pStringTableLookUpStringEx
=
(
void
*
)
GetProcAddress
(
hdll
,
"StringTableLookUpStringEx"
);
if
(
!
pStringTableLookUpStringEx
)
pStringTableLookUpStringEx
=
(
void
*
)
GetProcAddress
(
hdll
,
"pSetupStringTableLookUpStringEx"
);
pStringTableStringFromId
=
(
void
*
)
GetProcAddress
(
hdll
,
"StringTableStringFromId"
);
if
(
!
pStringTableStringFromId
)
pStringTableStringFromId
=
(
void
*
)
GetProcAddress
(
hdll
,
"pSetupStringTableStringFromId"
);
HMODULE
hdll
=
GetModuleHandleA
(
"setupapi.dll"
);
#define X(f) if (!(p##f = (void*)GetProcAddress(hdll, #f))) \
p##f = (void*)GetProcAddress(hdll, "pSetup"#f);
X
(
StringTableInitialize
);
X
(
StringTableInitializeEx
);
X
(
StringTableAddString
);
X
(
StringTableAddStringEx
);
X
(
StringTableDuplicate
);
X
(
StringTableDestroy
);
X
(
StringTableLookUpString
);
X
(
StringTableLookUpStringEx
);
X
(
StringTableStringFromId
);
X
(
StringTableGetExtraData
);
#undef X
}
static
void
test_StringTableAddString
(
void
)
{
DWORD
retval
,
hstring
,
hString
,
hfoo
;
H
AND
LE
table
;
H
STRING_TAB
LE
table
;
table
=
pStringTableInitialize
();
ok
(
table
!=
NULL
,
"failed to initialize string table
\n
"
);
...
...
@@ -124,22 +102,23 @@ static void test_StringTableAddString(void)
static
void
test_StringTableAddStringEx
(
void
)
{
DWORD
retval
,
hstring
,
hString
,
hfoo
;
DWORD
retval
,
hstring
,
hString
,
hfoo
,
extra
;
HANDLE
table
;
BOOL
ret
;
table
=
pStringTableInitialize
();
ok
(
table
!=
NULL
,
"Failed to Initialize String Table
\n
"
);
/* case insensitive */
hstring
=
pStringTableAddStringEx
(
table
,
string
,
0
,
NULL
,
0
);
ok
(
hstring
!=
~
0u
,
"Failed to add string to String Table
\n
"
);
ok
(
hstring
!=
-
1
,
"Failed to add string to String Table
\n
"
);
retval
=
pStringTableAddStringEx
(
table
,
String
,
0
,
NULL
,
0
);
ok
(
retval
!=
~
0u
,
"Failed to add String to String Table
\n
"
);
ok
(
retval
!=
-
1
,
"Failed to add String to String Table
\n
"
);
ok
(
hstring
==
retval
,
"string handle %x != String handle %x in String Table
\n
"
,
hstring
,
retval
);
hfoo
=
pStringTableAddStringEx
(
table
,
foo
,
0
,
NULL
,
0
);
ok
(
hfoo
!=
~
0u
,
"Failed to add foo to String Table
\n
"
);
ok
(
hfoo
!=
-
1
,
"Failed to add foo to String Table
\n
"
);
ok
(
hfoo
!=
hstring
,
"foo and string share the same ID %x in String Table
\n
"
,
hfoo
);
/* case sensitive */
...
...
@@ -147,11 +126,33 @@ static void test_StringTableAddStringEx(void)
ok
(
hstring
!=
hString
,
"String handle and string share same ID %x in Table
\n
"
,
hstring
);
pStringTableDestroy
(
table
);
/* set same string twice but with different extra */
table
=
pStringTableInitializeEx
(
4
,
0
);
ok
(
table
!=
NULL
,
"Failed to Initialize String Table
\n
"
);
extra
=
10
;
hstring
=
pStringTableAddStringEx
(
table
,
string
,
0
,
&
extra
,
4
);
ok
(
hstring
!=
-
1
,
"failed to add string, %d
\n
"
,
hstring
);
extra
=
0
;
ret
=
pStringTableGetExtraData
(
table
,
hstring
,
&
extra
,
4
);
ok
(
ret
&&
extra
==
10
,
"got %d, extra %d
\n
"
,
ret
,
extra
);
extra
=
11
;
hstring
=
pStringTableAddStringEx
(
table
,
string
,
0
,
&
extra
,
4
);
ok
(
hstring
!=
-
1
,
"failed to add string, %d
\n
"
,
hstring
);
extra
=
0
;
ret
=
pStringTableGetExtraData
(
table
,
hstring
,
&
extra
,
4
);
ok
(
ret
&&
extra
==
10
,
"got %d, extra %d
\n
"
,
ret
,
extra
);
pStringTableDestroy
(
table
);
}
static
void
test_StringTableDuplicate
(
void
)
{
H
AND
LE
table
,
table2
;
H
STRING_TAB
LE
table
,
table2
;
table
=
pStringTableInitialize
();
ok
(
table
!=
NULL
,
"Failed to Initialize String Table
\n
"
);
...
...
@@ -166,7 +167,7 @@ static void test_StringTableDuplicate(void)
static
void
test_StringTableLookUpString
(
void
)
{
DWORD
retval
,
retval2
,
hstring
,
hString
,
hfoo
;
H
AND
LE
table
,
table2
;
H
STRING_TAB
LE
table
,
table2
;
table
=
pStringTableInitialize
();
ok
(
table
!=
NULL
,
"failed to initialize string table
\n
"
);
...
...
@@ -224,7 +225,7 @@ static void test_StringTableLookUpStringEx(void)
{
static
WCHAR
uilevel
[]
=
{
'U'
,
'I'
,
'L'
,
'E'
,
'V'
,
'E'
,
'L'
,
0
};
DWORD
retval
,
retval2
,
hstring
,
hString
,
hfoo
,
data
;
H
AND
LE
table
,
table2
;
H
STRING_TAB
LE
table
,
table2
;
char
buffer
[
4
];
table
=
pStringTableInitialize
();
...
...
@@ -305,23 +306,55 @@ static void test_StringTableLookUpStringEx(void)
static
void
test_StringTableStringFromId
(
void
)
{
HANDLE
table
;
DWORD
hstring
;
HSTRING_TABLE
table
;
WCHAR
*
string2
;
int
result
;
DWORD
id
,
id2
;
table
=
pStringTableInitialize
();
ok
(
table
!=
NULL
,
"Failed to Initialize String Table
\n
"
);
ok
(
table
!=
NULL
,
"Failed to Initialize String Table
\n
"
);
hstring
=
pStringTableAddString
(
table
,
string
,
0
);
ok
(
hstring
!=
~
0u
,
"failed to add 'string' to string table
\n
"
);
id
=
pStringTableAddString
(
table
,
string
,
0
);
ok
(
id
!=
-
1
,
"failed to add 'string' to string table
\n
"
);
/* correct */
string2
=
pStringTableStringFromId
(
table
,
pStringTableLookUpString
(
table
,
string
,
0
));
ok
(
string2
!=
NULL
,
"Failed to look up string by ID from String Table
\n
"
);
id2
=
pStringTableLookUpString
(
table
,
string
,
0
);
ok
(
id2
==
id
,
"got %d and %d
\n
"
,
id2
,
id
);
string2
=
pStringTableStringFromId
(
table
,
id2
);
ok
(
string2
!=
NULL
,
"failed to lookup string %d
\n
"
,
id2
);
ok
(
!
lstrcmpiW
(
string
,
string2
),
"got %s, expected %s
\n
"
,
wine_dbgstr_w
(
string2
),
wine_dbgstr_w
(
string
));
pStringTableDestroy
(
table
);
}
struct
stringtable
{
char
*
data
;
ULONG
nextoffset
;
ULONG
allocated
;
DWORD_PTR
unk
[
2
];
ULONG
max_extra_size
;
LCID
lcid
;
};
static
void
test_stringtable_layout
(
void
)
{
struct
stringtable
*
ptr
;
HSTRING_TABLE
table
;
result
=
lstrcmpiW
(
string
,
string2
);
ok
(
result
==
0
,
"StringID %p does not match requested StringID %p
\n
"
,
string
,
string2
);
table
=
pStringTableInitialize
();
ok
(
table
!=
NULL
,
"failed to initialize string table
\n
"
);
ptr
=
(
struct
stringtable
*
)
table
;
ok
(
ptr
->
data
!=
NULL
,
"got %p
\n
"
,
ptr
->
data
);
/* first data offset is right after bucket area */
ok
(
ptr
->
nextoffset
==
509
*
sizeof
(
DWORD
),
"got %d
\n
"
,
ptr
->
nextoffset
);
ok
(
ptr
->
allocated
!=
0
,
"got %d
\n
"
,
ptr
->
allocated
);
todo_wine
{
ok
(
ptr
->
unk
[
0
]
!=
0
,
"got %lx
\n
"
,
ptr
->
unk
[
0
]);
ok
(
ptr
->
unk
[
1
]
!=
0
,
"got %lx
\n
"
,
ptr
->
unk
[
1
]);
}
ok
(
ptr
->
max_extra_size
==
0
,
"got %d
\n
"
,
ptr
->
max_extra_size
);
ok
(
ptr
->
lcid
==
GetThreadLocale
(),
"got %x, thread lcid %x
\n
"
,
ptr
->
lcid
,
GetThreadLocale
());
pStringTableDestroy
(
table
);
}
...
...
@@ -336,4 +369,5 @@ START_TEST(stringtable)
test_StringTableLookUpString
();
test_StringTableLookUpStringEx
();
test_StringTableStringFromId
();
test_stringtable_layout
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment