mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
[OLE32_WINETEST]
* Sync with Wine 1.7.27. CORE-8540 svn path=/trunk/; revision=64492
This commit is contained in:
parent
9fd8bd9a43
commit
087773e117
4 changed files with 630 additions and 9 deletions
|
@ -50,12 +50,15 @@ static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
|
|||
static HRESULT (WINAPI * pCoGetObjectContext)(REFIID riid, LPVOID *ppv);
|
||||
static HRESULT (WINAPI * pCoSwitchCallContext)(IUnknown *pObject, IUnknown **ppOldObject);
|
||||
static HRESULT (WINAPI * pCoGetTreatAsClass)(REFCLSID clsidOld, LPCLSID pClsidNew);
|
||||
static HRESULT (WINAPI * pCoTreatAsClass)(REFCLSID clsidOld, REFCLSID pClsidNew);
|
||||
static HRESULT (WINAPI * pCoGetContextToken)(ULONG_PTR *token);
|
||||
static LONG (WINAPI * pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
|
||||
static LONG (WINAPI * pRegOverridePredefKey)(HKEY key, HKEY override);
|
||||
|
||||
static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
|
||||
static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
|
||||
static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
|
||||
static BOOL (WINAPI *pIsWow64Process)(HANDLE, LPBOOL);
|
||||
static void (WINAPI *pReleaseActCtx)(HANDLE);
|
||||
|
||||
#define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
|
||||
|
@ -1057,6 +1060,8 @@ static void test_CoGetPSClsid(void)
|
|||
CLSID clsid;
|
||||
HKEY hkey;
|
||||
LONG res;
|
||||
const BOOL is_win64 = (sizeof(void*) != sizeof(int));
|
||||
BOOL is_wow64 = FALSE;
|
||||
|
||||
hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
|
||||
ok(hr == CO_E_NOTINITIALIZED,
|
||||
|
@ -1140,6 +1145,43 @@ static void test_CoGetPSClsid(void)
|
|||
pReleaseActCtx(handle);
|
||||
}
|
||||
|
||||
if (pRegDeleteKeyExA &&
|
||||
(is_win64 ||
|
||||
(pIsWow64Process && pIsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
|
||||
{
|
||||
static GUID IID_DeadBeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
|
||||
static const char clsidDeadBeef[] = "{deadbeef-dead-beef-dead-beefdeadbeef}";
|
||||
static const char clsidA[] = "{66666666-8888-7777-6666-555555555555}";
|
||||
HKEY hkey_iface, hkey_psclsid;
|
||||
REGSAM opposite = is_win64 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
|
||||
|
||||
hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
|
||||
ok(hr == REGDB_E_IIDNOTREG, "got 0x%08x\n", hr);
|
||||
|
||||
res = RegCreateKeyExA(HKEY_CLASSES_ROOT, "Interface",
|
||||
0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_iface, NULL);
|
||||
ok(!res, "RegCreateKeyEx returned %d\n", res);
|
||||
res = RegCreateKeyExA(hkey_iface, clsidDeadBeef,
|
||||
0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey, NULL);
|
||||
ok(!res, "RegCreateKeyEx returned %d\n", res);
|
||||
res = RegCreateKeyExA(hkey, "ProxyStubClsid32",
|
||||
0, NULL, 0, KEY_ALL_ACCESS | opposite, NULL, &hkey_psclsid, NULL);
|
||||
res = RegSetValueExA(hkey_psclsid, NULL, 0, REG_SZ, (const BYTE *)clsidA, strlen(clsidA)+1);
|
||||
ok(!res, "RegSetValueEx returned %d\n", res);
|
||||
RegCloseKey(hkey_psclsid);
|
||||
|
||||
hr = CoGetPSClsid(&IID_DeadBeef, &clsid);
|
||||
ok_ole_success(hr, "CoGetPSClsid");
|
||||
ok(IsEqualGUID(&clsid, &IID_TestPS), "got clsid %s\n", wine_dbgstr_guid(&clsid));
|
||||
|
||||
res = pRegDeleteKeyExA(hkey, "ProxyStubClsid32", opposite, 0);
|
||||
ok(!res, "RegDeleteKeyEx returned %d\n", res);
|
||||
RegCloseKey(hkey);
|
||||
res = pRegDeleteKeyExA(hkey_iface, clsidDeadBeef, opposite, 0);
|
||||
ok(!res, "RegDeleteKeyEx returned %d\n", res);
|
||||
RegCloseKey(hkey_iface);
|
||||
}
|
||||
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
|
@ -1905,11 +1947,15 @@ static void test_CoGetContextToken(void)
|
|||
CoUninitialize();
|
||||
}
|
||||
|
||||
static void test_CoGetTreatAsClass(void)
|
||||
static void test_TreatAsClass(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
CLSID out;
|
||||
static GUID deadbeef = {0xdeadbeef,0xdead,0xbeef,{0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}};
|
||||
static const char deadbeefA[] = "{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF}";
|
||||
IInternetProtocol *pIP = NULL;
|
||||
HKEY clsidkey, deadbeefkey;
|
||||
LONG lr;
|
||||
|
||||
if (!pCoGetTreatAsClass)
|
||||
{
|
||||
|
@ -1919,6 +1965,63 @@ static void test_CoGetTreatAsClass(void)
|
|||
hr = pCoGetTreatAsClass(&deadbeef,&out);
|
||||
ok (hr == S_FALSE, "expected S_FALSE got %x\n",hr);
|
||||
ok (IsEqualGUID(&out,&deadbeef), "expected to get same clsid back\n");
|
||||
|
||||
lr = RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_READ, &clsidkey);
|
||||
ok(lr == ERROR_SUCCESS, "Couldn't open CLSID key\n");
|
||||
|
||||
lr = RegCreateKeyExA(clsidkey, deadbeefA, 0, NULL, 0, KEY_WRITE, NULL, &deadbeefkey, NULL);
|
||||
ok(lr == ERROR_SUCCESS, "Couldn't create class key\n");
|
||||
|
||||
hr = pCoTreatAsClass(&deadbeef, &deadbeef);
|
||||
ok(hr == REGDB_E_WRITEREGDB, "CoTreatAsClass gave wrong error: %08x\n", hr);
|
||||
|
||||
hr = pCoTreatAsClass(&deadbeef, &CLSID_FileProtocol);
|
||||
if(hr == REGDB_E_WRITEREGDB){
|
||||
win_skip("Insufficient privileges to use CoTreatAsClass\n");
|
||||
goto exit;
|
||||
}
|
||||
ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
|
||||
|
||||
hr = pCoGetTreatAsClass(&deadbeef, &out);
|
||||
ok(hr == S_OK, "CoGetTreatAsClass failed: %08x\n",hr);
|
||||
ok(IsEqualGUID(&out, &CLSID_FileProtocol), "expected to get substituted clsid\n");
|
||||
|
||||
OleInitialize(NULL);
|
||||
|
||||
hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
|
||||
if(hr == REGDB_E_CLASSNOTREG)
|
||||
{
|
||||
win_skip("IE not installed so can't test CoCreateInstance\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr);
|
||||
if(pIP){
|
||||
IInternetProtocol_Release(pIP);
|
||||
pIP = NULL;
|
||||
}
|
||||
|
||||
hr = pCoTreatAsClass(&deadbeef, &CLSID_NULL);
|
||||
ok(hr == S_OK, "CoTreatAsClass failed: %08x\n", hr);
|
||||
|
||||
hr = pCoGetTreatAsClass(&deadbeef, &out);
|
||||
ok(hr == S_FALSE, "expected S_FALSE got %08x\n", hr);
|
||||
ok(IsEqualGUID(&out, &deadbeef), "expected to get same clsid back\n");
|
||||
|
||||
/* bizarrely, native's CoTreatAsClass takes some time to take effect in CoCreateInstance */
|
||||
Sleep(200);
|
||||
|
||||
hr = CoCreateInstance(&deadbeef, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void **)&pIP);
|
||||
ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance gave wrong error: %08x\n", hr);
|
||||
|
||||
if(pIP)
|
||||
IInternetProtocol_Release(pIP);
|
||||
|
||||
exit:
|
||||
OleUninitialize();
|
||||
RegCloseKey(deadbeefkey);
|
||||
RegDeleteKeyA(clsidkey, deadbeefA);
|
||||
RegCloseKey(clsidkey);
|
||||
}
|
||||
|
||||
static void test_CoInitializeEx(void)
|
||||
|
@ -1986,6 +2089,14 @@ static void test_OleRegGetMiscStatus(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void test_CoCreateGuid(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hr = CoCreateGuid(NULL);
|
||||
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
|
||||
}
|
||||
|
||||
static void init_funcs(void)
|
||||
{
|
||||
HMODULE hOle32 = GetModuleHandleA("ole32");
|
||||
|
@ -1995,13 +2106,16 @@ static void init_funcs(void)
|
|||
pCoGetObjectContext = (void*)GetProcAddress(hOle32, "CoGetObjectContext");
|
||||
pCoSwitchCallContext = (void*)GetProcAddress(hOle32, "CoSwitchCallContext");
|
||||
pCoGetTreatAsClass = (void*)GetProcAddress(hOle32,"CoGetTreatAsClass");
|
||||
pCoTreatAsClass = (void*)GetProcAddress(hOle32,"CoTreatAsClass");
|
||||
pCoGetContextToken = (void*)GetProcAddress(hOle32, "CoGetContextToken");
|
||||
pRegDeleteKeyExA = (void*)GetProcAddress(hAdvapi32, "RegDeleteKeyExA");
|
||||
pRegOverridePredefKey = (void*)GetProcAddress(hAdvapi32, "RegOverridePredefKey");
|
||||
pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx");
|
||||
|
||||
pActivateActCtx = (void*)GetProcAddress(hkernel32, "ActivateActCtx");
|
||||
pCreateActCtxW = (void*)GetProcAddress(hkernel32, "CreateActCtxW");
|
||||
pDeactivateActCtx = (void*)GetProcAddress(hkernel32, "DeactivateActCtx");
|
||||
pIsWow64Process = (void*)GetProcAddress(hkernel32, "IsWow64Process");
|
||||
pReleaseActCtx = (void*)GetProcAddress(hkernel32, "ReleaseActCtx");
|
||||
}
|
||||
|
||||
|
@ -2039,7 +2153,8 @@ START_TEST(compobj)
|
|||
test_CoGetObjectContext();
|
||||
test_CoGetCallContext();
|
||||
test_CoGetContextToken();
|
||||
test_CoGetTreatAsClass();
|
||||
test_TreatAsClass();
|
||||
test_CoInitializeEx();
|
||||
test_OleRegGetMiscStatus();
|
||||
test_CoCreateGuid();
|
||||
}
|
||||
|
|
|
@ -266,14 +266,17 @@ static void test_streamonhglobal(IStream *pStream)
|
|||
ok(ull.u.LowPart == 0x80000008, "should have set LowPart to 0x80000008 instead of %08x\n", ull.u.LowPart);
|
||||
ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);
|
||||
|
||||
/* IStream_Seek -- seek wraps position/size on integer overflow */
|
||||
/* IStream_Seek -- seek wraps position/size on integer overflow, but not on win8 */
|
||||
ull.u.HighPart = 0xCAFECAFE;
|
||||
ull.u.LowPart = 0xCAFECAFE;
|
||||
ll.u.HighPart = 0;
|
||||
ll.u.LowPart = 0x7FFFFFFF;
|
||||
hr = IStream_Seek(pStream, ll, STREAM_SEEK_CUR, &ull);
|
||||
ok_ole_success(hr, "IStream_Seek");
|
||||
ok(ull.u.LowPart == 0x00000007, "should have set LowPart to 0x00000007 instead of %08x\n", ull.u.LowPart);
|
||||
ok(hr == S_OK || hr == STG_E_SEEKERROR /* win8 */, "IStream_Seek\n");
|
||||
if (SUCCEEDED(hr))
|
||||
ok(ull.u.LowPart == 0x00000007, "should have set LowPart to 0x00000007 instead of %08x\n", ull.u.LowPart);
|
||||
else
|
||||
ok(ull.u.LowPart == 0x80000008, "should have set LowPart to 0x80000008 instead of %08x\n", ull.u.LowPart);
|
||||
ok(ull.u.HighPart == 0, "should have set HighPart to 0 instead of %d\n", ull.u.HighPart);
|
||||
|
||||
hr = IStream_Commit(pStream, STGC_DEFAULT);
|
||||
|
|
|
@ -61,11 +61,11 @@ static const struct valid_mapping
|
|||
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_CY */
|
||||
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_DATE */
|
||||
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_BSTR */
|
||||
{ PROP_V1 | PROP_TODO , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DISPATCH */
|
||||
{ PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DISPATCH */
|
||||
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_ERROR */
|
||||
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_BOOL */
|
||||
{ PROP_V1 | PROP_TODO , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_VARIANT */
|
||||
{ PROP_V1 | PROP_TODO , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UNKNOWN */
|
||||
{ PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UNKNOWN */
|
||||
{ PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DECIMAL */
|
||||
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 15 */
|
||||
{ PROP_V1 , PROP_V1 | PROP_TODO , PROP_V1 , PROP_V1 | PROP_TODO }, /* VT_I1 */
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
//#include <stdio.h>
|
||||
|
||||
#define COBJMACROS
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
|
||||
//#include <windows.h>
|
||||
#include <wine/test.h>
|
||||
|
@ -870,11 +872,9 @@ static void test_storage_refcount(void)
|
|||
r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stgprio);
|
||||
ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
|
||||
|
||||
todo_wine {
|
||||
/* non-transacted mode read/write fails */
|
||||
r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
|
||||
ok(r==STG_E_LOCKVIOLATION, "StgOpenStorage should return STG_E_LOCKVIOLATION instead of 0x%08x\n", r);
|
||||
}
|
||||
|
||||
/* non-transacted mode read-only succeeds */
|
||||
r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE|STGM_READ, NULL, 0, &stg);
|
||||
|
@ -3146,6 +3146,506 @@ if (hr == S_OK) {
|
|||
DeleteFileW(fileW);
|
||||
}
|
||||
|
||||
struct lock_test
|
||||
{
|
||||
DWORD stg_mode;
|
||||
BOOL create;
|
||||
DWORD access;
|
||||
DWORD sharing;
|
||||
const int *locked_bytes;
|
||||
const int *fail_ranges;
|
||||
BOOL todo;
|
||||
};
|
||||
|
||||
static const int priority_locked_bytes[] = { 0x58, 0x81, 0x93, -1 };
|
||||
static const int rwex_locked_bytes[] = { 0x93, 0xa7, 0xbb, 0xcf, -1 };
|
||||
static const int rw_locked_bytes[] = { 0x93, 0xa7, -1 };
|
||||
static const int nosn_locked_bytes[] = { 0x6c, 0x93, 0xa7, 0xcf, -1 };
|
||||
static const int rwdw_locked_bytes[] = { 0x93, 0xa7, 0xcf, -1 };
|
||||
static const int wodw_locked_bytes[] = { 0xa7, 0xcf, -1 };
|
||||
static const int tr_locked_bytes[] = { 0x93, -1 };
|
||||
static const int no_locked_bytes[] = { -1 };
|
||||
static const int roex_locked_bytes[] = { 0x93, 0xbb, 0xcf, -1 };
|
||||
|
||||
static const int rwex_fail_ranges[] = { 0x93,0xe3, -1 };
|
||||
static const int rw_fail_ranges[] = { 0xbb,0xe3, -1 };
|
||||
static const int rwdw_fail_ranges[] = { 0xa7,0xe3, -1 };
|
||||
static const int dw_fail_ranges[] = { 0xa7,0xcf, -1 };
|
||||
static const int tr_fail_ranges[] = { 0xbb,0xcf, -1 };
|
||||
static const int pr_fail_ranges[] = { 0x80,0x81, 0xbb,0xcf, -1 };
|
||||
static const int roex_fail_ranges[] = { 0x0,-1 };
|
||||
|
||||
static const struct lock_test lock_tests[] = {
|
||||
{ STGM_PRIORITY, FALSE, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, priority_locked_bytes, pr_fail_ranges, FALSE },
|
||||
{ STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwex_locked_bytes, 0, FALSE },
|
||||
{ STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE|STGM_TRANSACTED, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwex_locked_bytes, 0, FALSE },
|
||||
{ STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, rw_locked_bytes, 0, FALSE },
|
||||
{ STGM_CREATE|STGM_READWRITE|STGM_SHARE_DENY_WRITE|STGM_TRANSACTED, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwdw_locked_bytes, 0, FALSE },
|
||||
{ STGM_CREATE|STGM_WRITE|STGM_SHARE_DENY_WRITE|STGM_TRANSACTED, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, wodw_locked_bytes, 0, FALSE },
|
||||
{ STGM_SHARE_EXCLUSIVE|STGM_READWRITE, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwex_locked_bytes, rwex_fail_ranges, FALSE },
|
||||
{ STGM_SHARE_EXCLUSIVE|STGM_READWRITE|STGM_TRANSACTED, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwex_locked_bytes, rwex_fail_ranges, FALSE },
|
||||
{ STGM_READWRITE|STGM_TRANSACTED, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, rw_locked_bytes, rw_fail_ranges, FALSE },
|
||||
{ STGM_READWRITE|STGM_TRANSACTED|STGM_NOSNAPSHOT, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, nosn_locked_bytes, rwdw_fail_ranges, FALSE },
|
||||
{ STGM_READWRITE|STGM_TRANSACTED|STGM_SHARE_DENY_WRITE, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwdw_locked_bytes, rwdw_fail_ranges, FALSE },
|
||||
{ STGM_READ|STGM_SHARE_DENY_WRITE, FALSE, GENERIC_READ, FILE_SHARE_READ, no_locked_bytes, dw_fail_ranges, TRUE },
|
||||
{ STGM_READ|STGM_TRANSACTED, FALSE, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, tr_locked_bytes, tr_fail_ranges, FALSE },
|
||||
{ STGM_READ|STGM_SHARE_EXCLUSIVE, FALSE, GENERIC_READ, FILE_SHARE_READ, roex_locked_bytes, roex_fail_ranges, TRUE },
|
||||
{ STGM_READ|STGM_SHARE_EXCLUSIVE|STGM_TRANSACTED, FALSE, GENERIC_READ, FILE_SHARE_READ, roex_locked_bytes, roex_fail_ranges, TRUE },
|
||||
};
|
||||
|
||||
static BOOL can_open(LPCWSTR filename, DWORD access, DWORD sharing)
|
||||
{
|
||||
HANDLE hfile;
|
||||
|
||||
hfile = CreateFileW(filename, access, sharing, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hfile == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
|
||||
CloseHandle(hfile);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void check_sharing(LPCWSTR filename, const struct lock_test *current,
|
||||
DWORD access, DWORD sharing, const char *desc, DWORD *open_mode, BOOL *any_failure)
|
||||
{
|
||||
if (can_open(filename, access, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE))
|
||||
{
|
||||
*open_mode = access;
|
||||
if (!current->todo || (current->sharing & sharing))
|
||||
ok(current->sharing & sharing ||
|
||||
broken(!(current->sharing & sharing) && access == GENERIC_WRITE && (current->stg_mode & 0xf) != STGM_READ) /* win2k */,
|
||||
"file with mode %x should not be openable with %s permission\n", current->stg_mode, desc);
|
||||
else
|
||||
{
|
||||
todo_wine ok(current->sharing & sharing ||
|
||||
broken(!(current->sharing & sharing) && access == GENERIC_WRITE && (current->stg_mode & 0xf) != STGM_READ) /* win2k */,
|
||||
"file with mode %x should not be openable with %s permission\n", current->stg_mode, desc);
|
||||
*any_failure = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!current->todo || !(current->sharing & sharing))
|
||||
ok(!(current->sharing & sharing), "file with mode %x should be openable with %s permission\n", current->stg_mode, desc);
|
||||
else
|
||||
{
|
||||
todo_wine ok(!(current->sharing & sharing), "file with mode %x should be openable with %s permission\n", current->stg_mode, desc);
|
||||
*any_failure = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void check_access(LPCWSTR filename, const struct lock_test *current,
|
||||
DWORD access, DWORD sharing, const char *desc, DWORD open_mode, BOOL *any_failure)
|
||||
{
|
||||
if (can_open(filename, open_mode, (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE) & ~sharing))
|
||||
{
|
||||
if (!current->todo || !(current->access & access))
|
||||
ok(!(current->access & access), "file with mode %x should not be openable without %s sharing\n", current->stg_mode, desc);
|
||||
else
|
||||
{
|
||||
todo_wine ok(!(current->access & access), "file with mode %x should not be openable without %s sharing\n", current->stg_mode, desc);
|
||||
*any_failure = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!current->todo || (current->access & access))
|
||||
ok(current->access & access, "file with mode %x should be openable without %s sharing\n", current->stg_mode, desc);
|
||||
else
|
||||
{
|
||||
todo_wine ok(current->access & access, "file with mode %x should be openable without %s sharing\n", current->stg_mode, desc);
|
||||
*any_failure = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_locking(void)
|
||||
{
|
||||
static const WCHAR filename[] = {'w','i','n','e','t','e','s','t',0};
|
||||
int i;
|
||||
IStorage *stg;
|
||||
HRESULT hr;
|
||||
|
||||
for (i=0; i<sizeof(lock_tests)/sizeof(lock_tests[0]); i++)
|
||||
{
|
||||
const struct lock_test *current = &lock_tests[i];
|
||||
BOOL any_failure = FALSE;
|
||||
DWORD open_mode = 0;
|
||||
|
||||
if (current->create)
|
||||
{
|
||||
hr = StgCreateDocfile(filename, current->stg_mode, 0, &stg);
|
||||
ok(SUCCEEDED(hr), "StgCreateDocfile with mode %x failed with hr %x\n", current->stg_mode, hr);
|
||||
if (FAILED(hr)) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = StgCreateDocfile(filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
|
||||
ok(SUCCEEDED(hr), "StgCreateDocfile failed with hr %x\n", hr);
|
||||
if (FAILED(hr)) continue;
|
||||
IStorage_Release(stg);
|
||||
|
||||
hr = StgOpenStorage(filename, NULL, current->stg_mode, NULL, 0, &stg);
|
||||
ok(SUCCEEDED(hr), "StgOpenStorage with mode %x failed with hr %x\n", current->stg_mode, hr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
DeleteFileW(filename);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
check_sharing(filename, current, GENERIC_READ, FILE_SHARE_READ, "READ", &open_mode, &any_failure);
|
||||
check_sharing(filename, current, GENERIC_WRITE, FILE_SHARE_WRITE, "WRITE", &open_mode, &any_failure);
|
||||
check_sharing(filename, current, DELETE, FILE_SHARE_DELETE, "DELETE", &open_mode, &any_failure);
|
||||
|
||||
if (open_mode != 0)
|
||||
{
|
||||
HANDLE hfile;
|
||||
BOOL locked, expect_locked;
|
||||
OVERLAPPED ol;
|
||||
const int* next_lock = current->locked_bytes;
|
||||
|
||||
check_access(filename, current, GENERIC_READ, FILE_SHARE_READ, "READ", open_mode, &any_failure);
|
||||
check_access(filename, current, GENERIC_WRITE, FILE_SHARE_WRITE, "WRITE", open_mode, &any_failure);
|
||||
check_access(filename, current, DELETE, FILE_SHARE_DELETE, "DELETE", open_mode, &any_failure);
|
||||
|
||||
hfile = CreateFileW(filename, open_mode, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ok(hfile != INVALID_HANDLE_VALUE, "couldn't open file with mode %x\n", current->stg_mode);
|
||||
|
||||
ol.u.s.OffsetHigh = 0;
|
||||
ol.hEvent = NULL;
|
||||
|
||||
for (ol.u.s.Offset = 0x7fffff00; ol.u.s.Offset != 0x80000000; ol.u.s.Offset++)
|
||||
{
|
||||
if (LockFileEx(hfile, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &ol))
|
||||
locked = FALSE;
|
||||
else
|
||||
{
|
||||
ok(!LockFileEx(hfile, LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &ol), "shared locks should not be used\n");
|
||||
locked = TRUE;
|
||||
}
|
||||
|
||||
UnlockFileEx(hfile, 0, 1, 0, &ol);
|
||||
|
||||
if ((ol.u.s.Offset&0xff) == *next_lock)
|
||||
{
|
||||
expect_locked = TRUE;
|
||||
next_lock++;
|
||||
}
|
||||
else
|
||||
expect_locked = FALSE;
|
||||
|
||||
if (!current->todo || locked == expect_locked)
|
||||
ok(locked == expect_locked, "byte %x of file with mode %x is %slocked but should %sbe\n",
|
||||
ol.u.s.Offset, current->stg_mode, locked?"":"not ", expect_locked?"":"not ");
|
||||
else
|
||||
{
|
||||
any_failure = TRUE;
|
||||
todo_wine ok(locked == expect_locked, "byte %x of file with mode %x is %slocked but should %sbe\n",
|
||||
ol.u.s.Offset, current->stg_mode, locked?"":"not ", expect_locked?"":"not ");
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hfile);
|
||||
}
|
||||
|
||||
IStorage_Release( stg );
|
||||
|
||||
if (!current->create)
|
||||
{
|
||||
HANDLE hfile;
|
||||
BOOL failed, expect_failed=FALSE;
|
||||
OVERLAPPED ol;
|
||||
const int* next_range = current->fail_ranges;
|
||||
|
||||
hfile = CreateFileW(filename, open_mode, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ok(hfile != INVALID_HANDLE_VALUE, "couldn't open file with mode %x\n", current->stg_mode);
|
||||
|
||||
ol.u.s.OffsetHigh = 0;
|
||||
ol.hEvent = NULL;
|
||||
|
||||
for (ol.u.s.Offset = 0x7fffff00; ol.u.s.Offset != 0x80000000; ol.u.s.Offset++)
|
||||
{
|
||||
if (ol.u.s.Offset == 0x7fffff92 ||
|
||||
(ol.u.s.Offset == 0x7fffff80 && current->stg_mode == (STGM_TRANSACTED|STGM_READWRITE)) ||
|
||||
(ol.u.s.Offset == 0x7fffff80 && current->stg_mode == (STGM_TRANSACTED|STGM_READ)))
|
||||
continue; /* This makes opens hang */
|
||||
|
||||
LockFileEx(hfile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ol);
|
||||
|
||||
hr = StgOpenStorage(filename, NULL, current->stg_mode, NULL, 0, &stg);
|
||||
ok(hr == S_OK || hr == STG_E_LOCKVIOLATION || hr == STG_E_SHAREVIOLATION, "failed with unexpected hr %x\n", hr);
|
||||
if (SUCCEEDED(hr)) IStorage_Release(stg);
|
||||
|
||||
UnlockFileEx(hfile, 0, 1, 0, &ol);
|
||||
|
||||
failed = FAILED(hr);
|
||||
|
||||
if (!expect_failed && (ol.u.s.Offset&0xff) == next_range[0])
|
||||
{
|
||||
expect_failed = TRUE;
|
||||
}
|
||||
else if (expect_failed && (ol.u.s.Offset&0xff) == next_range[1])
|
||||
{
|
||||
expect_failed = FALSE;
|
||||
next_range += 2;
|
||||
}
|
||||
|
||||
if (!current->todo || failed == expect_failed)
|
||||
ok(failed == expect_failed, "open with byte %x locked, mode %x %s but should %s\n",
|
||||
ol.u.s.Offset, current->stg_mode, failed?"failed":"succeeded", expect_failed?"fail":"succeed");
|
||||
else
|
||||
{
|
||||
any_failure = TRUE;
|
||||
todo_wine ok(failed == expect_failed, "open with byte %x locked, mode %x %s but should %s\n",
|
||||
ol.u.s.Offset, current->stg_mode, failed?"failed":"succeeded", expect_failed?"fail":"succeed");
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hfile);
|
||||
}
|
||||
|
||||
DeleteFileW(filename);
|
||||
|
||||
if (current->todo && !any_failure)
|
||||
todo_wine ok(1, "tests succeeded for mode %x\n", current->stg_mode);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_transacted_shared(void)
|
||||
{
|
||||
IStorage *stg = NULL;
|
||||
IStorage *stgrw = NULL;
|
||||
HRESULT r;
|
||||
IStream *stm = NULL;
|
||||
static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
|
||||
LARGE_INTEGER pos;
|
||||
ULARGE_INTEGER upos;
|
||||
char buffer[10];
|
||||
ULONG bytesread;
|
||||
|
||||
DeleteFileA(filenameA);
|
||||
|
||||
/* create a new transacted storage with a stream */
|
||||
r = StgCreateDocfile(filename, STGM_CREATE |
|
||||
STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
|
||||
ok(r==S_OK, "StgCreateDocfile failed %x\n", r);
|
||||
|
||||
r = WriteClassStg(stg, &test_stg_cls);
|
||||
ok(r == S_OK, "WriteClassStg failed %x\n", r);
|
||||
|
||||
r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
|
||||
ok(r==S_OK, "IStorage->CreateStream failed %x\n", r);
|
||||
|
||||
pos.QuadPart = 0;
|
||||
r = IStream_Seek(stm, pos, 0, &upos);
|
||||
ok(r==S_OK, "IStream->Seek failed %x\n", r);
|
||||
|
||||
r = IStream_Write(stm, "aaa", 3, NULL);
|
||||
ok(r==S_OK, "IStream->Write failed %x\n", r);
|
||||
|
||||
r = IStorage_Commit(stg, STGC_ONLYIFCURRENT);
|
||||
ok(r==S_OK, "IStorage->Commit failed %x\n", r);
|
||||
|
||||
/* open a second transacted read/write storage */
|
||||
r = StgOpenStorage(filename, NULL, STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_NONE, NULL, 0, &stgrw);
|
||||
ok(r==S_OK, "StgOpenStorage failed %x\n", r);
|
||||
|
||||
/* update stream on the first storage and commit */
|
||||
pos.QuadPart = 0;
|
||||
r = IStream_Seek(stm, pos, 0, &upos);
|
||||
ok(r==S_OK, "IStream->Seek failed %x\n", r);
|
||||
|
||||
r = IStream_Write(stm, "ccc", 3, NULL);
|
||||
ok(r==S_OK, "IStream->Write failed %x\n", r);
|
||||
|
||||
r = IStorage_Commit(stg, STGC_ONLYIFCURRENT);
|
||||
ok(r==S_OK, "IStorage->Commit failed %x\n", r);
|
||||
|
||||
/* update again without committing */
|
||||
pos.QuadPart = 0;
|
||||
r = IStream_Seek(stm, pos, 0, &upos);
|
||||
ok(r==S_OK, "IStream->Seek failed %x\n", r);
|
||||
|
||||
r = IStream_Write(stm, "ddd", 3, NULL);
|
||||
ok(r==S_OK, "IStream->Write failed %x\n", r);
|
||||
|
||||
IStream_Release(stm);
|
||||
|
||||
/* we can still read the old content from the second storage */
|
||||
r = IStorage_OpenStream(stgrw, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
|
||||
ok(r==S_OK, "IStorage->OpenStream failed %x\n", r);
|
||||
|
||||
pos.QuadPart = 0;
|
||||
r = IStream_Seek(stm, pos, 0, &upos);
|
||||
ok(r==S_OK, "IStream->Seek failed %x\n", r);
|
||||
|
||||
r = IStream_Read(stm, buffer, sizeof(buffer), &bytesread);
|
||||
ok(r==S_OK, "IStream->Read failed %x\n", r);
|
||||
ok(bytesread == 3, "read wrong number of bytes %i\n", bytesread);
|
||||
ok(memcmp(buffer, "aaa", 3) == 0, "wrong data\n");
|
||||
|
||||
/* and overwrite the data */
|
||||
pos.QuadPart = 0;
|
||||
r = IStream_Seek(stm, pos, 0, &upos);
|
||||
ok(r==S_OK, "IStream->Seek failed %x\n", r);
|
||||
|
||||
r = IStream_Write(stm, "bbb", 3, NULL);
|
||||
ok(r==S_OK, "IStream->Write failed %x\n", r);
|
||||
|
||||
IStream_Release(stm);
|
||||
|
||||
/* commit fails because we're out of date */
|
||||
r = IStorage_Commit(stgrw, STGC_ONLYIFCURRENT);
|
||||
ok(r==STG_E_NOTCURRENT, "IStorage->Commit failed %x\n", r);
|
||||
|
||||
/* unless we force it */
|
||||
r = IStorage_Commit(stgrw, STGC_DEFAULT);
|
||||
ok(r==S_OK, "IStorage->Commit failed %x\n", r);
|
||||
|
||||
/* reverting gets us back to the last commit from the same storage */
|
||||
r = IStorage_Revert(stg);
|
||||
ok(r==S_OK, "IStorage->Revert failed %x\n", r);
|
||||
|
||||
r = IStorage_OpenStream(stg, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
|
||||
ok(r==S_OK, "IStorage->CreateStream failed %x\n", r);
|
||||
|
||||
pos.QuadPart = 0;
|
||||
r = IStream_Seek(stm, pos, 0, &upos);
|
||||
ok(r==S_OK, "IStream->Seek failed %x\n", r);
|
||||
|
||||
r = IStream_Read(stm, buffer, sizeof(buffer), &bytesread);
|
||||
ok(r==S_OK, "IStream->Read failed %x\n", r);
|
||||
ok(bytesread == 3, "read wrong number of bytes %i\n", bytesread);
|
||||
ok(memcmp(buffer, "ccc", 3) == 0, "wrong data\n");
|
||||
|
||||
/* and committing fails forever */
|
||||
r = IStorage_Commit(stg, STGC_ONLYIFCURRENT);
|
||||
ok(r==STG_E_NOTCURRENT, "IStorage->Commit failed %x\n", r);
|
||||
|
||||
IStream_Release(stm);
|
||||
|
||||
IStorage_Release(stg);
|
||||
IStorage_Release(stgrw);
|
||||
|
||||
DeleteFileA(filenameA);
|
||||
}
|
||||
|
||||
static void test_overwrite(void)
|
||||
{
|
||||
IStorage *stg = NULL;
|
||||
HRESULT r;
|
||||
IStream *stm = NULL;
|
||||
static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
|
||||
static const WCHAR stmname2[] = { 'C','O','N','T','E','N','T','2',0 };
|
||||
LARGE_INTEGER pos;
|
||||
ULARGE_INTEGER upos;
|
||||
char buffer[4096];
|
||||
DWORD orig_size, new_size;
|
||||
ULONG bytesread;
|
||||
HANDLE hfile;
|
||||
int i;
|
||||
|
||||
DeleteFileA(filenameA);
|
||||
|
||||
r = StgCreateDocfile(filename, STGM_CREATE | STGM_READWRITE | STGM_TRANSACTED, 0, &stg);
|
||||
ok(r==S_OK, "StgCreateDocfile failed %x\n", r);
|
||||
|
||||
r = WriteClassStg(stg, &test_stg_cls);
|
||||
ok(r == S_OK, "WriteClassStg failed %x\n", r);
|
||||
|
||||
r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
|
||||
ok(r==S_OK, "IStorage->CreateStream failed %x\n", r);
|
||||
|
||||
pos.QuadPart = 0;
|
||||
r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos);
|
||||
ok(r==S_OK, "IStream->Seek failed %x\n", r);
|
||||
|
||||
memset(buffer, 'a', sizeof(buffer));
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
/* Write enough bytes to pass the minimum storage file size */
|
||||
r = IStream_Write(stm, buffer, sizeof(buffer), NULL);
|
||||
ok(r==S_OK, "IStream->Write failed %x\n", r);
|
||||
}
|
||||
|
||||
r = IStorage_Commit(stg, STGC_DEFAULT);
|
||||
ok(r==S_OK, "IStorage->Commit failed %x\n", r);
|
||||
|
||||
hfile = CreateFileA(filenameA, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok(hfile != NULL, "couldn't open file %d\n", GetLastError());
|
||||
|
||||
orig_size = GetFileSize(hfile, NULL);
|
||||
|
||||
pos.QuadPart = 0;
|
||||
r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos);
|
||||
ok(r==S_OK, "IStream->Seek failed %x\n", r);
|
||||
|
||||
r = IStream_Write(stm, "b", 1, NULL);
|
||||
ok(r==S_OK, "IStream->Write failed %x\n", r);
|
||||
|
||||
r = IStorage_Commit(stg, STGC_OVERWRITE);
|
||||
ok(r==S_OK, "IStorage->Commit failed %x\n", r);
|
||||
|
||||
new_size = GetFileSize(hfile, NULL);
|
||||
|
||||
todo_wine ok(new_size == orig_size, "file grew from %d bytes to %d\n", orig_size, new_size);
|
||||
|
||||
IStream_Release(stm);
|
||||
|
||||
IStorage_RenameElement(stg, stmname, stmname2);
|
||||
|
||||
r = IStorage_Commit(stg, STGC_OVERWRITE);
|
||||
ok(r==S_OK, "IStorage->Commit failed %x\n", r);
|
||||
|
||||
new_size = GetFileSize(hfile, NULL);
|
||||
|
||||
todo_wine ok(new_size == orig_size, "file grew from %d bytes to %d\n", orig_size, new_size);
|
||||
|
||||
IStorage_Release(stg);
|
||||
|
||||
r = StgOpenStorage(filename, NULL, STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
|
||||
ok(r==S_OK, "StgOpenStorage failed %x\n", r);
|
||||
|
||||
r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
|
||||
ok(r==S_OK, "IStorage->CreateStream failed %x\n", r);
|
||||
|
||||
r = IStream_Read(stm, buffer, sizeof(buffer), &bytesread);
|
||||
ok(r==S_OK, "IStream->Write failed %x\n", r);
|
||||
ok(bytesread == sizeof(buffer), "only read %d bytes\n", bytesread);
|
||||
ok(buffer[0] == 'b', "unexpected data at byte 0\n");
|
||||
|
||||
for (i=1; i<sizeof(buffer); i++)
|
||||
if (buffer[i] != 'a')
|
||||
break;
|
||||
ok(i == sizeof(buffer), "unexpected data at byte %i\n", i);
|
||||
|
||||
pos.QuadPart = 0;
|
||||
r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos);
|
||||
ok(r==S_OK, "IStream->Seek failed %x\n", r);
|
||||
|
||||
r = IStream_Write(stm, "c", 1, NULL);
|
||||
ok(r==S_OK, "IStream->Write failed %x\n", r);
|
||||
|
||||
r = IStorage_Commit(stg, STGC_OVERWRITE);
|
||||
ok(r==S_OK, "IStorage->Commit failed %x\n", r);
|
||||
|
||||
new_size = GetFileSize(hfile, NULL);
|
||||
|
||||
todo_wine ok(new_size == orig_size, "file grew from %d bytes to %d\n", orig_size, new_size);
|
||||
|
||||
IStream_Release(stm);
|
||||
|
||||
IStorage_Release(stg);
|
||||
|
||||
CloseHandle(hfile);
|
||||
|
||||
DeleteFileA(filenameA);
|
||||
}
|
||||
|
||||
START_TEST(storage32)
|
||||
{
|
||||
CHAR temp[MAX_PATH];
|
||||
|
@ -3191,4 +3691,7 @@ START_TEST(storage32)
|
|||
test_hglobal_storage_creation();
|
||||
test_convert();
|
||||
test_direct_swmr();
|
||||
test_locking();
|
||||
test_transacted_shared();
|
||||
test_overwrite();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue