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
bf83ba1f
Commit
bf83ba1f
authored
Apr 23, 2005
by
Juan Lang
Committed by
Alexandre Julliard
Apr 23, 2005
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- convert strings between property storage's code page and system code
page - add tests for setting code page - fix tests and behavior to match WinXP
parent
419e9281
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
337 additions
and
30 deletions
+337
-30
stg_prop.c
dlls/ole32/stg_prop.c
+175
-23
stg_prop.c
dlls/ole32/tests/stg_prop.c
+162
-7
No files found.
dlls/ole32/stg_prop.c
View file @
bf83ba1f
...
@@ -31,7 +31,7 @@
...
@@ -31,7 +31,7 @@
* below, but it gives the best "big picture" that I've found.
* below, but it gives the best "big picture" that I've found.
*
*
* TODO: There's a lot missing in here. Biggies:
* TODO: There's a lot missing in here. Biggies:
* - There are all sorts of restricions I don't honor, like maximum property
* - There are all sorts of restric
t
ions I don't honor, like maximum property
* set byte size, maximum property name length
* set byte size, maximum property name length
* - Certain bogus files could result in reading past the end of a buffer.
* - Certain bogus files could result in reading past the end of a buffer.
* - This will probably fail on big-endian machines, especially reading and
* - This will probably fail on big-endian machines, especially reading and
...
@@ -130,6 +130,22 @@ static HRESULT PropertyStorage_CreateDictionaries(
...
@@ -130,6 +130,22 @@ static HRESULT PropertyStorage_CreateDictionaries(
static
void
PropertyStorage_DestroyDictionaries
(
static
void
PropertyStorage_DestroyDictionaries
(
struct
tagPropertyStorage_impl
*
);
struct
tagPropertyStorage_impl
*
);
/* Copies from propvar to prop. If propvar's type is VT_LPSTR, copies the
* string using PropertyStorage_StringCopy.
*/
static
HRESULT
PropertyStorage_PropVariantCopy
(
PROPVARIANT
*
prop
,
const
PROPVARIANT
*
propvar
,
LCID
targetCP
,
LCID
srcCP
);
/* Copies the string src, which is encoded using code page srcCP, and returns
* it in *dst, in the code page specified by targetCP. The returned string is
* allocated using CoTaskMemAlloc.
* If srcCP is CP_UNICODE, src is in fact an LPCWSTR. Similarly, if targetCP
* is CP_UNICODE, the returned string is in fact an LPWSTR.
* Returns S_OK on success, something else on failure.
*/
static
HRESULT
PropertyStorage_StringCopy
(
LPCSTR
src
,
LPSTR
*
dst
,
LCID
targetCP
,
LCID
srcCP
);
static
IPropertyStorageVtbl
IPropertyStorage_Vtbl
;
static
IPropertyStorageVtbl
IPropertyStorage_Vtbl
;
/***********************************************************************
/***********************************************************************
...
@@ -280,23 +296,144 @@ static HRESULT WINAPI IPropertyStorage_fnReadMultiple(
...
@@ -280,23 +296,144 @@ static HRESULT WINAPI IPropertyStorage_fnReadMultiple(
rgpspec
[
i
].
u
.
lpwstr
);
rgpspec
[
i
].
u
.
lpwstr
);
if
(
prop
)
if
(
prop
)
PropVariantCopy
(
&
rgpropvar
[
i
],
prop
);
PropertyStorage_PropVariantCopy
(
&
rgpropvar
[
i
],
prop
,
GetACP
(),
This
->
codePage
);
}
}
else
else
{
{
PROPVARIANT
*
prop
=
PropertyStorage_FindProperty
(
This
,
switch
(
rgpspec
[
i
].
u
.
propid
)
rgpspec
[
i
].
u
.
propid
);
{
case
PID_CODEPAGE
:
rgpropvar
[
i
].
vt
=
VT_I2
;
rgpropvar
[
i
].
u
.
iVal
=
This
->
codePage
;
break
;
case
PID_LOCALE
:
rgpropvar
[
i
].
vt
=
VT_I4
;
rgpropvar
[
i
].
u
.
lVal
=
This
->
locale
;
break
;
default:
{
PROPVARIANT
*
prop
=
PropertyStorage_FindProperty
(
This
,
rgpspec
[
i
].
u
.
propid
);
if
(
prop
)
if
(
prop
)
PropVariantCopy
(
&
rgpropvar
[
i
],
prop
);
PropertyStorage_PropVariantCopy
(
&
rgpropvar
[
i
],
prop
,
GetACP
(),
This
->
codePage
);
}
}
}
}
}
}
LeaveCriticalSection
(
&
This
->
cs
);
LeaveCriticalSection
(
&
This
->
cs
);
return
hr
;
return
hr
;
}
}
static
HRESULT
PropertyStorage_StringCopy
(
LPCSTR
src
,
LPSTR
*
dst
,
LCID
targetCP
,
LCID
srcCP
)
{
HRESULT
hr
=
S_OK
;
int
len
;
TRACE
(
"%s, %p, %ld, %ld
\n
"
,
srcCP
==
CP_UNICODE
?
debugstr_w
((
LPCWSTR
)
src
)
:
debugstr_a
(
src
),
dst
,
targetCP
,
srcCP
);
assert
(
src
);
assert
(
dst
);
*
dst
=
NULL
;
if
(
targetCP
==
srcCP
)
{
size_t
len
;
if
(
targetCP
==
CP_UNICODE
)
len
=
(
strlenW
((
LPCWSTR
)
src
)
+
1
)
*
sizeof
(
WCHAR
);
else
len
=
strlen
(
src
)
+
1
;
*
dst
=
CoTaskMemAlloc
(
len
*
sizeof
(
WCHAR
));
if
(
!*
dst
)
hr
=
STG_E_INSUFFICIENTMEMORY
;
else
memcpy
(
*
dst
,
src
,
len
);
}
else
{
if
(
targetCP
==
CP_UNICODE
)
{
len
=
MultiByteToWideChar
(
srcCP
,
0
,
src
,
-
1
,
NULL
,
0
);
*
dst
=
CoTaskMemAlloc
(
len
*
sizeof
(
WCHAR
));
if
(
!*
dst
)
hr
=
STG_E_INSUFFICIENTMEMORY
;
else
MultiByteToWideChar
(
srcCP
,
0
,
src
,
-
1
,
(
LPWSTR
)
*
dst
,
len
);
}
else
{
LPWSTR
wideStr
;
if
(
srcCP
==
CP_UNICODE
)
wideStr
=
(
LPWSTR
)
src
;
else
{
len
=
MultiByteToWideChar
(
srcCP
,
0
,
src
,
-
1
,
NULL
,
0
);
wideStr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
));
if
(
wideStr
)
MultiByteToWideChar
(
srcCP
,
0
,
src
,
-
1
,
wideStr
,
len
);
else
hr
=
STG_E_INSUFFICIENTMEMORY
;
}
if
(
SUCCEEDED
(
hr
))
{
len
=
WideCharToMultiByte
(
targetCP
,
0
,
wideStr
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
*
dst
=
CoTaskMemAlloc
(
len
);
if
(
!*
dst
)
hr
=
STG_E_INSUFFICIENTMEMORY
;
else
{
BOOL
defCharUsed
=
FALSE
;
if
(
WideCharToMultiByte
(
targetCP
,
0
,
wideStr
,
-
1
,
*
dst
,
len
,
NULL
,
&
defCharUsed
)
==
0
||
defCharUsed
)
{
CoTaskMemFree
(
*
dst
);
*
dst
=
NULL
;
hr
=
HRESULT_FROM_WIN32
(
ERROR_NO_UNICODE_TRANSLATION
);
}
}
}
if
(
wideStr
!=
(
LPWSTR
)
src
)
HeapFree
(
GetProcessHeap
(),
0
,
wideStr
);
}
}
TRACE
(
"returning 0x%08lx (%s)
\n
"
,
hr
,
targetCP
==
CP_UNICODE
?
debugstr_w
((
LPCWSTR
)
*
dst
)
:
debugstr_a
(
*
dst
));
return
hr
;
}
static
HRESULT
PropertyStorage_PropVariantCopy
(
PROPVARIANT
*
prop
,
const
PROPVARIANT
*
propvar
,
LCID
targetCP
,
LCID
srcCP
)
{
HRESULT
hr
=
S_OK
;
assert
(
prop
);
assert
(
propvar
);
if
(
propvar
->
vt
==
VT_LPSTR
)
{
hr
=
PropertyStorage_StringCopy
(
propvar
->
u
.
pszVal
,
&
prop
->
u
.
pszVal
,
targetCP
,
srcCP
);
if
(
SUCCEEDED
(
hr
))
prop
->
vt
=
VT_LPSTR
;
}
else
PropVariantCopy
(
prop
,
propvar
);
return
hr
;
}
/* Stores the property with id propid and value propvar into this property
* storage. lcid is ignored if propvar's type is not VT_LPSTR. If propvar's
* type is VT_LPSTR, converts the string using lcid as the source code page
* and This->codePage as the target code page before storing.
*/
static
HRESULT
PropertyStorage_StorePropWithId
(
PropertyStorage_impl
*
This
,
static
HRESULT
PropertyStorage_StorePropWithId
(
PropertyStorage_impl
*
This
,
PROPID
propid
,
const
PROPVARIANT
*
propvar
)
PROPID
propid
,
const
PROPVARIANT
*
propvar
,
LCID
lcid
)
{
{
HRESULT
hr
=
S_OK
;
HRESULT
hr
=
S_OK
;
PROPVARIANT
*
prop
=
PropertyStorage_FindProperty
(
This
,
propid
);
PROPVARIANT
*
prop
=
PropertyStorage_FindProperty
(
This
,
propid
);
...
@@ -307,7 +444,8 @@ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This,
...
@@ -307,7 +444,8 @@ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This,
if
(
prop
)
if
(
prop
)
{
{
PropVariantClear
(
prop
);
PropVariantClear
(
prop
);
PropVariantCopy
(
prop
,
propvar
);
hr
=
PropertyStorage_PropVariantCopy
(
prop
,
propvar
,
This
->
codePage
,
lcid
);
}
}
else
else
{
{
...
@@ -315,10 +453,16 @@ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This,
...
@@ -315,10 +453,16 @@ static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This,
sizeof
(
PROPVARIANT
));
sizeof
(
PROPVARIANT
));
if
(
prop
)
if
(
prop
)
{
{
PropVariantCopy
(
prop
,
propvar
);
hr
=
PropertyStorage_PropVariantCopy
(
prop
,
propvar
,
This
->
codePage
,
dictionary_insert
(
This
->
propid_to_prop
,
(
void
*
)
propid
,
prop
);
lcid
);
if
(
propid
>
This
->
highestProp
)
if
(
SUCCEEDED
(
hr
))
This
->
highestProp
=
propid
;
{
dictionary_insert
(
This
->
propid_to_prop
,
(
void
*
)
propid
,
prop
);
if
(
propid
>
This
->
highestProp
)
This
->
highestProp
=
propid
;
}
else
HeapFree
(
GetProcessHeap
(),
0
,
prop
);
}
}
else
else
hr
=
STG_E_INSUFFICIENTMEMORY
;
hr
=
STG_E_INSUFFICIENTMEMORY
;
...
@@ -383,7 +527,7 @@ static HRESULT WINAPI IPropertyStorage_fnWriteMultiple(
...
@@ -383,7 +527,7 @@ static HRESULT WINAPI IPropertyStorage_fnWriteMultiple(
dictionary_insert
(
This
->
propid_to_name
,
(
void
*
)
nextId
,
dictionary_insert
(
This
->
propid_to_name
,
(
void
*
)
nextId
,
name
);
name
);
hr
=
PropertyStorage_StorePropWithId
(
This
,
nextId
,
hr
=
PropertyStorage_StorePropWithId
(
This
,
nextId
,
&
rgpropvar
[
i
]);
&
rgpropvar
[
i
]
,
GetACP
()
);
}
}
}
}
}
}
...
@@ -419,7 +563,7 @@ static HRESULT WINAPI IPropertyStorage_fnWriteMultiple(
...
@@ -419,7 +563,7 @@ static HRESULT WINAPI IPropertyStorage_fnWriteMultiple(
hr
=
STG_E_INVALIDPARAMETER
;
hr
=
STG_E_INVALIDPARAMETER
;
else
else
hr
=
PropertyStorage_StorePropWithId
(
This
,
hr
=
PropertyStorage_StorePropWithId
(
This
,
rgpspec
[
i
].
u
.
propid
,
&
rgpropvar
[
i
]);
rgpspec
[
i
].
u
.
propid
,
&
rgpropvar
[
i
]
,
GetACP
()
);
}
}
}
}
}
}
...
@@ -541,16 +685,23 @@ static HRESULT WINAPI IPropertyStorage_fnWritePropertyNames(
...
@@ -541,16 +685,23 @@ static HRESULT WINAPI IPropertyStorage_fnWritePropertyNames(
hr
=
S_OK
;
hr
=
S_OK
;
EnterCriticalSection
(
&
This
->
cs
);
EnterCriticalSection
(
&
This
->
cs
);
This
->
dirty
=
TRUE
;
This
->
dirty
=
TRUE
;
for
(
i
=
0
;
i
<
cpropid
;
i
++
)
for
(
i
=
0
;
SUCCEEDED
(
hr
)
&&
i
<
cpropid
;
i
++
)
{
{
if
(
rgpropid
[
i
]
!=
PID_ILLEGAL
)
if
(
rgpropid
[
i
]
!=
PID_ILLEGAL
)
{
{
size_t
len
=
lstrlenW
(
rglpwstrName
[
i
])
+
1
;
size_t
len
=
lstrlenW
(
rglpwstrName
[
i
])
+
1
;
LPWSTR
name
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
));
LPWSTR
name
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
));
strcpyW
(
name
,
rglpwstrName
[
i
]);
if
(
name
)
dictionary_insert
(
This
->
name_to_propid
,
name
,
(
void
*
)
rgpropid
[
i
]);
{
dictionary_insert
(
This
->
propid_to_name
,
(
void
*
)
rgpropid
[
i
],
name
);
strcpyW
(
name
,
rglpwstrName
[
i
]);
dictionary_insert
(
This
->
name_to_propid
,
name
,
(
void
*
)
rgpropid
[
i
]);
dictionary_insert
(
This
->
propid_to_name
,
(
void
*
)
rgpropid
[
i
],
name
);
}
else
hr
=
STG_E_INSUFFICIENTMEMORY
;
}
}
}
}
if
(
This
->
grfFlags
&
PROPSETFLAG_UNBUFFERED
)
if
(
This
->
grfFlags
&
PROPSETFLAG_UNBUFFERED
)
...
@@ -879,8 +1030,9 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data)
...
@@ -879,8 +1030,9 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data)
{
{
/* FIXME: if the host is big-endian, this'll suck */
/* FIXME: if the host is big-endian, this'll suck */
memcpy
(
prop
->
u
.
pszVal
,
data
+
sizeof
(
DWORD
),
count
);
memcpy
(
prop
->
u
.
pszVal
,
data
+
sizeof
(
DWORD
),
count
);
/* FIXME: so far so good, but this may be Unicode or DBCS depending
/* This is stored in the code page specified in This->codePage.
* on This->codePage.
* Don't convert it, the caller will just store it as-is.
* (Note the trace will be misleading if the code page is Unicode.)
*/
*/
TRACE
(
"Read string value %s
\n
"
,
debugstr_a
(
prop
->
u
.
pszVal
));
TRACE
(
"Read string value %s
\n
"
,
debugstr_a
(
prop
->
u
.
pszVal
));
}
}
...
@@ -1160,7 +1312,7 @@ static HRESULT PropertyStorage_ReadFromStream(PropertyStorage_impl *This)
...
@@ -1160,7 +1312,7 @@ static HRESULT PropertyStorage_ReadFromStream(PropertyStorage_impl *This)
break
;
break
;
default:
default:
hr
=
PropertyStorage_StorePropWithId
(
This
,
hr
=
PropertyStorage_StorePropWithId
(
This
,
idOffset
->
propid
,
&
prop
);
idOffset
->
propid
,
&
prop
,
This
->
codePage
);
}
}
}
}
}
}
...
@@ -2106,12 +2258,12 @@ HRESULT WINAPI FmtIdToPropStgName(const FMTID *rfmtid, LPOLESTR str)
...
@@ -2106,12 +2258,12 @@ HRESULT WINAPI FmtIdToPropStgName(const FMTID *rfmtid, LPOLESTR str)
*/
*/
HRESULT
WINAPI
PropStgNameToFmtId
(
const
LPOLESTR
str
,
FMTID
*
rfmtid
)
HRESULT
WINAPI
PropStgNameToFmtId
(
const
LPOLESTR
str
,
FMTID
*
rfmtid
)
{
{
HRESULT
hr
=
E_INVALIDARG
;
HRESULT
hr
=
STG_E_INVALIDNAME
;
TRACE
(
"%s, %p
\n
"
,
debugstr_w
(
str
),
rfmtid
);
TRACE
(
"%s, %p
\n
"
,
debugstr_w
(
str
),
rfmtid
);
if
(
!
rfmtid
)
return
E_INVALIDARG
;
if
(
!
rfmtid
)
return
E_INVALIDARG
;
if
(
!
str
)
return
E_INVALIDARG
;
if
(
!
str
)
return
STG_E_INVALIDNAME
;
if
(
!
lstrcmpiW
(
str
,
szDocSummaryInfo
))
if
(
!
lstrcmpiW
(
str
,
szDocSummaryInfo
))
{
{
...
...
dlls/ole32/tests/stg_prop.c
View file @
bf83ba1f
...
@@ -211,12 +211,10 @@ static void testProps(void)
...
@@ -211,12 +211,10 @@ static void testProps(void)
/* revert it */
/* revert it */
hr
=
IPropertyStorage_Revert
(
propertyStorage
);
hr
=
IPropertyStorage_Revert
(
propertyStorage
);
ok
(
SUCCEEDED
(
hr
),
"Revert failed: 0x%08lx
\n
"
,
hr
);
ok
(
SUCCEEDED
(
hr
),
"Revert failed: 0x%08lx
\n
"
,
hr
);
/* and make sure it's still an integer */
/* Oddly enough, there's no guarantee that a successful revert actually
hr
=
IPropertyStorage_ReadMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
);
* implies the value wasn't saved. Maybe transactional mode needs to be
ok
(
SUCCEEDED
(
hr
),
"ReadMultiple failed: 0x%08lx
\n
"
,
hr
);
* used for that?
ok
(
var
.
vt
==
VT_I4
&&
U
(
var
).
lVal
==
1
,
*/
"Didn't get expected type or value for property (got type %d, value %ld)
\n
"
,
var
.
vt
,
U
(
var
).
lVal
);
IPropertyStorage_Release
(
propertyStorage
);
IPropertyStorage_Release
(
propertyStorage
);
propertyStorage
=
NULL
;
propertyStorage
=
NULL
;
...
@@ -260,6 +258,161 @@ static void testProps(void)
...
@@ -260,6 +258,161 @@ static void testProps(void)
DeleteFileW
(
filename
);
DeleteFileW
(
filename
);
}
}
void
testCodepage
(
void
)
{
static
const
WCHAR
szDot
[]
=
{
'.'
,
0
};
static
const
WCHAR
szPrefix
[]
=
{
's'
,
't'
,
'g'
,
0
};
static
const
WCHAR
wval
[]
=
{
'h'
,
'i'
,
0
};
HRESULT
hr
;
IStorage
*
storage
=
NULL
;
IPropertySetStorage
*
propSetStorage
=
NULL
;
IPropertyStorage
*
propertyStorage
=
NULL
;
PROPSPEC
spec
;
PROPVARIANT
var
;
WCHAR
fileName
[
MAX_PATH
];
if
(
!
GetTempFileNameW
(
szDot
,
szPrefix
,
0
,
fileName
))
return
;
hr
=
StgCreateDocfile
(
fileName
,
STGM_READWRITE
|
STGM_SHARE_EXCLUSIVE
|
STGM_CREATE
,
0
,
&
storage
);
ok
(
SUCCEEDED
(
hr
),
"StgCreateDocfile failed: 0x%08lx
\n
"
,
hr
);
hr
=
StgCreatePropSetStg
(
storage
,
0
,
&
propSetStorage
);
ok
(
SUCCEEDED
(
hr
),
"StgCreatePropSetStg failed: 0x%08lx
\n
"
,
hr
);
hr
=
IPropertySetStorage_Create
(
propSetStorage
,
&
FMTID_SummaryInformation
,
NULL
,
PROPSETFLAG_DEFAULT
,
STGM_READWRITE
|
STGM_CREATE
|
STGM_SHARE_EXCLUSIVE
,
&
propertyStorage
);
ok
(
SUCCEEDED
(
hr
),
"IPropertySetStorage_Create failed: 0x%08lx
\n
"
,
hr
);
PropVariantInit
(
&
var
);
spec
.
ulKind
=
PRSPEC_PROPID
;
U
(
spec
).
propid
=
PID_CODEPAGE
;
/* check code page before it's been explicitly set */
hr
=
IPropertyStorage_ReadMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
);
ok
(
SUCCEEDED
(
hr
),
"ReadMultiple failed: 0x%08lx
\n
"
,
hr
);
ok
(
var
.
vt
==
VT_I2
&&
U
(
var
).
iVal
==
1200
,
"Didn't get expected type or value for property
\n
"
);
/* Set the code page to ascii */
var
.
vt
=
VT_I2
;
U
(
var
).
iVal
=
1252
;
hr
=
IPropertyStorage_WriteMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
,
0
);
ok
(
SUCCEEDED
(
hr
),
"WriteMultiple failed: 0x%08lx
\n
"
,
hr
);
/* check code page */
hr
=
IPropertyStorage_ReadMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
);
ok
(
SUCCEEDED
(
hr
),
"ReadMultiple failed: 0x%08lx
\n
"
,
hr
);
ok
(
var
.
vt
==
VT_I2
&&
U
(
var
).
iVal
==
1252
,
"Didn't get expected type or value for property
\n
"
);
/* Set code page to Unicode */
U
(
var
).
iVal
=
1200
;
hr
=
IPropertyStorage_WriteMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
,
0
);
ok
(
SUCCEEDED
(
hr
),
"WriteMultiple failed: 0x%08lx
\n
"
,
hr
);
/* check code page */
hr
=
IPropertyStorage_ReadMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
);
ok
(
SUCCEEDED
(
hr
),
"ReadMultiple failed: 0x%08lx
\n
"
,
hr
);
ok
(
var
.
vt
==
VT_I2
&&
U
(
var
).
iVal
==
1200
,
"Didn't get expected type or value for property
\n
"
);
/* Set a string value */
spec
.
ulKind
=
PRSPEC_PROPID
;
U
(
spec
).
propid
=
PID_FIRST_USABLE
;
var
.
vt
=
VT_LPSTR
;
U
(
var
).
pszVal
=
"hi"
;
hr
=
IPropertyStorage_WriteMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
,
0
);
ok
(
SUCCEEDED
(
hr
),
"WriteMultiple failed: 0x%08lx
\n
"
,
hr
);
hr
=
IPropertyStorage_ReadMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
);
ok
(
SUCCEEDED
(
hr
),
"ReadMultiple failed: 0x%08lx
\n
"
,
hr
);
ok
(
var
.
vt
==
VT_LPSTR
&&
!
strcmp
(
U
(
var
).
pszVal
,
"hi"
),
"Didn't get expected type or value for property
\n
"
);
/* This seemingly non-sensical test is to show that the string is indeed
* interpreted according to the current system code page, not according to
* the property set's code page. (If the latter were true, the whole
* string would be maintained. As it is, only the first character is.)
*/
U
(
var
).
pszVal
=
(
LPSTR
)
wval
;
hr
=
IPropertyStorage_WriteMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
,
0
);
ok
(
SUCCEEDED
(
hr
),
"WriteMultiple failed: 0x%08lx
\n
"
,
hr
);
hr
=
IPropertyStorage_ReadMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
);
ok
(
SUCCEEDED
(
hr
),
"ReadMultiple failed: 0x%08lx
\n
"
,
hr
);
ok
(
var
.
vt
==
VT_LPSTR
&&
!
strcmp
(
U
(
var
).
pszVal
,
"h"
),
"Didn't get expected type or value for property
\n
"
);
/* now that a property's been set, you can't change the code page */
spec
.
ulKind
=
PRSPEC_PROPID
;
U
(
spec
).
propid
=
PID_CODEPAGE
;
var
.
vt
=
VT_I2
;
U
(
var
).
iVal
=
1200
;
hr
=
IPropertyStorage_WriteMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
,
0
);
ok
(
hr
==
STG_E_INVALIDPARAMETER
,
"Expected STG_E_INVALIDPARAMETER, got 0x%08lx
\n
"
,
hr
);
IPropertyStorage_Release
(
propertyStorage
);
IPropertySetStorage_Release
(
propSetStorage
);
IStorage_Release
(
storage
);
DeleteFileW
(
fileName
);
/* same tests, but with PROPSETFLAG_ANSI */
hr
=
StgCreateDocfile
(
fileName
,
STGM_READWRITE
|
STGM_SHARE_EXCLUSIVE
|
STGM_CREATE
,
0
,
&
storage
);
ok
(
SUCCEEDED
(
hr
),
"StgCreateDocfile failed: 0x%08lx
\n
"
,
hr
);
hr
=
StgCreatePropSetStg
(
storage
,
0
,
&
propSetStorage
);
ok
(
SUCCEEDED
(
hr
),
"StgCreatePropSetStg failed: 0x%08lx
\n
"
,
hr
);
hr
=
IPropertySetStorage_Create
(
propSetStorage
,
&
FMTID_SummaryInformation
,
NULL
,
PROPSETFLAG_ANSI
,
STGM_READWRITE
|
STGM_CREATE
|
STGM_SHARE_EXCLUSIVE
,
&
propertyStorage
);
ok
(
SUCCEEDED
(
hr
),
"IPropertySetStorage_Create failed: 0x%08lx
\n
"
,
hr
);
/* check code page before it's been explicitly set */
hr
=
IPropertyStorage_ReadMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
);
ok
(
SUCCEEDED
(
hr
),
"ReadMultiple failed: 0x%08lx
\n
"
,
hr
);
ok
(
var
.
vt
==
VT_I2
&&
U
(
var
).
iVal
==
1252
,
"Didn't get expected type or value for property
\n
"
);
/* Set code page to Unicode */
U
(
var
).
iVal
=
1200
;
hr
=
IPropertyStorage_WriteMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
,
0
);
ok
(
SUCCEEDED
(
hr
),
"WriteMultiple failed: 0x%08lx
\n
"
,
hr
);
/* check code page */
hr
=
IPropertyStorage_ReadMultiple
(
propertyStorage
,
1
,
&
spec
,
&
var
);
ok
(
SUCCEEDED
(
hr
),
"ReadMultiple failed: 0x%08lx
\n
"
,
hr
);
ok
(
var
.
vt
==
VT_I2
&&
U
(
var
).
iVal
==
1200
,
"Didn't get expected type or value for property
\n
"
);
/* This test is commented out for documentation. It fails under Wine,
* and I expect it would under Windows as well, yet it succeeds. There's
* obviously something about string conversion I don't understand.
*/
#if 0
static const char strVal[] = { 0x81, 0xff, 0x04, 0 };
/* Set code page to 950 (Traditional Chinese) */
U(var).iVal = 950;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var, 0);
ok(SUCCEEDED(hr), "WriteMultiple failed: 0x%08lx\n", hr);
/* Try writing an invalid string: lead byte 0x81 is unused in Traditional
* Chinese.
*/
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PID_FIRST_USABLE;
var.vt = VT_LPSTR;
U(var).pszVal = (LPSTR)strVal;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var, 0);
ok(SUCCEEDED(hr), "WriteMultiple failed: 0x%08lx\n", hr);
/* Check returned string */
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(SUCCEEDED(hr), "ReadMultiple failed: 0x%08lx\n", hr);
ok(var.vt == VT_LPSTR && !strcmp(U(var).pszVal, strVal),
"Didn't get expected type or value for property\n");
#endif
IPropertyStorage_Release
(
propertyStorage
);
IPropertySetStorage_Release
(
propSetStorage
);
IStorage_Release
(
storage
);
DeleteFileW
(
fileName
);
}
static
void
testFmtId
(
void
)
static
void
testFmtId
(
void
)
{
{
WCHAR
szSummaryInfo
[]
=
{
5
,
'S'
,
'u'
,
'm'
,
'm'
,
'a'
,
'r'
,
'y'
,
WCHAR
szSummaryInfo
[]
=
{
5
,
'S'
,
'u'
,
'm'
,
'm'
,
'a'
,
'r'
,
'y'
,
...
@@ -302,7 +455,8 @@ static void testFmtId(void)
...
@@ -302,7 +455,8 @@ static void testFmtId(void)
hr
=
pPropStgNameToFmtId
(
NULL
,
NULL
);
hr
=
pPropStgNameToFmtId
(
NULL
,
NULL
);
ok
(
hr
==
E_INVALIDARG
,
"Expected E_INVALIDARG, got 0x%08lx
\n
"
,
hr
);
ok
(
hr
==
E_INVALIDARG
,
"Expected E_INVALIDARG, got 0x%08lx
\n
"
,
hr
);
hr
=
pPropStgNameToFmtId
(
NULL
,
&
fmtid
);
hr
=
pPropStgNameToFmtId
(
NULL
,
&
fmtid
);
ok
(
hr
==
E_INVALIDARG
,
"Expected E_INVALIDARG, got 0x%08lx
\n
"
,
hr
);
ok
(
hr
==
STG_E_INVALIDNAME
,
"Expected STG_E_INVALIDNAME, got 0x%08lx
\n
"
,
hr
);
hr
=
pPropStgNameToFmtId
(
szDocSummaryInfo
,
NULL
);
hr
=
pPropStgNameToFmtId
(
szDocSummaryInfo
,
NULL
);
ok
(
hr
==
E_INVALIDARG
,
"Expected E_INVALIDARG, got 0x%08lx
\n
"
,
hr
);
ok
(
hr
==
E_INVALIDARG
,
"Expected E_INVALIDARG, got 0x%08lx
\n
"
,
hr
);
/* test the known format IDs */
/* test the known format IDs */
...
@@ -337,5 +491,6 @@ START_TEST(stg_prop)
...
@@ -337,5 +491,6 @@ START_TEST(stg_prop)
{
{
init_function_pointers
();
init_function_pointers
();
testProps
();
testProps
();
testCodepage
();
testFmtId
();
testFmtId
();
}
}
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