Autosyncing with Wine HEAD

svn path=/trunk/; revision=30896
This commit is contained in:
The Wine Synchronizer 2007-11-29 12:54:54 +00:00
parent ffbe9d4a1a
commit 83c857dfd3
106 changed files with 56703 additions and 1093 deletions

View file

@ -0,0 +1,597 @@
/*
* Unit tests for advpack.dll
*
* Copyright (C) 2005 Robert Reif
* Copyright (C) 2005 Sami Aario
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
#include <stdarg.h>
#include <windows.h>
#include <advpub.h>
#include <assert.h>
#include "wine/test.h"
/* defines for the TranslateInfString/Ex tests */
#define TEST_STRING1 "\\Application Name"
#define TEST_STRING2 "%49001%\\Application Name"
/* defines for the SetPerUserSecValues tests */
#define GUID_KEY "SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\guid"
#define REG_VAL_EXISTS(key, value) !RegQueryValueEx(key, value, NULL, NULL, NULL, NULL)
#define OPEN_GUID_KEY() !RegOpenKey(HKEY_LOCAL_MACHINE, GUID_KEY, &guid)
static HRESULT (WINAPI *pCloseINFEngine)(HINF);
static HRESULT (WINAPI *pDelNode)(LPCSTR,DWORD);
static HRESULT (WINAPI *pGetVersionFromFile)(LPCSTR,LPDWORD,LPDWORD,BOOL);
static HRESULT (WINAPI *pOpenINFEngine)(PCSTR,PCSTR,DWORD,HINF*,PVOID);
static HRESULT (WINAPI *pSetPerUserSecValues)(PPERUSERSECTION pPerUser);
static HRESULT (WINAPI *pTranslateInfString)(LPCSTR,LPCSTR,LPCSTR,LPCSTR,LPSTR,DWORD,LPDWORD,LPVOID);
static HRESULT (WINAPI *pTranslateInfStringEx)(HINF,PCSTR,PCSTR,PCSTR,PSTR,DWORD,PDWORD,PVOID);
static CHAR inf_file[MAX_PATH];
static CHAR PROG_FILES_ROOT[MAX_PATH];
static CHAR PROG_FILES[MAX_PATH];
static CHAR APP_PATH[MAX_PATH];
static DWORD APP_PATH_LEN;
static void get_progfiles_dir(void)
{
HKEY hkey;
DWORD size = MAX_PATH;
RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey);
RegQueryValueExA(hkey, "ProgramFilesDir", NULL, NULL, (LPBYTE)PROG_FILES_ROOT, &size);
RegCloseKey(hkey);
lstrcpyA(PROG_FILES, PROG_FILES_ROOT + 3); /* skip C:\ */
lstrcpyA(APP_PATH, PROG_FILES_ROOT);
lstrcatA(APP_PATH, TEST_STRING1);
APP_PATH_LEN = lstrlenA(APP_PATH) + 1;
}
static BOOL init_function_pointers(void)
{
HMODULE hAdvPack = LoadLibraryA("advpack.dll");
if (!hAdvPack)
return FALSE;
pCloseINFEngine = (void*)GetProcAddress(hAdvPack, "CloseINFEngine");
pDelNode = (void *)GetProcAddress(hAdvPack, "DelNode");
pGetVersionFromFile = (void *)GetProcAddress(hAdvPack, "GetVersionFromFile");
pOpenINFEngine = (void*)GetProcAddress(hAdvPack, "OpenINFEngine");
pSetPerUserSecValues = (void*)GetProcAddress(hAdvPack, "SetPerUserSecValues");
pTranslateInfString = (void *)GetProcAddress(hAdvPack, "TranslateInfString");
pTranslateInfStringEx = (void*)GetProcAddress(hAdvPack, "TranslateInfStringEx");
if (!pCloseINFEngine || !pDelNode || !pGetVersionFromFile ||
!pOpenINFEngine || !pSetPerUserSecValues || !pTranslateInfString)
return FALSE;
return TRUE;
}
static void version_test(void)
{
HRESULT hr;
DWORD major, minor;
major = minor = 0;
hr = pGetVersionFromFile("kernel32.dll", &major, &minor, FALSE);
ok (hr == S_OK, "GetVersionFromFileEx(kernel32.dll) failed, returned "
"0x%08x\n", hr);
trace("kernel32.dll Language ID: 0x%08x, Codepage ID: 0x%08x\n",
major, minor);
major = minor = 0;
hr = pGetVersionFromFile("kernel32.dll", &major, &minor, TRUE);
ok (hr == S_OK, "GetVersionFromFileEx(kernel32.dll) failed, returned "
"0x%08x\n", hr);
trace("kernel32.dll version: %d.%d.%d.%d\n", HIWORD(major), LOWORD(major),
HIWORD(minor), LOWORD(minor));
major = minor = 0;
hr = pGetVersionFromFile("advpack.dll", &major, &minor, FALSE);
ok (hr == S_OK, "GetVersionFromFileEx(advpack.dll) failed, returned "
"0x%08x\n", hr);
trace("advpack.dll Language ID: 0x%08x, Codepage ID: 0x%08x\n",
major, minor);
major = minor = 0;
hr = pGetVersionFromFile("advpack.dll", &major, &minor, TRUE);
ok (hr == S_OK, "GetVersionFromFileEx(advpack.dll) failed, returned "
"0x%08x\n", hr);
trace("advpack.dll version: %d.%d.%d.%d\n", HIWORD(major), LOWORD(major),
HIWORD(minor), LOWORD(minor));
}
static void delnode_test(void)
{
HRESULT hr;
HANDLE hn;
CHAR currDir[MAX_PATH];
int currDirLen;
/* Native DelNode apparently does not support relative paths, so we use
absolute paths for testing */
currDirLen = GetCurrentDirectoryA(sizeof(currDir) / sizeof(CHAR), currDir);
assert(currDirLen > 0 && currDirLen < sizeof(currDir) / sizeof(CHAR));
if(currDir[currDirLen - 1] == '\\')
currDir[--currDirLen] = 0;
/* Simple tests; these should fail. */
hr = pDelNode(NULL, 0);
ok (hr == E_FAIL, "DelNode called with NULL pathname should return E_FAIL\n");
hr = pDelNode("", 0);
ok (hr == E_FAIL, "DelNode called with empty pathname should return E_FAIL\n");
/* Test deletion of a file. */
hn = CreateFile("DelNodeTestFile1", GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
assert(hn != INVALID_HANDLE_VALUE);
CloseHandle(hn);
hr = pDelNode(lstrcat(currDir, "\\DelNodeTestFile1"), 0);
ok (hr == S_OK, "DelNode failed deleting a single file\n");
currDir[currDirLen] = '\0';
/* Test deletion of an empty directory. */
CreateDirectoryA("DelNodeTestDir", NULL);
hr = pDelNode(lstrcat(currDir, "\\DelNodeTestDir"), 0);
ok (hr == S_OK, "DelNode failed deleting an empty directory\n");
currDir[currDirLen] = '\0';
/* Test deletion of a directory containing one file. */
CreateDirectoryA("DelNodeTestDir", NULL);
hn = CreateFile("DelNodeTestDir\\DelNodeTestFile1", GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
assert(hn != INVALID_HANDLE_VALUE);
CloseHandle(hn);
hr = pDelNode(lstrcat(currDir, "\\DelNodeTestDir"), 0);
ok (hr == S_OK, "DelNode failed deleting a directory containing one file\n");
currDir[currDirLen] = '\0';
/* Test deletion of a directory containing multiple files. */
CreateDirectoryA("DelNodeTestDir", NULL);
hn = CreateFile("DelNodeTestDir\\DelNodeTestFile1", GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
assert(hn != INVALID_HANDLE_VALUE);
CloseHandle(hn);
hn = CreateFile("DelNodeTestDir\\DelNodeTestFile2", GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
assert(hn != INVALID_HANDLE_VALUE);
CloseHandle(hn);
hn = CreateFile("DelNodeTestDir\\DelNodeTestFile3", GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
assert(hn != INVALID_HANDLE_VALUE);
CloseHandle(hn);
hr = pDelNode(lstrcat(currDir, "\\DelNodeTestDir"), 0);
ok (hr == S_OK, "DelNode failed deleting a directory containing multiple files\n");
currDir[currDirLen] = '\0';
}
static void append_str(char **str, const char *data, ...)
{
va_list valist;
va_start(valist, data);
vsprintf(*str, data, valist);
*str += strlen(*str);
va_end(valist);
}
static void create_inf_file(void)
{
char data[1024];
char *ptr = data;
DWORD dwNumberOfBytesWritten;
HANDLE hf = CreateFile(inf_file, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
append_str(&ptr, "[Version]\n");
append_str(&ptr, "Signature=\"$Chicago$\"\n");
append_str(&ptr, "[CustInstDestSection]\n");
append_str(&ptr, "49001=ProgramFilesDir\n");
append_str(&ptr, "49010=DestA,1\n");
append_str(&ptr, "49020=DestB\n");
append_str(&ptr, "49030=DestC\n");
append_str(&ptr, "[ProgramFilesDir]\n");
append_str(&ptr, "HKLM,\"Software\\Microsoft\\Windows\\CurrentVersion\",");
append_str(&ptr, "\"ProgramFilesDir\",,\"%%24%%\\%%LProgramF%%\"\n");
append_str(&ptr, "[section]\n");
append_str(&ptr, "NotACustomDestination=Version\n");
append_str(&ptr, "CustomDestination=CustInstDestSection\n");
append_str(&ptr, "[Options.NTx86]\n");
append_str(&ptr, "49001=ProgramFilesDir\n");
append_str(&ptr, "InstallDir=%%49001%%\\%%DefaultAppPath%%\n");
append_str(&ptr, "Result1=%%49010%%\n");
append_str(&ptr, "Result2=%%49020%%\n");
append_str(&ptr, "Result3=%%49030%%\n");
append_str(&ptr, "CustomHDestination=CustInstDestSection\n");
append_str(&ptr, "[Strings]\n");
append_str(&ptr, "DefaultAppPath=\"Application Name\"\n");
append_str(&ptr, "LProgramF=\"%s\"\n", PROG_FILES);
append_str(&ptr, "[DestA]\n");
append_str(&ptr, "HKLM,\"Software\\Garbage\",\"ProgramFilesDir\",,'%%24%%\\%%LProgramF%%'\n");
append_str(&ptr, "[DestB]\n");
append_str(&ptr, "'HKLM','Software\\Microsoft\\Windows\\CurrentVersion',");
append_str(&ptr, "'ProgramFilesDir',,\"%%24%%\"\n");
append_str(&ptr, "[DestC]\n");
append_str(&ptr, "HKLM,\"Software\\Garbage\",\"ProgramFilesDir\",,'%%24%%'\n");
WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
CloseHandle(hf);
}
static void translateinfstring_test(void)
{
HRESULT hr;
char buffer[MAX_PATH];
DWORD dwSize;
create_inf_file();
/* pass in a couple invalid parameters */
hr = pTranslateInfString(NULL, NULL, NULL, NULL, buffer, MAX_PATH, &dwSize, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got 0x%08x\n", (UINT)hr);
/* try to open an inf file that doesn't exist */
hr = pTranslateInfString("c:\\a.inf", "Options.NTx86", "Options.NTx86",
"InstallDir", buffer, MAX_PATH, &dwSize, NULL);
ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || hr == E_INVALIDARG ||
hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND),
"Expected E_INVALIDARG, 0x80070002 or 0x8007007e, got 0x%08x\n", (UINT)hr);
if(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND))
{
trace("WinNT 3.51 detected. Skipping tests for TranslateInfString()\n");
return;
}
/* try a nonexistent section */
buffer[0] = 0;
hr = pTranslateInfString(inf_file, "idontexist", "Options.NTx86",
"InstallDir", buffer, MAX_PATH, &dwSize, NULL);
ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", (UINT)hr);
ok(!strcmp(buffer, TEST_STRING2), "Expected %s, got %s\n", TEST_STRING2, buffer);
ok(dwSize == 25, "Expected size 25, got %d\n", dwSize);
buffer[0] = 0;
/* try other nonexistent section */
hr = pTranslateInfString(inf_file, "Options.NTx86", "idontexist",
"InstallDir", buffer, MAX_PATH, &dwSize, NULL);
ok(hr == SPAPI_E_LINE_NOT_FOUND || hr == E_INVALIDARG,
"Expected SPAPI_E_LINE_NOT_FOUND or E_INVALIDARG, got 0x%08x\n", (UINT)hr);
buffer[0] = 0;
/* try nonexistent key */
hr = pTranslateInfString(inf_file, "Options.NTx86", "Options.NTx86",
"notvalid", buffer, MAX_PATH, &dwSize, NULL);
ok(hr == SPAPI_E_LINE_NOT_FOUND || hr == E_INVALIDARG,
"Expected SPAPI_E_LINE_NOT_FOUND or E_INVALIDARG, got 0x%08x\n", (UINT)hr);
buffer[0] = 0;
/* test the behavior of pszInstallSection */
hr = pTranslateInfString(inf_file, "section", "Options.NTx86",
"InstallDir", buffer, MAX_PATH, &dwSize, NULL);
ok(hr == ERROR_SUCCESS || hr == E_FAIL,
"Expected ERROR_SUCCESS or E_FAIL, got 0x%08x\n", (UINT)hr);
if(hr == ERROR_SUCCESS)
{
ok(!strcmp(buffer, APP_PATH), "Expected '%s', got '%s'\n", APP_PATH, buffer);
ok(dwSize == APP_PATH_LEN, "Expected size %d, got %d\n", APP_PATH_LEN, dwSize);
}
buffer[0] = 0;
/* try without a pszInstallSection */
hr = pTranslateInfString(inf_file, NULL, "Options.NTx86",
"InstallDir", buffer, MAX_PATH, &dwSize, NULL);
ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", (UINT)hr);
todo_wine
{
ok(!strcmp(buffer, TEST_STRING2), "Expected %s, got %s\n", TEST_STRING2, buffer);
ok(dwSize == 25, "Expected size 25, got %d\n", dwSize);
}
DeleteFile("c:\\a.inf");
DeleteFile(inf_file);
}
static void translateinfstringex_test(void)
{
HINF hinf;
HRESULT hr;
char buffer[MAX_PATH];
DWORD size = MAX_PATH;
create_inf_file();
/* need to see if there are any flags */
/* try a NULL filename */
hr = pOpenINFEngine(NULL, "Options.NTx86", 0, &hinf, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
/* try an empty filename */
hr = pOpenINFEngine("", "Options.NTx86", 0, &hinf, NULL);
ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
"Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", hr);
/* try a NULL hinf */
hr = pOpenINFEngine(inf_file, "Options.NTx86", 0, NULL, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
/* open the INF without the Install section specified */
hr = pOpenINFEngine(inf_file, NULL, 0, &hinf, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
/* try a NULL hinf */
hr = pTranslateInfStringEx(NULL, inf_file, "Options.NTx86", "InstallDir",
buffer, size, &size, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
/* try a NULL filename */
hr = pTranslateInfStringEx(hinf, NULL, "Options.NTx86", "InstallDir",
buffer, size, &size, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
/* try an empty filename */
memset(buffer, 'a', 25);
buffer[24] = '\0';
size = MAX_PATH;
hr = pTranslateInfStringEx(hinf, "", "Options.NTx86", "InstallDir",
buffer, size, &size, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
todo_wine
{
ok(!strcmp(buffer, TEST_STRING2), "Expected %s, got %s\n", TEST_STRING2, buffer);
ok(size == 25, "Expected size 25, got %d\n", size);
}
/* try a NULL translate section */
hr = pTranslateInfStringEx(hinf, inf_file, NULL, "InstallDir",
buffer, size, &size, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
/* try an empty translate section */
hr = pTranslateInfStringEx(hinf, inf_file, "", "InstallDir",
buffer, size, &size, NULL);
ok(hr == SPAPI_E_LINE_NOT_FOUND, "Expected SPAPI_E_LINE_NOT_FOUND, got %08x\n", hr);
/* try a NULL translate key */
hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", NULL,
buffer, size, &size, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
/* try an empty translate key */
hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "",
buffer, size, &size, NULL);
ok(hr == SPAPI_E_LINE_NOT_FOUND, "Expected SPAPI_E_LINE_NOT_FOUND, got %08x\n", hr);
/* successfully translate the string */
memset(buffer, 'a', 25);
buffer[24] = '\0';
size = MAX_PATH;
hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "InstallDir",
buffer, size, &size, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
todo_wine
{
ok(!strcmp(buffer, TEST_STRING2), "Expected %s, got %s\n", TEST_STRING2, buffer);
ok(size == 25, "Expected size 25, got %d\n", size);
}
/* try a NULL hinf */
hr = pCloseINFEngine(NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
/* successfully close the hinf */
hr = pCloseINFEngine(hinf);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
/* open the inf with the install section */
hr = pOpenINFEngine(inf_file, "section", 0, &hinf, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
/* translate the string with the install section specified */
memset(buffer, 'a', APP_PATH_LEN);
buffer[APP_PATH_LEN - 1] = '\0';
size = MAX_PATH;
hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "InstallDir",
buffer, size, &size, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
ok(!strcmp(buffer, APP_PATH), "Expected %s, got %s\n", APP_PATH, buffer);
ok(size == APP_PATH_LEN, "Expected size %d, got %d\n", APP_PATH_LEN, size);
/* Single quote test (Note size includes null on return from call) */
memset(buffer, 'a', APP_PATH_LEN);
buffer[APP_PATH_LEN - 1] = '\0';
size = MAX_PATH;
hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "Result1",
buffer, size, &size, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
ok(!lstrcmpi(buffer, PROG_FILES_ROOT),
"Expected %s, got %s\n", PROG_FILES_ROOT, buffer);
ok(size == lstrlenA(PROG_FILES_ROOT)+1, "Expected size %d, got %d\n",
lstrlenA(PROG_FILES_ROOT)+1, size);
memset(buffer, 'a', APP_PATH_LEN);
buffer[APP_PATH_LEN - 1] = '\0';
size = MAX_PATH;
hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "Result2",
buffer, size, &size, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
ok(!lstrcmpi(buffer, PROG_FILES_ROOT),
"Expected %s, got %s\n", PROG_FILES_ROOT, buffer);
ok(size == lstrlenA(PROG_FILES_ROOT)+1, "Expected size %d, got %d\n",
lstrlenA(PROG_FILES_ROOT)+1, size);
{
char drive[MAX_PATH];
lstrcpy(drive, PROG_FILES_ROOT);
drive[3] = 0x00; /* Just keep the system drive plus '\' */
memset(buffer, 'a', APP_PATH_LEN);
buffer[APP_PATH_LEN - 1] = '\0';
size = MAX_PATH;
hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "Result3",
buffer, size, &size, NULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
ok(!lstrcmpi(buffer, drive),
"Expected %s, got %s\n", drive, buffer);
ok(size == lstrlenA(drive)+1, "Expected size %d, got %d\n",
lstrlenA(drive)+1, size);
}
/* close the INF again */
hr = pCloseINFEngine(hinf);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
DeleteFileA(inf_file);
}
static BOOL check_reg_str(HKEY hkey, LPCSTR name, LPCSTR value)
{
DWORD size = MAX_PATH;
char check[MAX_PATH];
if (RegQueryValueEx(hkey, name, NULL, NULL, (LPBYTE)check, &size))
return FALSE;
return !lstrcmp(check, value);
}
static BOOL check_reg_dword(HKEY hkey, LPCSTR name, DWORD value)
{
DWORD size = sizeof(DWORD);
DWORD check;
if (RegQueryValueEx(hkey, name, NULL, NULL, (LPBYTE)&check, &size))
return FALSE;
return (check == value);
}
static void setperusersecvalues_test(void)
{
PERUSERSECTION peruser;
HRESULT hr;
HKEY guid;
lstrcpy(peruser.szDispName, "displayname");
lstrcpy(peruser.szLocale, "locale");
lstrcpy(peruser.szStub, "stub");
lstrcpy(peruser.szVersion, "1,1,1,1");
lstrcpy(peruser.szCompID, "compid");
peruser.dwIsInstalled = 1;
peruser.bRollback = FALSE;
/* try a NULL pPerUser */
if (0)
{
/* This crashes on systems with IE7 */
hr = pSetPerUserSecValues(NULL);
todo_wine
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
ok(!OPEN_GUID_KEY(), "Expected guid key to not exist\n");
}
/* at the very least, szGUID must be valid */
peruser.szGUID[0] = '\0';
hr = pSetPerUserSecValues(&peruser);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
ok(!OPEN_GUID_KEY(), "Expected guid key to not exist\n");
/* set initial values */
lstrcpy(peruser.szGUID, "guid");
hr = pSetPerUserSecValues(&peruser);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
ok(OPEN_GUID_KEY(), "Expected guid key to exist\n");
ok(check_reg_str(guid, NULL, "displayname"), "Expected displayname\n");
ok(check_reg_str(guid, "ComponentID", "compid"), "Expected compid\n");
ok(check_reg_str(guid, "Locale", "locale"), "Expected locale\n");
ok(check_reg_str(guid, "StubPath", "stub"), "Expected stub\n");
ok(check_reg_str(guid, "Version", "1,1,1,1"), "Expected 1,1,1,1\n");
ok(check_reg_dword(guid, "IsInstalled", 1), "Expected 1\n");
ok(!REG_VAL_EXISTS(guid, "OldDisplayName"), "Expected OldDisplayName to not exist\n");
ok(!REG_VAL_EXISTS(guid, "OldLocale"), "Expected OldLocale to not exist\n");
ok(!REG_VAL_EXISTS(guid, "OldStubPath"), "Expected OldStubPath to not exist\n");
ok(!REG_VAL_EXISTS(guid, "OldVersion"), "Expected OldVersion to not exist\n");
ok(!REG_VAL_EXISTS(guid, "RealStubPath"), "Expected RealStubPath to not exist\n");
/* raise the version, but bRollback is FALSE, so vals not saved */
lstrcpy(peruser.szVersion, "2,1,1,1");
hr = pSetPerUserSecValues(&peruser);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
ok(check_reg_str(guid, NULL, "displayname"), "Expected displayname\n");
ok(check_reg_str(guid, "ComponentID", "compid"), "Expected compid\n");
ok(check_reg_str(guid, "Locale", "locale"), "Expected locale\n");
ok(check_reg_str(guid, "StubPath", "stub"), "Expected stub\n");
ok(check_reg_str(guid, "Version", "2,1,1,1"), "Expected 2,1,1,1\n");
ok(check_reg_dword(guid, "IsInstalled", 1), "Expected 1\n");
ok(!REG_VAL_EXISTS(guid, "OldDisplayName"), "Expected OldDisplayName to not exist\n");
ok(!REG_VAL_EXISTS(guid, "OldLocale"), "Expected OldLocale to not exist\n");
ok(!REG_VAL_EXISTS(guid, "OldStubPath"), "Expected OldStubPath to not exist\n");
ok(!REG_VAL_EXISTS(guid, "OldVersion"), "Expected OldVersion to not exist\n");
ok(!REG_VAL_EXISTS(guid, "RealStubPath"), "Expected RealStubPath to not exist\n");
/* raise the version again, bRollback is TRUE so vals are saved */
peruser.bRollback = TRUE;
lstrcpy(peruser.szVersion, "3,1,1,1");
hr = pSetPerUserSecValues(&peruser);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
ok(check_reg_str(guid, NULL, "displayname"), "Expected displayname\n");
ok(check_reg_str(guid, "ComponentID", "compid"), "Expected compid\n");
ok(check_reg_str(guid, "Locale", "locale"), "Expected locale\n");
ok(check_reg_dword(guid, "IsInstalled", 1), "Expected 1\n");
ok(check_reg_str(guid, "Version", "3,1,1,1"), "Expected 3,1,1,1\n");
todo_wine
{
ok(check_reg_str(guid, "OldDisplayName", "displayname"), "Expected displayname\n");
ok(check_reg_str(guid, "OldLocale", "locale"), "Expected locale\n");
ok(check_reg_str(guid, "RealStubPath", "stub"), "Expected stub\n");
ok(check_reg_str(guid, "OldStubPath", "stub"), "Expected stub\n");
ok(check_reg_str(guid, "OldVersion", "2,1,1,1"), "Expected 2,1,1,1\n");
ok(check_reg_str(guid, "StubPath",
"rundll32.exe advpack.dll,UserInstStubWrapper guid"),
"Expected real stub\n");
}
RegDeleteKey(HKEY_LOCAL_MACHINE, GUID_KEY);
}
START_TEST(advpack)
{
if (!init_function_pointers())
return;
/* Make sure we create the temporary file in a directory
* were we have enough rights
*/
GetTempPath(MAX_PATH, inf_file);
lstrcat(inf_file,"test.inf");
get_progfiles_dir();
version_test();
delnode_test();
setperusersecvalues_test();
translateinfstring_test();
translateinfstringex_test();
}

View file

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="advpack_winetest" type="win32cui" installbase="bin" installname="advpack_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="advpack_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>cabinet</library>
<library>user32</library>
<library>advapi32</library>
<library>kernel32</library>
<library>ntdll</library>
<file>advpack.c</file>
<file>files.c</file>
<file>install.c</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,563 @@
/*
* Unit tests for advpack.dll file functions
*
* Copyright (C) 2006 James Hawkins
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
#include <windows.h>
#include <advpub.h>
#include <fci.h>
#include "wine/test.h"
/* make the max size large so there is only one cab file */
#define MEDIA_SIZE 999999999
#define FOLDER_THRESHOLD 900000
/* function pointers */
HMODULE hAdvPack;
static HRESULT (WINAPI *pAddDelBackupEntry)(LPCSTR, LPCSTR, LPCSTR, DWORD);
static HRESULT (WINAPI *pExtractFiles)(LPCSTR, LPCSTR, DWORD, LPCSTR, LPVOID, DWORD);
static HRESULT (WINAPI *pAdvInstallFile)(HWND,LPCSTR,LPCSTR,LPCSTR,LPCSTR,DWORD,DWORD);
CHAR CURR_DIR[MAX_PATH];
static void init_function_pointers(void)
{
hAdvPack = LoadLibraryA("advpack.dll");
if (hAdvPack)
{
pAddDelBackupEntry = (void *)GetProcAddress(hAdvPack, "AddDelBackupEntry");
pExtractFiles = (void *)GetProcAddress(hAdvPack, "ExtractFiles");
pAdvInstallFile = (void*)GetProcAddress(hAdvPack, "AdvInstallFile");
}
}
/* creates a file with the specified name for tests */
static void createTestFile(const CHAR *name)
{
HANDLE file;
DWORD written;
file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
WriteFile(file, name, strlen(name), &written, NULL);
WriteFile(file, "\n", strlen("\n"), &written, NULL);
CloseHandle(file);
}
static void create_test_files(void)
{
int len;
GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
len = lstrlenA(CURR_DIR);
if(len && (CURR_DIR[len-1] == '\\'))
CURR_DIR[len-1] = 0;
createTestFile("a.txt");
createTestFile("b.txt");
CreateDirectoryA("testdir", NULL);
createTestFile("testdir\\c.txt");
createTestFile("testdir\\d.txt");
CreateDirectoryA("dest", NULL);
}
static void delete_test_files(void)
{
DeleteFileA("a.txt");
DeleteFileA("b.txt");
DeleteFileA("testdir\\c.txt");
DeleteFileA("testdir\\d.txt");
RemoveDirectoryA("testdir");
RemoveDirectoryA("dest");
DeleteFileA("extract.cab");
}
static BOOL check_ini_file_attr(LPSTR filename)
{
BOOL ret;
DWORD expected = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY;
DWORD attr = GetFileAttributesA(filename);
ret = (attr & expected) && (attr != INVALID_FILE_ATTRIBUTES);
SetFileAttributesA(filename, FILE_ATTRIBUTE_NORMAL);
return ret;
}
#define FIELD_LEN 16
static BOOL check_ini_contents(LPSTR filename, BOOL add)
{
CHAR field[FIELD_LEN];
BOOL ret = TRUE, match;
GetPrivateProfileStringA("backup", "one", NULL, field, FIELD_LEN, filename);
match = !lstrcmpA(field, "-1,0,0,0,0,0,-1");
if ((add && !match) || (!add && match)) {
trace("first test: got %s\n", field);
ret = FALSE;
}
GetPrivateProfileStringA("backup", "two", NULL, field, FIELD_LEN, filename);
if (lstrcmpA(field, "-1,0,0,0,0,0,-1")) {
trace("second test: got %s\n", field);
ret = FALSE;
}
GetPrivateProfileStringA("backup", "three", NULL, field, FIELD_LEN, filename);
match = !lstrcmpA(field, "-1,0,0,0,0,0,-1");
if ((add && !match) || (!add && match)) {
trace("third test: got %s\n", field);
ret = FALSE;
}
return ret;
}
static void test_AddDelBackupEntry(void)
{
HRESULT res;
CHAR path[MAX_PATH];
CHAR windir[MAX_PATH];
lstrcpyA(path, CURR_DIR);
lstrcatA(path, "\\backup\\basename.INI");
/* native AddDelBackupEntry crashes if lpcszBaseName is NULL */
/* try a NULL file list */
res = pAddDelBackupEntry(NULL, "backup", "basename", AADBE_ADD_ENTRY);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(!DeleteFileA(path), "Expected path to not exist\n");
lstrcpyA(path, CURR_DIR);
lstrcatA(path, "\\backup\\.INI");
/* try an empty base name */
res = pAddDelBackupEntry("one\0two\0three\0", "backup", "", AADBE_ADD_ENTRY);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(!DeleteFileA(path), "Expected path to not exist\n");
lstrcpyA(path, CURR_DIR);
lstrcatA(path, "\\basename.INI");
/* try an invalid flag */
res = pAddDelBackupEntry("one\0two\0three\0", NULL, "basename", 0);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(!DeleteFileA(path), "Expected path to not exist\n");
lstrcpyA(path, "c:\\basename.INI");
/* create the INF file */
res = pAddDelBackupEntry("one\0two\0three\0", "c:\\", "basename", AADBE_ADD_ENTRY);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(check_ini_file_attr(path), "Expected ini file to be hidden\n");
ok(check_ini_contents(path, TRUE), "Expected ini contents to match\n");
ok(DeleteFileA(path), "Expected path to exist\n");
lstrcpyA(path, CURR_DIR);
lstrcatA(path, "\\backup\\basename.INI");
/* try to create the INI file in a nonexistent directory */
RemoveDirectoryA("backup");
res = pAddDelBackupEntry("one\0two\0three\0", "backup", "basename", AADBE_ADD_ENTRY);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(!check_ini_file_attr(path), "Expected ini file to not be hidden\n");
ok(!check_ini_contents(path, TRUE), "Expected ini contents to not match\n");
ok(!DeleteFileA(path), "Expected path to not exist\n");
/* try an existent, relative backup directory */
CreateDirectoryA("backup", NULL);
res = pAddDelBackupEntry("one\0two\0three\0", "backup", "basename", AADBE_ADD_ENTRY);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(check_ini_file_attr(path), "Expected ini file to be hidden\n");
ok(check_ini_contents(path, TRUE), "Expected ini contents to match\n");
ok(DeleteFileA(path), "Expected path to exist\n");
RemoveDirectoryA("backup");
GetWindowsDirectoryA(windir, sizeof(windir));
sprintf(path, "%s\\basename.INI", windir);
/* try a NULL backup dir, INI is created in the windows directory */
res = pAddDelBackupEntry("one\0two\0three\0", NULL, "basename", AADBE_ADD_ENTRY);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(check_ini_contents(path, TRUE), "Expected ini contents to match\n");
/* remove the entries with AADBE_DEL_ENTRY */
SetFileAttributesA(path, FILE_ATTRIBUTE_NORMAL);
res = pAddDelBackupEntry("one\0three\0", NULL, "basename", AADBE_DEL_ENTRY);
SetFileAttributesA(path, FILE_ATTRIBUTE_NORMAL);
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(check_ini_contents(path, FALSE), "Expected ini contents to match\n");
ok(DeleteFileA(path), "Expected path to exist\n");
}
/* the FCI callbacks */
static void *mem_alloc(ULONG cb)
{
return HeapAlloc(GetProcessHeap(), 0, cb);
}
static void mem_free(void *memory)
{
HeapFree(GetProcessHeap(), 0, memory);
}
static BOOL get_next_cabinet(PCCAB pccab, ULONG cbPrevCab, void *pv)
{
return TRUE;
}
static long progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
{
return 0;
}
static int file_placed(PCCAB pccab, char *pszFile, long cbFile,
BOOL fContinuation, void *pv)
{
return 0;
}
static INT_PTR fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
{
HANDLE handle;
DWORD dwAccess = 0;
DWORD dwShareMode = 0;
DWORD dwCreateDisposition = OPEN_EXISTING;
dwAccess = GENERIC_READ | GENERIC_WRITE;
/* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
dwCreateDisposition = OPEN_EXISTING;
else
dwCreateDisposition = CREATE_NEW;
handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
dwCreateDisposition, 0, NULL);
ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
return (INT_PTR)handle;
}
static UINT fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
{
HANDLE handle = (HANDLE)hf;
DWORD dwRead;
BOOL res;
res = ReadFile(handle, memory, cb, &dwRead, NULL);
ok(res, "Failed to ReadFile\n");
return dwRead;
}
static UINT fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
{
HANDLE handle = (HANDLE)hf;
DWORD dwWritten;
BOOL res;
res = WriteFile(handle, memory, cb, &dwWritten, NULL);
ok(res, "Failed to WriteFile\n");
return dwWritten;
}
static int fci_close(INT_PTR hf, int *err, void *pv)
{
HANDLE handle = (HANDLE)hf;
ok(CloseHandle(handle), "Failed to CloseHandle\n");
return 0;
}
static long fci_seek(INT_PTR hf, long dist, int seektype, int *err, void *pv)
{
HANDLE handle = (HANDLE)hf;
DWORD ret;
ret = SetFilePointer(handle, dist, NULL, seektype);
ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
return ret;
}
static int fci_delete(char *pszFile, int *err, void *pv)
{
BOOL ret = DeleteFileA(pszFile);
ok(ret, "Failed to DeleteFile %s\n", pszFile);
return 0;
}
static BOOL get_temp_file(char *pszTempName, int cbTempName, void *pv)
{
LPSTR tempname;
tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
GetTempFileNameA(".", "xx", 0, tempname);
if (tempname && (strlen(tempname) < (unsigned)cbTempName))
{
lstrcpyA(pszTempName, tempname);
HeapFree(GetProcessHeap(), 0, tempname);
return TRUE;
}
HeapFree(GetProcessHeap(), 0, tempname);
return FALSE;
}
static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
USHORT *pattribs, int *err, void *pv)
{
BY_HANDLE_FILE_INFORMATION finfo;
FILETIME filetime;
HANDLE handle;
DWORD attrs;
BOOL res;
handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
res = GetFileInformationByHandle(handle, &finfo);
ok(res, "Expected GetFileInformationByHandle to succeed\n");
FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
FileTimeToDosDateTime(&filetime, pdate, ptime);
attrs = GetFileAttributes(pszName);
ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
return (INT_PTR)handle;
}
static void add_file(HFCI hfci, char *file)
{
char path[MAX_PATH];
BOOL res;
lstrcpyA(path, CURR_DIR);
lstrcatA(path, "\\");
lstrcatA(path, file);
res = FCIAddFile(hfci, path, file, FALSE, get_next_cabinet, progress,
get_open_info, tcompTYPE_MSZIP);
ok(res, "Expected FCIAddFile to succeed\n");
}
static void set_cab_parameters(PCCAB pCabParams)
{
ZeroMemory(pCabParams, sizeof(CCAB));
pCabParams->cb = MEDIA_SIZE;
pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
pCabParams->setID = 0xbeef;
lstrcpyA(pCabParams->szCabPath, CURR_DIR);
lstrcatA(pCabParams->szCabPath, "\\");
lstrcpyA(pCabParams->szCab, "extract.cab");
}
static void create_cab_file(void)
{
CCAB cabParams;
HFCI hfci;
ERF erf;
static CHAR a_txt[] = "a.txt",
b_txt[] = "b.txt",
testdir_c_txt[] = "testdir\\c.txt",
testdir_d_txt[] = "testdir\\d.txt";
BOOL res;
set_cab_parameters(&cabParams);
hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
fci_read, fci_write, fci_close, fci_seek, fci_delete,
get_temp_file, &cabParams, NULL);
ok(hfci != NULL, "Failed to create an FCI context\n");
add_file(hfci, a_txt);
add_file(hfci, b_txt);
add_file(hfci, testdir_c_txt);
add_file(hfci, testdir_d_txt);
res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
ok(res, "Failed to flush the cabinet\n");
res = FCIDestroy(hfci);
ok(res, "Failed to destroy the cabinet\n");
}
static void test_ExtractFiles(void)
{
HRESULT hr;
char destFolder[MAX_PATH];
lstrcpyA(destFolder, CURR_DIR);
lstrcatA(destFolder, "\\");
lstrcatA(destFolder, "dest");
/* try NULL cab file */
hr = pExtractFiles(NULL, destFolder, 0, NULL, NULL, 0);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr);
ok(RemoveDirectoryA("dest"), "Expected dest to exist\n");
/* try NULL destination */
hr = pExtractFiles("extract.cab", NULL, 0, NULL, NULL, 0);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr);
ok(!RemoveDirectoryA("dest"), "Expected dest to not exist\n");
/* extract all files in the cab to nonexistent destination directory */
hr = pExtractFiles("extract.cab", destFolder, 0, NULL, NULL, 0);
ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND),
"Expected %d, got %d\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), hr);
ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
ok(!RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to not exist\n");
ok(!RemoveDirectoryA("dest"), "Expected dest to not exist\n");
/* extract all files in the cab to the destination directory */
CreateDirectoryA("dest", NULL);
hr = pExtractFiles("extract.cab", destFolder, 0, NULL, NULL, 0);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n");
/* extract all files to a relative destination directory */
hr = pExtractFiles("extract.cab", "dest", 0, NULL, NULL, 0);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n");
/* only extract two of the files from the cab */
hr = pExtractFiles("extract.cab", "dest", 0, "a.txt:testdir\\c.txt", NULL, 0);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n");
ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
/* use valid chars before and after file list */
hr = pExtractFiles("extract.cab", "dest", 0, " :\t: a.txt:testdir\\c.txt \t:", NULL, 0);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n");
ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
/* use invalid chars before and after file list */
hr = pExtractFiles("extract.cab", "dest", 0, " +-\\ a.txt:testdir\\c.txt a_:", NULL, 0);
ok(hr == E_FAIL, "Expected E_FAIL, got %d\n", hr);
ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
ok(!RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to not exist\n");
/* try an empty file list */
hr = pExtractFiles("extract.cab", "dest", 0, "", NULL, 0);
ok(hr == E_FAIL, "Expected E_FAIL, got %d\n", hr);
ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
ok(!RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to not exist\n");
/* try a nonexistent file in the file list */
hr = pExtractFiles("extract.cab", "dest", 0, "a.txt:idontexist:testdir\\c.txt", NULL, 0);
ok(hr == E_FAIL, "Expected E_FAIL, got %d\n", hr);
ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
ok(!RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to not exist\n");
}
static void test_AdvInstallFile(void)
{
HRESULT hr;
char CURR_DIR[MAX_PATH];
char destFolder[MAX_PATH];
GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
lstrcpyA(destFolder, CURR_DIR);
lstrcatA(destFolder, "\\");
lstrcatA(destFolder, "dest");
createTestFile("source.txt");
/* try invalid source directory */
hr = pAdvInstallFile(NULL, NULL, "source.txt", destFolder, "destination.txt", 0, 0);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr);
ok(!DeleteFileA("dest\\destination.txt"), "Expected dest\\destination.txt to not exist\n");
/* try invalid source file */
hr = pAdvInstallFile(NULL, CURR_DIR, NULL, destFolder, "destination.txt", 0, 0);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr);
ok(!DeleteFileA("dest\\destination.txt"), "Expected dest\\destination.txt to not exist\n");
/* try invalid destination directory */
hr = pAdvInstallFile(NULL, CURR_DIR, "source.txt", NULL, "destination.txt", 0, 0);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr);
ok(!DeleteFileA("dest\\destination.txt"), "Expected dest\\destination.txt to not exist\n");
/* try copying to nonexistent destination directory */
hr = pAdvInstallFile(NULL, CURR_DIR, "source.txt", destFolder, "destination.txt", 0, 0);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
ok(DeleteFileA("dest\\destination.txt"), "Expected dest\\destination.txt to exist\n");
/* native windows screws up if the source file doesn't exist */
/* test AIF_NOOVERWRITE behavior, asks the user to overwrite if AIF_QUIET is not specified */
createTestFile("dest\\destination.txt");
hr = pAdvInstallFile(NULL, CURR_DIR, "source.txt", destFolder,
"destination.txt", AIF_NOOVERWRITE | AIF_QUIET, 0);
ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
ok(DeleteFileA("dest\\destination.txt"), "Expected dest\\destination.txt to exist\n");
ok(RemoveDirectoryA("dest"), "Expected dest to exist\n");
DeleteFileA("source.txt");
}
START_TEST(files)
{
init_function_pointers();
create_test_files();
create_cab_file();
test_AddDelBackupEntry();
test_ExtractFiles();
test_AdvInstallFile();
delete_test_files();
}

View file

@ -0,0 +1,276 @@
/*
* Unit tests for advpack.dll install functions
*
* Copyright (C) 2006 James Hawkins
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
#include <windows.h>
#include <advpub.h>
#include "wine/test.h"
/* function pointers */
static HRESULT (WINAPI *pRunSetupCommand)(HWND, LPCSTR, LPCSTR, LPCSTR, LPCSTR, HANDLE*, DWORD, LPVOID);
static HRESULT (WINAPI *pLaunchINFSection)(HWND, HINSTANCE, LPSTR, INT);
static HRESULT (WINAPI *pLaunchINFSectionEx)(HWND, HINSTANCE, LPSTR, INT);
static char CURR_DIR[MAX_PATH];
static BOOL init_function_pointers(void)
{
HMODULE hAdvPack = LoadLibraryA("advpack.dll");
if (!hAdvPack)
return FALSE;
pRunSetupCommand = (void *)GetProcAddress(hAdvPack, "RunSetupCommand");
pLaunchINFSection = (void *)GetProcAddress(hAdvPack, "LaunchINFSection");
pLaunchINFSectionEx = (void *)GetProcAddress(hAdvPack, "LaunchINFSectionEx");
if (!pRunSetupCommand || !pLaunchINFSection || !pLaunchINFSectionEx)
return FALSE;
return TRUE;
}
static BOOL is_spapi_err(DWORD err)
{
const DWORD SPAPI_PREFIX = 0x800F0000L;
const DWORD SPAPI_MASK = 0xFFFF0000L;
return (((err & SPAPI_MASK) ^ SPAPI_PREFIX) == 0);
}
static void append_str(char **str, const char *data)
{
sprintf(*str, data);
*str += strlen(*str);
}
static void create_inf_file(LPCSTR filename)
{
char data[1024];
char *ptr = data;
DWORD dwNumberOfBytesWritten;
HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
append_str(&ptr, "[Version]\n");
append_str(&ptr, "Signature=\"$Chicago$\"\n");
append_str(&ptr, "AdvancedINF=2.5\n");
append_str(&ptr, "[DefaultInstall]\n");
append_str(&ptr, "RegisterOCXs=RegisterOCXsSection\n");
append_str(&ptr, "[RegisterOCXsSection]\n");
append_str(&ptr, "%%11%%\\ole32.dll\n");
WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL);
CloseHandle(hf);
}
static void test_RunSetupCommand(void)
{
HRESULT hr;
HANDLE hexe;
char path[MAX_PATH];
char dir[MAX_PATH];
char systemdir[MAX_PATH];
GetSystemDirectoryA(systemdir, sizeof(systemdir));
/* try an invalid cmd name */
hr = pRunSetupCommand(NULL, NULL, "Install", "Dir", "Title", NULL, 0, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr);
/* try an invalid directory */
hr = pRunSetupCommand(NULL, "winver.exe", "Install", NULL, "Title", NULL, 0, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr);
/* try to run a nonexistent exe */
hexe = (HANDLE)0xdeadbeef;
hr = pRunSetupCommand(NULL, "idontexist.exe", "Install", systemdir, "Title", &hexe, 0, NULL);
ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
"Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr);
ok(hexe == NULL, "Expcted hexe to be NULL\n");
ok(!TerminateProcess(hexe, 0), "Expected TerminateProcess to fail\n");
/* try a bad directory */
hexe = (HANDLE)0xdeadbeef;
hr = pRunSetupCommand(NULL, "winver.exe", "Install", "non\\existent\\directory", "Title", &hexe, 0, NULL);
ok(hr == HRESULT_FROM_WIN32(ERROR_DIRECTORY),
"Expected HRESULT_FROM_WIN32(ERROR_DIRECTORY), got %d\n", hr);
ok(hexe == NULL, "Expcted hexe to be NULL\n");
ok(!TerminateProcess(hexe, 0), "Expected TerminateProcess to fail\n");
/* try to run an exe with the RSC_FLAG_INF flag */
hexe = (HANDLE)0xdeadbeef;
hr = pRunSetupCommand(NULL, "winver.exe", "Install", systemdir, "Title", &hexe, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(is_spapi_err(hr), "Expected a setupapi error, got %d\n", hr);
ok(hexe == (HANDLE)0xdeadbeef, "Expected hexe to be 0xdeadbeef\n");
ok(!TerminateProcess(hexe, 0), "Expected TerminateProcess to fail\n");
/* run winver.exe */
hexe = (HANDLE)0xdeadbeef;
hr = pRunSetupCommand(NULL, "winver.exe", "Install", systemdir, "Title", &hexe, 0, NULL);
ok(hr == S_ASYNCHRONOUS, "Expected S_ASYNCHRONOUS, got %d\n", hr);
ok(hexe != NULL, "Expected hexe to be non-NULL\n");
ok(TerminateProcess(hexe, 0), "Expected TerminateProcess to succeed\n");
CreateDirectoryA("one", NULL);
create_inf_file("one\\test.inf");
/* try a full path to the INF, with working dir provided */
lstrcpy(path, CURR_DIR);
lstrcat(path, "\\one\\test.inf");
lstrcpy(dir, CURR_DIR);
lstrcat(dir, "\\one");
hr = pRunSetupCommand(NULL, path, "DefaultInstall", dir, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(hr == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", hr);
/* try a full path to the INF, NULL working dir */
hr = pRunSetupCommand(NULL, path, "DefaultInstall", NULL, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %d\n", hr);
/* try a full path to the INF, empty working dir */
hr = pRunSetupCommand(NULL, path, "DefaultInstall", "", "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(hr == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", hr);
/* try a relative path to the INF, with working dir provided */
hr = pRunSetupCommand(NULL, "one\\test.inf", "DefaultInstall", dir, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(hr == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", hr);
/* try a relative path to the INF, NULL working dir */
hr = pRunSetupCommand(NULL, "one\\test.inf", "DefaultInstall", NULL, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %d\n", hr);
/* try a relative path to the INF, empty working dir */
hr = pRunSetupCommand(NULL, "one\\test.inf", "DefaultInstall", "", "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(hr == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", hr);
/* try only the INF filename, with working dir provided */
hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", dir, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
"Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr);
/* try only the INF filename, NULL working dir */
hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", NULL, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %d\n", hr);
/* try only the INF filename, empty working dir */
hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", "", "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
"Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr);
DeleteFileA("one\\test.inf");
RemoveDirectoryA("one");
create_inf_file("test.inf");
/* try INF file in the current directory, working directory provided */
hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", CURR_DIR, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
"Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr);
/* try INF file in the current directory, NULL working directory */
hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", NULL, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %d\n", hr);
/* try INF file in the current directory, empty working directory */
hr = pRunSetupCommand(NULL, "test.inf", "DefaultInstall", CURR_DIR, "Title", NULL, RSC_FLAG_INF | RSC_FLAG_QUIET, NULL);
ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
"Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %d\n", hr);
}
static void test_LaunchINFSection(void)
{
HRESULT hr;
char cmdline[MAX_PATH];
static char file[] = "test.inf,DefaultInstall,4,0";
/* The 'No UI' flag seems to have no effect whatsoever on Windows.
* So only do this test in interactive mode.
*/
if (winetest_interactive)
{
/* try an invalid cmdline */
hr = pLaunchINFSection(NULL, NULL, NULL, 0);
ok(hr == 1, "Expected 1, got %d\n", hr);
}
CreateDirectoryA("one", NULL);
create_inf_file("one\\test.inf");
/* try a full path to the INF */
lstrcpy(cmdline, CURR_DIR);
lstrcat(cmdline, "\\");
lstrcat(cmdline, "one\\test.inf,DefaultInstall,,4");
hr = pLaunchINFSection(NULL, NULL, cmdline, 0);
ok(hr == 0, "Expected 0, got %d\n", hr);
DeleteFileA("one\\test.inf");
RemoveDirectoryA("one");
create_inf_file("test.inf");
/* try just the INF filename */
hr = pLaunchINFSection(NULL, NULL, file, 0);
ok(hr == 0, "Expected 0, got %d\n", hr);
DeleteFileA("test.inf");
}
static void test_LaunchINFSectionEx(void)
{
HRESULT hr;
char cmdline[MAX_PATH];
create_inf_file("test.inf");
/* try an invalid CAB filename with an absolute INF name */
lstrcpy(cmdline, CURR_DIR);
lstrcat(cmdline, "\\");
lstrcat(cmdline, "test.inf,DefaultInstall,c:imacab.cab,4");
hr = pLaunchINFSectionEx(NULL, NULL, cmdline, 0);
ok(hr == 0, "Expected 0, got %d\n", hr);
/* The 'No UI' flag seems to have no effect whatsoever on Windows.
* So only do this test in interactive mode.
*/
if (winetest_interactive)
{
/* try an invalid CAB filename with a relative INF name */
lstrcpy(cmdline, "test.inf,DefaultInstall,c:imacab.cab,4");
hr = pLaunchINFSectionEx(NULL, NULL, cmdline, 0);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %d\n", hr);
}
DeleteFileA("test.inf");
}
START_TEST(install)
{
if (!init_function_pointers())
return;
GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
test_RunSetupCommand();
test_LaunchINFSection();
test_LaunchINFSectionEx();
}

View file

@ -0,0 +1,19 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_advpack(void);
extern void func_files(void);
extern void func_install(void);
const struct test winetest_testlist[] =
{
{ "advpack", func_advpack },
{ "files", func_files },
{ "install", func_install },
{ 0, 0 }
};

View file

@ -0,0 +1,320 @@
/* Unit tests for autocomplete
*
* Copyright 2007 Mikolaj Zalewski
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdarg.h>
#include <windows.h>
#include <shlobj.h>
#include <shlwapi.h>
#include "wine/test.h"
#define stop_on_error(exp) \
{ \
HRESULT res = (exp); \
if (FAILED(res)) \
{ \
ok(FALSE, #exp " failed: %x\n", res); \
return; \
} \
}
#define ole_ok(exp) \
{ \
HRESULT res = (exp); \
if (res != S_OK) \
ok(FALSE, #exp " failed: %x\n", res); \
}
LPWSTR strdup_AtoW(LPCSTR str)
{
int size = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
LPWSTR wstr = (LPWSTR)CoTaskMemAlloc((size + 1)*sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, size+1);
return wstr;
}
typedef struct
{
IEnumStringVtbl *vtbl;
IACListVtbl *aclVtbl;
LONG ref;
HRESULT expret;
INT expcount;
INT pos;
INT limit;
const char **data;
} TestACL;
extern IEnumStringVtbl TestACLVtbl;
extern IACListVtbl TestACL_ACListVtbl;
static TestACL *impl_from_IACList(IACList *iface)
{
return (TestACL *)((char *)iface - FIELD_OFFSET(TestACL, aclVtbl));
}
static TestACL *TestACL_Constructor(int limit, const char **strings)
{
TestACL *This = CoTaskMemAlloc(sizeof(TestACL));
ZeroMemory(This, sizeof(*This));
This->vtbl = &TestACLVtbl;
This->aclVtbl = &TestACL_ACListVtbl;
This->ref = 1;
This->expret = S_OK;
This->limit = limit;
This->data = strings;
return This;
}
ULONG STDMETHODCALLTYPE TestACL_AddRef(IEnumString *iface)
{
TestACL *This = (TestACL *)iface;
trace("ACL(%p): addref (%d)\n", This, This->ref+1);
return InterlockedIncrement(&This->ref);
}
ULONG STDMETHODCALLTYPE TestACL_Release(IEnumString *iface)
{
TestACL *This = (TestACL *)iface;
ULONG res;
res = InterlockedDecrement(&This->ref);
trace("ACL(%p): release (%d)\n", This, res);
return res;
}
HRESULT STDMETHODCALLTYPE TestACL_QueryInterface(IEnumString *iface, REFIID iid, LPVOID *ppvOut)
{
TestACL *This = (TestACL *)iface;
*ppvOut = NULL;
if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IEnumString))
{
*ppvOut = iface;
}
else if (IsEqualGUID(iid, &IID_IACList))
{
*ppvOut = &This->aclVtbl;
}
if (*ppvOut)
{
iface->lpVtbl->AddRef(iface);
return S_OK;
}
#if 0 /* IID_IEnumACString not defined yet in wine */
if (!IsEqualGUID(iid, &IID_IEnumACString))
trace("unknown interface queried\n");
#endif
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE TestACL_Next(IEnumString *iface, ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched)
{
TestACL *This = (TestACL *)iface;
ULONG i;
trace("ACL(%p): read %d item(s)\n", This, celt);
for (i = 0; i < celt; i++)
{
if (This->pos >= This->limit)
break;
rgelt[i] = strdup_AtoW(This->data[This->pos]);
This->pos++;
}
if (pceltFetched)
*pceltFetched = i;
if (i == celt)
return S_OK;
return S_FALSE;
}
HRESULT STDMETHODCALLTYPE TestACL_Skip(IEnumString *iface, ULONG celt)
{
ok(FALSE, "Unexpected call to TestACL_Skip\n");
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE TestACL_Clone(IEnumString *iface, IEnumString **out)
{
ok(FALSE, "Unexpected call to TestACL_Clone\n");
return E_OUTOFMEMORY;
}
HRESULT STDMETHODCALLTYPE TestACL_Reset(IEnumString *iface)
{
TestACL *This = (TestACL *)iface;
trace("ACL(%p): Reset\n", This);
This->pos = 0;
return S_OK;
}
HRESULT STDMETHODCALLTYPE TestACL_Expand(IACList *iface, LPCOLESTR str)
{
TestACL *This = impl_from_IACList(iface);
trace("ACL(%p): Expand\n", impl_from_IACList(iface));
This->expcount++;
return This->expret;
}
IEnumStringVtbl TestACLVtbl =
{
TestACL_QueryInterface,
TestACL_AddRef,
TestACL_Release,
TestACL_Next,
TestACL_Skip,
TestACL_Reset,
TestACL_Clone
};
ULONG STDMETHODCALLTYPE TestACL_ACList_AddRef(IACList *iface)
{
return TestACL_AddRef((IEnumString *)impl_from_IACList(iface));
}
ULONG STDMETHODCALLTYPE TestACL_ACList_Release(IACList *iface)
{
return TestACL_Release((IEnumString *)impl_from_IACList(iface));
}
HRESULT STDMETHODCALLTYPE TestACL_ACList_QueryInterface(IACList *iface, REFIID iid, LPVOID *ppvout)
{
return TestACL_QueryInterface((IEnumString *)impl_from_IACList(iface), iid, ppvout);
}
IACListVtbl TestACL_ACListVtbl =
{
TestACL_ACList_QueryInterface,
TestACL_ACList_AddRef,
TestACL_ACList_Release,
TestACL_Expand
};
#define expect_str(obj, str) \
{ \
ole_ok(obj->lpVtbl->Next(obj, 1, &wstr, &i)); \
ok(i == 1, "Expected i == 1, got %d\n", i); \
ok(str[0] == wstr[0], "String mismatch\n"); \
}
#define expect_end(obj) \
ok(obj->lpVtbl->Next(obj, 1, &wstr, &i) == S_FALSE, "Unexpected return from Next\n");
static void test_ACLMulti(void)
{
const char *strings1[] = {"a", "c", "e"};
const char *strings2[] = {"a", "b", "d"};
WCHAR exp[] = {'A','B','C',0};
IEnumString *obj;
TestACL *acl1, *acl2;
IACList *acl;
IObjMgr *mgr;
LPWSTR wstr;
LPWSTR wstrtab[15];
LPVOID tmp;
UINT i;
stop_on_error(CoCreateInstance(&CLSID_ACLMulti, NULL, CLSCTX_INPROC, &IID_IEnumString, (LPVOID *)&obj));
stop_on_error(obj->lpVtbl->QueryInterface(obj, &IID_IACList, (LPVOID *)&acl));
ok(obj->lpVtbl->QueryInterface(obj, &IID_IACList2, &tmp) == E_NOINTERFACE,
"Unexpected interface IACList2 in ACLMulti\n");
stop_on_error(obj->lpVtbl->QueryInterface(obj, &IID_IObjMgr, (LPVOID *)&mgr));
#if 0 /* IID_IEnumACString not defined yet in wine */
ole_ok(obj->lpVtbl->QueryInterface(obj, &IID_IEnumACString, &unk));
if (unk != NULL)
unk->lpVtbl->Release(unk);
#endif
ok(obj->lpVtbl->Next(obj, 1, (LPOLESTR *)&tmp, &i) == S_FALSE, "Unexpected return from Next\n");
ok(i == 0, "Unexpected fetched value %d\n", i);
ok(obj->lpVtbl->Next(obj, 44, (LPOLESTR *)&tmp, &i) == S_FALSE, "Unexpected return from Next\n");
ok(obj->lpVtbl->Skip(obj, 1) == E_NOTIMPL, "Unexpected return from Skip\n");
ok(obj->lpVtbl->Clone(obj, (IEnumString **)&tmp) == E_OUTOFMEMORY, "Unexpected return from Clone\n");
ole_ok(acl->lpVtbl->Expand(acl, exp));
acl1 = TestACL_Constructor(3, strings1);
acl2 = TestACL_Constructor(3, strings2);
stop_on_error(mgr->lpVtbl->Append(mgr, (IUnknown *)acl1));
stop_on_error(mgr->lpVtbl->Append(mgr, (IUnknown *)acl2));
ok(mgr->lpVtbl->Append(mgr, NULL) == E_FAIL, "Unexpected return from Append\n");
expect_str(obj, "a");
expect_str(obj, "c");
expect_str(obj, "e");
expect_str(obj, "a");
expect_str(obj, "b");
expect_str(obj, "d");
expect_end(obj);
ole_ok(obj->lpVtbl->Reset(obj));
ok(acl1->pos == 0, "acl1 not reset\n");
ok(acl2->pos == 0, "acl2 not reset\n");
ole_ok(acl->lpVtbl->Expand(acl, exp));
ok(acl1->expcount == 1, "expcount - expected 1, got %d\n", acl1->expcount);
ok(acl2->expcount == 0, "expcount - expected 0, got %d\n", acl2->expcount);
ole_ok(obj->lpVtbl->Next(obj, 15, wstrtab, &i));
ok(i == 1, "Expected i == 1, got %d\n", i);
ole_ok(obj->lpVtbl->Next(obj, 15, wstrtab, &i));
ole_ok(obj->lpVtbl->Next(obj, 15, wstrtab, &i));
ole_ok(obj->lpVtbl->Next(obj, 15, wstrtab, &i));
ole_ok(acl->lpVtbl->Expand(acl, exp));
ok(acl1->expcount == 2, "expcount - expected 1, got %d\n", acl1->expcount);
ok(acl2->expcount == 0, "expcount - expected 0, got %d\n", acl2->expcount);
acl1->expret = S_FALSE;
ole_ok(acl->lpVtbl->Expand(acl, exp));
ok(acl1->expcount == 3, "expcount - expected 1, got %d\n", acl1->expcount);
ok(acl2->expcount == 1, "expcount - expected 0, got %d\n", acl2->expcount);
acl1->expret = E_NOTIMPL;
ole_ok(acl->lpVtbl->Expand(acl, exp));
ok(acl1->expcount == 4, "expcount - expected 1, got %d\n", acl1->expcount);
ok(acl2->expcount == 2, "expcount - expected 0, got %d\n", acl2->expcount);
acl2->expret = E_OUTOFMEMORY;
ok(acl->lpVtbl->Expand(acl, exp) == E_OUTOFMEMORY, "Unexpected Expand return\n");
acl2->expret = E_FAIL;
ok(acl->lpVtbl->Expand(acl, exp) == E_FAIL, "Unexpected Expand return\n");
stop_on_error(mgr->lpVtbl->Remove(mgr, (IUnknown *)acl1));
ok(acl1->ref == 1, "acl1 not released\n");
expect_end(obj);
obj->lpVtbl->Reset(obj);
expect_str(obj, "a");
expect_str(obj, "b");
expect_str(obj, "d");
expect_end(obj);
obj->lpVtbl->Release(obj);
acl->lpVtbl->Release(acl);
ok(mgr->lpVtbl->Release(mgr) == 0, "Unexpected references\n");
ok(acl1->ref == 1, "acl1 not released\n");
ok(acl2->ref == 1, "acl2 not released\n");
}
START_TEST(autocomplete)
{
CoInitialize(NULL);
test_ACLMulti();
CoUninitialize();
}

View file

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="browseui_winetest" type="win32cui" installbase="bin" installname="browseui_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="browseui_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>ole32</library>
<library>user32</library>
<library>kernel32</library>
<library>uuid</library>
<library>ntdll</library>
<file>autocomplete.c</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,15 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_autocomplete(void);
const struct test winetest_testlist[] =
{
{ "autocomplete", func_autocomplete },
{ 0, 0 }
};

View file

@ -1,9 +1,15 @@
<module name="cabinet_winetest" type="win32cui" installbase="bin" installname="cabinet_winetest.exe" allowwarnings="true">
<include base="cabinet_winetest">.</include>
<define name="__USE_W32API" />
<library>cabinet</library>
<library>kernel32</library>
<library>ntdll</library>
<file>extract.c</file>
<file>testlist.c</file>
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="cabinet_winetest" type="win32cui" installbase="bin" installname="cabinet_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="cabinet_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>cabinet</library>
<library>user32</library>
<library>kernel32</library>
<library>ntdll</library>
<file>extract.c</file>
<file>fdi.c</file>
<file>testlist.c</file>
</module>

View file

@ -20,7 +20,8 @@
#include <stdio.h>
#include <windows.h>
#include <fci.h>
#include "fci.h"
#include "fdi.h"
#include "wine/test.h"
/* make the max size large so there is only one cab file */
@ -31,41 +32,39 @@
* because they are undocumented in windows.
*/
/* EXTRACTdest flags */
/* SESSION Operation */
#define EXTRACT_FILLFILELIST 0x00000001
#define EXTRACT_EXTRACTFILES 0x00000002
struct ExtractFileList {
LPSTR filename;
struct ExtractFileList *next;
BOOL unknown; /* always 1L */
struct FILELIST{
LPSTR FileName;
struct FILELIST *next;
BOOL DoExtract;
};
/* the first parameter of the function extract */
typedef struct {
long result1; /* 0x000 */
long unknown1[3]; /* 0x004 */
struct ExtractFileList *filelist; /* 0x010 */
long filecount; /* 0x014 */
long flags; /* 0x018 */
char directory[0x104]; /* 0x01c */
char lastfile[0x20c]; /* 0x120 */
} EXTRACTDEST;
INT FileSize;
ERF Error;
struct FILELIST *FileList;
INT FileCount;
INT Operation;
CHAR Destination[MAX_PATH];
CHAR CurrentFile[MAX_PATH];
CHAR Reserved[MAX_PATH];
struct FILELIST *FilterList;
} SESSION;
/* function pointers */
HMODULE hCabinet;
static HRESULT (WINAPI *pExtract)(EXTRACTDEST*, LPCSTR);
static HRESULT (WINAPI *pExtract)(SESSION*, LPCSTR);
CHAR CURR_DIR[MAX_PATH];
static void init_function_pointers(void)
{
hCabinet = LoadLibraryA("cabinet.dll");
hCabinet = GetModuleHandleA("cabinet.dll");
if (hCabinet)
{
pExtract = (void *)GetProcAddress(hCabinet, "Extract");
}
pExtract = (void *)GetProcAddress(hCabinet, "Extract");
}
/* creates a file with the specified name for tests */
@ -144,9 +143,10 @@ static INT_PTR fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
DWORD dwAccess = 0;
DWORD dwShareMode = 0;
DWORD dwCreateDisposition = OPEN_EXISTING;
dwAccess = GENERIC_READ | GENERIC_WRITE;
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
/* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
dwCreateDisposition = OPEN_EXISTING;
@ -166,7 +166,7 @@ static UINT fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
HANDLE handle = (HANDLE)hf;
DWORD dwRead;
BOOL res;
res = ReadFile(handle, memory, cb, &dwRead, NULL);
ok(res, "Failed to ReadFile\n");
@ -197,7 +197,7 @@ static long fci_seek(INT_PTR hf, long dist, int seektype, int *err, void *pv)
{
HANDLE handle = (HANDLE)hf;
DWORD ret;
ret = SetFilePointer(handle, dist, NULL, seektype);
ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
@ -247,7 +247,7 @@ static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
res = GetFileInformationByHandle(handle, &finfo);
ok(res, "Expected GetFileInformationByHandle to succeed\n");
FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
FileTimeToDosDateTime(&filetime, pdate, ptime);
@ -288,6 +288,10 @@ static void create_cab_file(void)
CCAB cabParams;
HFCI hfci;
ERF erf;
static CHAR a_txt[] = "a.txt",
b_txt[] = "b.txt",
testdir_c_txt[] = "testdir\\c.txt",
testdir_d_txt[] = "testdir\\d.txt";
BOOL res;
set_cab_parameters(&cabParams);
@ -298,10 +302,10 @@ static void create_cab_file(void)
ok(hfci != NULL, "Failed to create an FCI context\n");
add_file(hfci, "a.txt");
add_file(hfci, "b.txt");
add_file(hfci, "testdir\\c.txt");
add_file(hfci, "testdir\\d.txt");
add_file(hfci, a_txt);
add_file(hfci, b_txt);
add_file(hfci, testdir_c_txt);
add_file(hfci, testdir_d_txt);
res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
ok(res, "Failed to flush the cabinet\n");
@ -310,10 +314,26 @@ static void create_cab_file(void)
ok(res, "Failed to destroy the cabinet\n");
}
static BOOL check_list(struct FILELIST **node, const char *filename, BOOL do_extract)
{
if (!*node)
return FALSE;
if (lstrcmpA((*node)->FileName, filename))
return FALSE;
if ((*node)->DoExtract != do_extract)
return FALSE;
*node = (*node)->next;
return TRUE;
}
static void test_Extract(void)
{
EXTRACTDEST extractDest;
SESSION session;
HRESULT res;
struct FILELIST *node;
/* native windows crashes if
* - invalid parameters are sent in
@ -322,58 +342,341 @@ static void test_Extract(void)
*/
/* try to extract all files */
ZeroMemory(&extractDest, sizeof(EXTRACTDEST));
lstrcpyA(extractDest.directory, "dest");
extractDest.flags = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES;
res = pExtract(&extractDest, "extract.cab");
ok(res == S_OK, "Expected S_OK, got %ld\n", res);
ZeroMemory(&session, sizeof(SESSION));
lstrcpyA(session.Destination, "dest");
session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES;
res = pExtract(&session, "extract.cab");
node = session.FileList;
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
ok(session.Error.erfOper == FDIERROR_NONE,
"Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount);
ok(session.Operation == (EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES),
"Expected EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
"Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
ok(!session.FilterList, "Expected empty filter list\n");
ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n");
ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n");
/* try fill file list operation */
ZeroMemory(&extractDest, sizeof(EXTRACTDEST));
lstrcpyA(extractDest.directory, "dest");
extractDest.flags = EXTRACT_FILLFILELIST;
res = pExtract(&extractDest, "extract.cab");
ok(res == S_OK, "Expected S_OK, got %ld\n", res);
ZeroMemory(&session, sizeof(SESSION));
lstrcpyA(session.Destination, "dest");
session.Operation = EXTRACT_FILLFILELIST;
res = pExtract(&session, "extract.cab");
node = session.FileList;
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
ok(session.Error.erfOper == FDIERROR_NONE,
"Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount);
ok(session.Operation == EXTRACT_FILLFILELIST,
"Expected EXTRACT_FILLFILELIST, got %d\n", session.Operation);
ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
"Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
ok(!session.FilterList, "Expected empty filter list\n");
ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
ok(extractDest.filecount == 4, "Expected 4 files, got %ld\n", extractDest.filecount);
ok(!lstrcmpA(extractDest.lastfile, "dest\\testdir\\d.txt"),
"Expected last file to be dest\\testdir\\d.txt, got %s\n", extractDest.lastfile);
ok(check_list(&node, "testdir\\d.txt", TRUE), "list entry wrong\n");
ok(check_list(&node, "testdir\\c.txt", TRUE), "list entry wrong\n");
ok(check_list(&node, "b.txt", TRUE), "list entry wrong\n");
ok(check_list(&node, "a.txt", TRUE), "list entry wrong\n");
/* try extract files operation once file list is filled */
extractDest.flags = EXTRACT_EXTRACTFILES;
res = pExtract(&extractDest, "extract.cab");
ok(res == S_OK, "Expected S_OK, got %ld\n", res);
session.Operation = EXTRACT_EXTRACTFILES;
res = pExtract(&session, "extract.cab");
node = session.FileList;
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
ok(session.Error.erfOper == FDIERROR_NONE,
"Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount);
ok(session.Operation == EXTRACT_EXTRACTFILES,
"Expected EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
"Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
ok(!session.FilterList, "Expected empty filter list\n");
ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n");
ok(RemoveDirectoryA("dest"), "Expected dest to exist\n");
ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n");
/* Extract does not extract files if the dest dir does not exist */
res = pExtract(&extractDest, "extract.cab");
ok(res == S_OK, "Expected S_OK, got %ld\n", res);
res = pExtract(&session, "extract.cab");
node = session.FileList;
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
ok(session.Error.erfOper == FDIERROR_NONE,
"Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount);
ok(session.Operation == EXTRACT_EXTRACTFILES,
"Expected EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
"Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
ok(!session.FilterList, "Expected empty filter list\n");
ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n");
/* remove two of the files in the list */
extractDest.filelist->next = extractDest.filelist->next->next;
extractDest.filelist->next->next = NULL;
session.FileList->next = session.FileList->next->next;
session.FileList->next->next = NULL;
session.FilterList = NULL;
CreateDirectoryA("dest", NULL);
res = pExtract(&extractDest, "extract.cab");
ok(res == S_OK, "Expected S_OK, got %ld\n", res);
res = pExtract(&session, "extract.cab");
node = session.FileList;
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
ok(session.Error.erfOper == FDIERROR_NONE,
"Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount);
ok(session.Operation == EXTRACT_EXTRACTFILES,
"Expected EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
"Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
ok(!session.FilterList, "Expected empty filter list\n");
ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n");
ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n");
ok(!check_list(&node, "a.txt", FALSE), "list entry wrong\n");
session.Operation = EXTRACT_FILLFILELIST;
session.FileList = NULL;
res = pExtract(&session, "extract.cab");
node = session.FileList;
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
ok(session.Error.erfOper == FDIERROR_NONE,
"Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
ok(session.FileCount == 8, "Expected 8, got %d\n", session.FileCount);
ok(session.Operation == EXTRACT_FILLFILELIST,
"Expected EXTRACT_FILLFILELIST, got %d\n", session.Operation);
ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
"Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
ok(!session.FilterList, "Expected empty filter list\n");
ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
ok(check_list(&node, "testdir\\d.txt", TRUE), "list entry wrong\n");
ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
ok(!check_list(&node, "b.txt", FALSE), "list entry wrong\n");
ok(!check_list(&node, "a.txt", FALSE), "list entry wrong\n");
session.Operation = 0;
res = pExtract(&session, "extract.cab");
node = session.FileList;
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
ok(session.Error.erfOper == FDIERROR_NONE,
"Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
ok(session.FileCount == 8, "Expected 8, got %d\n", session.FileCount);
ok(session.Operation == 0, "Expected 0, got %d\n", session.Operation);
ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
"Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
ok(!session.FilterList, "Expected empty filter list\n");
ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
ok(check_list(&node, "testdir\\d.txt", TRUE), "list entry wrong\n");
ok(check_list(&node, "testdir\\c.txt", TRUE), "list entry wrong\n");
ok(check_list(&node, "b.txt", TRUE), "list entry wrong\n");
ok(check_list(&node, "a.txt", TRUE), "list entry wrong\n");
session.Operation = 0;
session.FilterList = session.FileList;
res = pExtract(&session, "extract.cab");
node = session.FileList;
ok(res == S_OK, "Expected S_OK, got %d\n", res);
ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
ok(session.Error.erfOper == FDIERROR_NONE,
"Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
ok(session.FileCount == 8, "Expected 8, got %d\n", session.FileCount);
ok(session.Operation == 0, "Expected 0, got %d\n", session.Operation);
ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
"Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n");
node = session.FilterList;
ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n");
/* cabinet does not exist */
ZeroMemory(&session, sizeof(SESSION));
lstrcpyA(session.Destination, "dest");
session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES;
res = pExtract(&session, "nonexistent.cab");
node = session.FileList;
ok(res == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
"Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", res);
ok(session.Error.erfOper == FDIERROR_CABINET_NOT_FOUND,
"Expected FDIERROR_CABINET_NOT_FOUND, got %d\n", session.Error.erfOper);
ok(session.FileSize == 0, "Expected 0, got %d\n", session.FileSize);
ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
ok(session.Error.fError == TRUE, "Expected TRUE, got %d\n", session.Error.fError);
ok(session.FileCount == 0, "Expected 0, got %d\n", session.FileCount);
ok(session.Operation == (EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES),
"Expected EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
ok(!*session.CurrentFile, "Expected empty string, got %s\n", session.CurrentFile);
ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
ok(!session.FilterList, "Expected empty filter list\n");
ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
ok(!check_list(&node, "testdir\\d.txt", FALSE), "list entry should not exist\n");
ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry should not exist\n");
ok(!check_list(&node, "b.txt", FALSE), "list entry should not exist\n");
ok(!check_list(&node, "a.txt", FALSE), "list entry should not exist\n");
/* first file exists */
createTestFile("dest\\a.txt");
SetFileAttributes("dest\\a.txt", FILE_ATTRIBUTE_READONLY);
ZeroMemory(&session, sizeof(SESSION));
lstrcpyA(session.Destination, "dest");
session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES;
res = pExtract(&session, "extract.cab");
node = session.FileList;
todo_wine
{
ok(res == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) || res == E_FAIL,
"Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) or E_FAIL, got %08x\n", res);
ok(session.FileSize == 6, "Expected 6, got %d\n", session.FileSize);
ok(session.Error.erfOper == FDIERROR_USER_ABORT,
"Expected FDIERROR_USER_ABORT, got %d\n", session.Error.erfOper);
ok(session.Error.fError == TRUE, "Expected TRUE, got %d\n", session.Error.fError);
ok(session.FileCount == 1, "Expected 1, got %d\n", session.FileCount);
ok(!lstrcmpA(session.CurrentFile, "dest\\a.txt"),
"Expected dest\\a.txt, got %s\n", session.CurrentFile);
}
ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
ok(session.Operation == (EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES),
"Expected EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
ok(!session.FilterList, "Expected empty filter list\n");
ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
todo_wine
{
ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
ok(!check_list(&node, "testdir\\d.txt", FALSE), "list entry should not exist\n");
ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry should not exist\n");
ok(!check_list(&node, "b.txt", FALSE), "list entry should not exist\n");
}
ok(!check_list(&node, "a.txt", FALSE), "list entry should not exist\n");
SetFileAttributesA("dest\\a.txt", FILE_ATTRIBUTE_NORMAL);
DeleteFileA("dest\\a.txt");
/* third file exists */
createTestFile("dest\\testdir\\c.txt");
SetFileAttributes("dest\\testdir\\c.txt", FILE_ATTRIBUTE_READONLY);
ZeroMemory(&session, sizeof(SESSION));
lstrcpyA(session.Destination, "dest");
session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES;
res = pExtract(&session, "extract.cab");
todo_wine
{
ok(res == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) || res == E_FAIL,
"Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) or E_FAIL, got %08x\n", res);
ok(session.FileSize == 26, "Expected 26, got %d\n", session.FileSize);
ok(session.Error.erfOper == FDIERROR_USER_ABORT,
"Expected FDIERROR_USER_ABORT, got %d\n", session.Error.erfOper);
ok(session.Error.fError == TRUE, "Expected TRUE, got %d\n", session.Error.fError);
ok(session.FileCount == 3, "Expected 3, got %d\n", session.FileCount);
ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\c.txt"),
"Expected dest\\c.txt, got %s\n", session.CurrentFile);
}
ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
ok(session.Operation == (EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES),
"Expected EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
ok(!session.FilterList, "Expected empty filter list\n");
ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
todo_wine
{
ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
}
ok(!check_list(&node, "testdir\\d.txt", FALSE), "list entry should not exist\n");
ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
ok(!check_list(&node, "b.txt", FALSE), "list entry wrong\n");
ok(check_list(&node, "a.txt", TRUE), "list entry wrong\n");
SetFileAttributesA("dest\\testdir\\c.txt", FILE_ATTRIBUTE_NORMAL);
DeleteFileA("dest\\testdir\\c.txt");
ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n");
ok(RemoveDirectoryA("dest"), "Expected dest\\testdir to exist\n");
ok(RemoveDirectoryA("dest"), "Expected dest to exist\n");
}
START_TEST(extract)

View file

@ -0,0 +1,580 @@
/*
* Unit tests for the File Decompression Interface
*
* Copyright (C) 2006 James Hawkins
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
#include <windows.h>
#include "fci.h"
#include "fdi.h"
#include "wine/test.h"
/* make the max size large so there is only one cab file */
#define MEDIA_SIZE 999999999
#define FOLDER_THRESHOLD 900000
CHAR CURR_DIR[MAX_PATH];
/* FDI callbacks */
static void *fdi_alloc(ULONG cb)
{
return HeapAlloc(GetProcessHeap(), 0, cb);
}
static void *fdi_alloc_bad(ULONG cb)
{
return NULL;
}
static void fdi_free(void *pv)
{
HeapFree(GetProcessHeap(), 0, pv);
}
static INT_PTR fdi_open(char *pszFile, int oflag, int pmode)
{
HANDLE handle;
handle = CreateFileA(pszFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL );
if (handle == INVALID_HANDLE_VALUE)
return 0;
return (INT_PTR) handle;
}
static UINT fdi_read(INT_PTR hf, void *pv, UINT cb)
{
HANDLE handle = (HANDLE) hf;
DWORD dwRead;
if (ReadFile(handle, pv, cb, &dwRead, NULL))
return dwRead;
return 0;
}
static UINT fdi_write(INT_PTR hf, void *pv, UINT cb)
{
HANDLE handle = (HANDLE) hf;
DWORD dwWritten;
if (WriteFile(handle, pv, cb, &dwWritten, NULL))
return dwWritten;
return 0;
}
static int fdi_close(INT_PTR hf)
{
HANDLE handle = (HANDLE) hf;
return CloseHandle(handle) ? 0 : -1;
}
static long fdi_seek(INT_PTR hf, long dist, int seektype)
{
HANDLE handle = (HANDLE) hf;
return SetFilePointer(handle, dist, NULL, seektype);
}
static void test_FDICreate(void)
{
HFDI hfdi;
ERF erf;
erf.erfOper = 0xcafefeed;
erf.erfType = 0xdeadbabe;
erf.fError = 0xdecaface;
/* native crashes if pfnalloc is NULL */
/* FDICreate does not crash with a NULL pfnfree,
* but FDIDestroy will crash when it tries to access it.
*/
if (0)
{
SetLastError(0xdeadbeef);
hfdi = FDICreate(fdi_alloc, NULL, fdi_open, fdi_read,
fdi_write, fdi_close, fdi_seek,
cpuUNKNOWN, &erf);
ok(hfdi != NULL, "Expected non-NULL context\n");
ok(GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got %d\n", GetLastError());
ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
FDIDestroy(hfdi);
}
SetLastError(0xdeadbeef);
hfdi = FDICreate(fdi_alloc, fdi_free, NULL, fdi_read,
fdi_write, fdi_close, fdi_seek,
cpuUNKNOWN, &erf);
ok(hfdi != NULL, "Expected non-NULL context\n");
ok(GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got %d\n", GetLastError());
ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
FDIDestroy(hfdi);
SetLastError(0xdeadbeef);
hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, NULL,
fdi_write, fdi_close, fdi_seek,
cpuUNKNOWN, &erf);
ok(hfdi != NULL, "Expected non-NULL context\n");
ok(GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got %d\n", GetLastError());
ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
FDIDestroy(hfdi);
SetLastError(0xdeadbeef);
hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
NULL, fdi_close, fdi_seek,
cpuUNKNOWN, &erf);
ok(hfdi != NULL, "Expected non-NULL context\n");
ok(GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got %d\n", GetLastError());
ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
FDIDestroy(hfdi);
SetLastError(0xdeadbeef);
hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
fdi_write, NULL, fdi_seek,
cpuUNKNOWN, &erf);
ok(hfdi != NULL, "Expected non-NULL context\n");
ok(GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got %d\n", GetLastError());
ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
FDIDestroy(hfdi);
SetLastError(0xdeadbeef);
hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
fdi_write, fdi_close, NULL,
cpuUNKNOWN, &erf);
ok(hfdi != NULL, "Expected non-NULL context\n");
ok(GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got %d\n", GetLastError());
ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
FDIDestroy(hfdi);
SetLastError(0xdeadbeef);
hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
fdi_write, fdi_close, fdi_seek,
cpuUNKNOWN, NULL);
ok(hfdi != NULL, "Expected non-NULL context\n");
ok(GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got %d\n", GetLastError());
ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
FDIDestroy(hfdi);
/* bad cpu type */
SetLastError(0xdeadbeef);
hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
fdi_write, fdi_close, fdi_seek,
0xcafebabe, &erf);
ok(hfdi != NULL, "Expected non-NULL context\n");
ok(GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got %d\n", GetLastError());
ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
FDIDestroy(hfdi);
/* pfnalloc fails */
SetLastError(0xdeadbeef);
hfdi = FDICreate(fdi_alloc_bad, fdi_free, fdi_open, fdi_read,
fdi_write, fdi_close, fdi_seek,
cpuUNKNOWN, &erf);
ok(hfdi == NULL, "Expected NULL context, got %p\n", hfdi);
ok(erf.erfOper == FDIERROR_ALLOC_FAIL,
"Expected FDIERROR_ALLOC_FAIL, got %d\n", erf.erfOper);
ok(erf.fError == TRUE, "Expected TRUE, got %d\n", erf.fError);
todo_wine
{
ok(GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got %d\n", GetLastError());
ok(erf.erfType == 0, "Expected 0, got %d\n", erf.erfType);
}
}
static void test_FDIDestroy(void)
{
HFDI hfdi;
ERF erf;
BOOL ret;
/* native crashes if hfdi is NULL or invalid */
hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
fdi_write, fdi_close, fdi_seek,
cpuUNKNOWN, &erf);
ok(hfdi != NULL, "Expected non-NULL context\n");
/* successfully destroy hfdi */
ret = FDIDestroy(hfdi);
ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
/* native crashes if you try to destroy hfdi twice */
if (0)
{
/* try to destroy hfdi again */
ret = FDIDestroy(hfdi);
ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
}
}
static void createTestFile(const CHAR *name)
{
HANDLE file;
DWORD written;
file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
WriteFile(file, name, strlen(name), &written, NULL);
WriteFile(file, "\n", strlen("\n"), &written, NULL);
CloseHandle(file);
}
static void create_test_files(void)
{
int len;
GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
len = lstrlenA(CURR_DIR);
if(len && (CURR_DIR[len-1] == '\\'))
CURR_DIR[len-1] = 0;
createTestFile("a.txt");
createTestFile("b.txt");
CreateDirectoryA("testdir", NULL);
createTestFile("testdir\\c.txt");
createTestFile("testdir\\d.txt");
}
static void delete_test_files(void)
{
DeleteFileA("a.txt");
DeleteFileA("b.txt");
DeleteFileA("testdir\\c.txt");
DeleteFileA("testdir\\d.txt");
RemoveDirectoryA("testdir");
DeleteFileA("extract.cab");
}
/* FCI callbacks */
static void *mem_alloc(ULONG cb)
{
return HeapAlloc(GetProcessHeap(), 0, cb);
}
static void mem_free(void *memory)
{
HeapFree(GetProcessHeap(), 0, memory);
}
static BOOL get_next_cabinet(PCCAB pccab, ULONG cbPrevCab, void *pv)
{
return TRUE;
}
static long progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
{
return 0;
}
static int file_placed(PCCAB pccab, char *pszFile, long cbFile,
BOOL fContinuation, void *pv)
{
return 0;
}
static INT_PTR fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
{
HANDLE handle;
DWORD dwAccess = 0;
DWORD dwShareMode = 0;
DWORD dwCreateDisposition = OPEN_EXISTING;
dwAccess = GENERIC_READ | GENERIC_WRITE;
/* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
dwCreateDisposition = OPEN_EXISTING;
else
dwCreateDisposition = CREATE_NEW;
handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
dwCreateDisposition, 0, NULL);
ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
return (INT_PTR)handle;
}
static UINT fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
{
HANDLE handle = (HANDLE)hf;
DWORD dwRead;
BOOL res;
res = ReadFile(handle, memory, cb, &dwRead, NULL);
ok(res, "Failed to ReadFile\n");
return dwRead;
}
static UINT fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
{
HANDLE handle = (HANDLE)hf;
DWORD dwWritten;
BOOL res;
res = WriteFile(handle, memory, cb, &dwWritten, NULL);
ok(res, "Failed to WriteFile\n");
return dwWritten;
}
static int fci_close(INT_PTR hf, int *err, void *pv)
{
HANDLE handle = (HANDLE)hf;
ok(CloseHandle(handle), "Failed to CloseHandle\n");
return 0;
}
static long fci_seek(INT_PTR hf, long dist, int seektype, int *err, void *pv)
{
HANDLE handle = (HANDLE)hf;
DWORD ret;
ret = SetFilePointer(handle, dist, NULL, seektype);
ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
return ret;
}
static int fci_delete(char *pszFile, int *err, void *pv)
{
BOOL ret = DeleteFileA(pszFile);
ok(ret, "Failed to DeleteFile %s\n", pszFile);
return 0;
}
static BOOL get_temp_file(char *pszTempName, int cbTempName, void *pv)
{
LPSTR tempname;
tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
GetTempFileNameA(".", "xx", 0, tempname);
if (tempname && (strlen(tempname) < (unsigned)cbTempName))
{
lstrcpyA(pszTempName, tempname);
HeapFree(GetProcessHeap(), 0, tempname);
return TRUE;
}
HeapFree(GetProcessHeap(), 0, tempname);
return FALSE;
}
static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
USHORT *pattribs, int *err, void *pv)
{
BY_HANDLE_FILE_INFORMATION finfo;
FILETIME filetime;
HANDLE handle;
DWORD attrs;
BOOL res;
handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
res = GetFileInformationByHandle(handle, &finfo);
ok(res, "Expected GetFileInformationByHandle to succeed\n");
FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
FileTimeToDosDateTime(&filetime, pdate, ptime);
attrs = GetFileAttributes(pszName);
ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
/* fixme: should convert attrs to *pattribs, make sure
* have a test that catches the fact that we don't?
*/
return (INT_PTR)handle;
}
static void add_file(HFCI hfci, char *file)
{
char path[MAX_PATH];
BOOL res;
lstrcpyA(path, CURR_DIR);
lstrcatA(path, "\\");
lstrcatA(path, file);
res = FCIAddFile(hfci, path, file, FALSE, get_next_cabinet, progress,
get_open_info, tcompTYPE_MSZIP);
ok(res, "Expected FCIAddFile to succeed\n");
}
static void set_cab_parameters(PCCAB pCabParams)
{
ZeroMemory(pCabParams, sizeof(CCAB));
pCabParams->cb = MEDIA_SIZE;
pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
pCabParams->setID = 0xbeef;
lstrcpyA(pCabParams->szCabPath, CURR_DIR);
lstrcatA(pCabParams->szCabPath, "\\");
lstrcpyA(pCabParams->szCab, "extract.cab");
}
static void create_cab_file(void)
{
CCAB cabParams;
HFCI hfci;
ERF erf;
static CHAR a_txt[] = "a.txt",
b_txt[] = "b.txt",
testdir_c_txt[] = "testdir\\c.txt",
testdir_d_txt[] = "testdir\\d.txt";
BOOL res;
set_cab_parameters(&cabParams);
hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
fci_read, fci_write, fci_close, fci_seek, fci_delete,
get_temp_file, &cabParams, NULL);
ok(hfci != NULL, "Failed to create an FCI context\n");
add_file(hfci, a_txt);
add_file(hfci, b_txt);
add_file(hfci, testdir_c_txt);
add_file(hfci, testdir_d_txt);
res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
ok(res, "Failed to flush the cabinet\n");
res = FCIDestroy(hfci);
ok(res, "Failed to destroy the cabinet\n");
}
static void test_FDIIsCabinet(void)
{
ERF erf;
BOOL ret;
HFDI hfdi;
INT_PTR fd;
FDICABINETINFO cabinfo;
char temp[] = "temp.txt";
char extract[] = "extract.cab";
create_test_files();
create_cab_file();
hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
fdi_write, fdi_close, fdi_seek,
cpuUNKNOWN, &erf);
ok(hfdi != NULL, "Expected non-NULL context\n");
/* native crashes if hfdi or cabinfo are NULL or invalid */
/* invalid file handle */
ZeroMemory(&cabinfo, sizeof(FDICABINETINFO));
SetLastError(0xdeadbeef);
ret = FDIIsCabinet(hfdi, (int)INVALID_HANDLE_VALUE, &cabinfo);
ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
ok(GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
ok(cabinfo.cbCabinet == 0, "Expected 0, got %ld\n", cabinfo.cbCabinet);
ok(cabinfo.cFiles == 0, "Expected 0, got %d\n", cabinfo.cFiles);
ok(cabinfo.cFolders == 0, "Expected 0, got %d\n", cabinfo.cFolders);
ok(cabinfo.iCabinet == 0, "Expected 0, got %d\n", cabinfo.iCabinet);
ok(cabinfo.setID == 0, "Expected 0, got %d\n", cabinfo.setID);
createTestFile("temp.txt");
fd = fdi_open(temp, 0, 0);
/* file handle doesn't point to a cabinet */
ZeroMemory(&cabinfo, sizeof(FDICABINETINFO));
SetLastError(0xdeadbeef);
ret = FDIIsCabinet(hfdi, fd, &cabinfo);
ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
ok(cabinfo.cbCabinet == 0, "Expected 0, got %ld\n", cabinfo.cbCabinet);
ok(cabinfo.cFiles == 0, "Expected 0, got %d\n", cabinfo.cFiles);
ok(cabinfo.cFolders == 0, "Expected 0, got %d\n", cabinfo.cFolders);
ok(cabinfo.iCabinet == 0, "Expected 0, got %d\n", cabinfo.iCabinet);
ok(cabinfo.setID == 0, "Expected 0, got %d\n", cabinfo.setID);
fdi_close(fd);
DeleteFileA("temp.txt");
/* try a real cab */
fd = fdi_open(extract, 0, 0);
ZeroMemory(&cabinfo, sizeof(FDICABINETINFO));
SetLastError(0xdeadbeef);
ret = FDIIsCabinet(hfdi, fd, &cabinfo);
ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
ok(cabinfo.cFiles == 4, "Expected 4, got %d\n", cabinfo.cFiles);
ok(cabinfo.cFolders == 1, "Expected 1, got %d\n", cabinfo.cFolders);
ok(cabinfo.setID == 0xbeef, "Expected 0xbeef, got %d\n", cabinfo.setID);
todo_wine
{
ok(cabinfo.cbCabinet == 182, "Expected 182, got %ld\n", cabinfo.cbCabinet);
ok(cabinfo.iCabinet == 0, "Expected 0, got %d\n", cabinfo.iCabinet);
}
fdi_close(fd);
FDIDestroy(hfdi);
delete_test_files();
}
START_TEST(fdi)
{
test_FDICreate();
test_FDIDestroy();
test_FDIIsCabinet();
}

View file

@ -1,3 +1,5 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@ -5,9 +7,11 @@
#include "wine/test.h"
extern void func_extract(void);
extern void func_fdi(void);
const struct test winetest_testlist[] =
{
{ "extract", func_extract },
{ "fdi", func_fdi },
{ 0, 0 }
};

View file

@ -0,0 +1,129 @@
/*
* tests for comcat functions
*
* Copyright 2006 Aric Stewart for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include <stdio.h>
#include <windows.h>
#include "objbase.h"
#include "comcat.h"
#include "wine/test.h"
#define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x \n", hr)
static void register_testentry(void)
{
HKEY hkey,hkey2;
RegCreateKeyA(HKEY_CLASSES_ROOT,"CLSID\\{deadcafe-beed-bead-dead-cafebeaddead}",
&hkey);
RegSetValueA(hkey,NULL,REG_SZ,"ComCat Test key",16);
RegCreateKeyA(hkey,
"Implemented Categories\\{deadcafe-0000-0000-0000-000000000000}",
&hkey2);
RegCloseKey(hkey);
RegCloseKey(hkey2);
}
static void unregister_testentry(void)
{
RegDeleteKeyA(HKEY_CLASSES_ROOT,
"CLSID\\{deadcafe-beed-bead-dead-cafebeaddead}\\Implemented Categories\\{deadcafe-0000-0000-0000-000000000000}");
RegDeleteKeyA(HKEY_CLASSES_ROOT,
"CLSID\\{deadcafe-beed-bead-dead-cafebeaddead}\\Implemented Categories");
RegDeleteKeyA(HKEY_CLASSES_ROOT,
"CLSID\\{deadcafe-beed-bead-dead-cafebeaddead}");
}
static void do_enum(void)
{
HRESULT hr;
REFCLSID rclsid = &CLSID_StdComponentCategoriesMgr;
ICatInformation *pICat = (ICatInformation*)0xdeadbeef;
GUID the_guid[1];
GUID the_cat[1];
GUID wanted_guid;
ULONG fetched = -1;
static WCHAR szCatID[] = {
'{',
'd','e','a','d','c','a','f','e',
'-','0','0','0','0','-','0','0','0','0',
'-','0','0','0','0',
'-','0','0','0','0','0','0','0','0','0','0','0','0',
'}',0};
static WCHAR szGuid[] = {
'{',
'd','e','a','d','c','a','f','e','-',
'b','e','e','d','-',
'b','e','a','d','-',
'd','e','a','d','-',
'c','a','f','e','b','e','a','d','d','e','a','d',
'}',0};
IEnumCLSID *pIEnum =(IEnumCLSID*)0xdeadcafe;
CLSIDFromString((LPOLESTR)szCatID,the_cat);
CLSIDFromString((LPOLESTR)szGuid,&wanted_guid);
OleInitialize(NULL);
hr = CoCreateInstance(rclsid,NULL,CLSCTX_INPROC_SERVER,
&IID_ICatInformation, (void **)&pICat);
ok_ole_success(hr, "CoCreateInstance");
hr = ICatInformation_EnumClassesOfCategories(pICat, -1, NULL, -1, NULL,
&pIEnum);
ok_ole_success(hr,"ICatInformation_EnumClassesOfCategories");
IEnumGUID_Release(pIEnum);
hr = ICatInformation_EnumClassesOfCategories(pICat, 1, the_cat, -1, NULL,
&pIEnum);
ok_ole_success(hr,"ICatInformation_EnumClassesOfCategories");
hr = IEnumGUID_Next(pIEnum,1,the_guid, &fetched);
ok (fetched == 0,"Fetched wrong number of guids %u\n",fetched);
IEnumGUID_Release(pIEnum);
register_testentry();
hr = ICatInformation_EnumClassesOfCategories(pICat, 1, the_cat, -1, NULL,
&pIEnum);
ok_ole_success(hr,"ICatInformation_EnumClassesOfCategories");
hr = IEnumGUID_Next(pIEnum,1,the_guid, &fetched);
ok (fetched == 1,"Fetched wrong number of guids %u\n",fetched);
ok (IsEqualGUID(the_guid,&wanted_guid),"Guids do not match\n");
IEnumGUID_Release(pIEnum);
ICatInformation_Release(pICat);
unregister_testentry();
OleUninitialize();
}
START_TEST(comcat)
{
do_enum();
}

View file

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="comcat_winetest" type="win32cui" installbase="bin" installname="comcat_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="comcat_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>ole32</library>
<library>advapi32</library>
<library>kernel32</library>
<library>uuid</library>
<library>ntdll</library>
<file>comcat.c</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,15 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_comcat(void);
const struct test winetest_testlist[] =
{
{ "comcat", func_comcat },
{ 0, 0 }
};

View file

@ -1,15 +1,15 @@
<module name="comdlg32_winetest" type="win32cui" installbase="bin" installname="comdlg32_winetest.exe" allowwarnings="true">
<include base="comdlg32_winetest">.</include>
<define name="__USE_W32API" />
<define name="_WIN32_IE">0x600</define>
<define name="_WIN32_WINNT">0x501</define>
<define name="WINVER">0x501</define>
<library>wine</library>
<library>comdlg32</library>
<library>user32</library>
<library>kernel32</library>
<library>ntdll</library>
<file>filedlg.c</file>
<file>printdlg.c</file>
<file>testlist.c</file>
</module>
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="comdlg32_winetest" type="win32cui" installbase="bin" installname="comdlg32_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="comdlg32_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>comdlg32</library>
<library>user32</library>
<library>kernel32</library>
<library>ntdll</library>
<file>filedlg.c</file>
<file>printdlg.c</file>
<file>testlist.c</file>
</module>

View file

@ -1,116 +1,116 @@
/*
* Unit test suite for comdlg32 API functions: file dialogs
*
* Copyright 2007 Google (Lei Zhang)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#include <windows.h>
#include <wine/test.h>
/* ##### */
static UINT CALLBACK OFNHookProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
LPNMHDR nmh;
if( msg == WM_NOTIFY)
{
nmh = (LPNMHDR) lParam;
if( nmh->code == CDN_INITDONE)
{
PostMessage( GetParent(hDlg), WM_COMMAND, IDCANCEL, FALSE);
}
}
return 0;
}
/* bug 6829 */
static void test_DialogCancel(void)
{
OPENFILENAMEA ofn;
BOOL result;
char szFileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLEHOOK;
ofn.lpstrDefExt = "txt";
ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProc;
PrintDlgA(NULL);
ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n",
CDERR_INITIALIZATION, CommDlgExtendedError());
result = GetOpenFileNameA(&ofn);
ok(0 == result, "expected %d, got %d\n", 0, result);
ok(0 == CommDlgExtendedError(), "expected %d, got %d\n", 0,
CommDlgExtendedError());
PrintDlgA(NULL);
ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n",
CDERR_INITIALIZATION, CommDlgExtendedError());
SetLastError(0xdeadbeef);
result = GetOpenFileNameW((LPOPENFILENAMEW) &ofn);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
skip("GetOpenFileNameW is not implemented\n");
else
{
ok(0 == result, "expected %d, got %d\n", 0, result);
ok(0 == CommDlgExtendedError(), "expected %d, got %d\n", 0,
CommDlgExtendedError());
}
PrintDlgA(NULL);
ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n",
CDERR_INITIALIZATION, CommDlgExtendedError());
result = GetSaveFileNameA(&ofn);
ok(0 == result, "expected %d, got %d\n", 0, result);
ok(0 == CommDlgExtendedError(), "expected %d, got %d\n", 0,
CommDlgExtendedError());
PrintDlgA(NULL);
ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n",
CDERR_INITIALIZATION, CommDlgExtendedError());
SetLastError(0xdeadbeef);
result = GetSaveFileNameW((LPOPENFILENAMEW) &ofn);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
skip("GetSaveFileNameW is not implemented\n");
else
{
ok(0 == result, "expected %d, got %d\n", 0, result);
ok(0 == CommDlgExtendedError(), "expected %d, got %d\n", 0,
CommDlgExtendedError());
}
}
START_TEST(filedlg)
{
test_DialogCancel();
}
/*
* Unit test suite for comdlg32 API functions: file dialogs
*
* Copyright 2007 Google (Lei Zhang)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#include <windows.h>
#include <wine/test.h>
/* ##### */
static UINT CALLBACK OFNHookProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
LPNMHDR nmh;
if( msg == WM_NOTIFY)
{
nmh = (LPNMHDR) lParam;
if( nmh->code == CDN_INITDONE)
{
PostMessage( GetParent(hDlg), WM_COMMAND, IDCANCEL, FALSE);
}
}
return 0;
}
/* bug 6829 */
static void test_DialogCancel(void)
{
OPENFILENAMEA ofn;
BOOL result;
char szFileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFilter = "Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_ENABLEHOOK;
ofn.lpstrDefExt = "txt";
ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProc;
PrintDlgA(NULL);
ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n",
CDERR_INITIALIZATION, CommDlgExtendedError());
result = GetOpenFileNameA(&ofn);
ok(0 == result, "expected %d, got %d\n", 0, result);
ok(0 == CommDlgExtendedError(), "expected %d, got %d\n", 0,
CommDlgExtendedError());
PrintDlgA(NULL);
ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n",
CDERR_INITIALIZATION, CommDlgExtendedError());
SetLastError(0xdeadbeef);
result = GetOpenFileNameW((LPOPENFILENAMEW) &ofn);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
skip("GetOpenFileNameW is not implemented\n");
else
{
ok(0 == result, "expected %d, got %d\n", 0, result);
ok(0 == CommDlgExtendedError(), "expected %d, got %d\n", 0,
CommDlgExtendedError());
}
PrintDlgA(NULL);
ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n",
CDERR_INITIALIZATION, CommDlgExtendedError());
result = GetSaveFileNameA(&ofn);
ok(0 == result, "expected %d, got %d\n", 0, result);
ok(0 == CommDlgExtendedError(), "expected %d, got %d\n", 0,
CommDlgExtendedError());
PrintDlgA(NULL);
ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n",
CDERR_INITIALIZATION, CommDlgExtendedError());
SetLastError(0xdeadbeef);
result = GetSaveFileNameW((LPOPENFILENAMEW) &ofn);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
skip("GetSaveFileNameW is not implemented\n");
else
{
ok(0 == result, "expected %d, got %d\n", 0, result);
ok(0 == CommDlgExtendedError(), "expected %d, got %d\n", 0,
CommDlgExtendedError());
}
}
START_TEST(filedlg)
{
test_DialogCancel();
}

View file

@ -1,153 +1,312 @@
/*
* Unit test suite for comdlg32 API functions: printer dialogs
*
* Copyright 2006 Detlef Riekenberg
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wingdi.h"
#include "wingdi.h"
#include "winuser.h"
#include "cderr.h"
#include "commdlg.h"
#include "wine/test.h"
/* ######## */
static void test_PageSetupDlgA(void)
{
LPPAGESETUPDLGA pDlg;
DWORD res;
pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PAGESETUPDLGA)) * 2);
if (!pDlg) return;
SetLastError(0xdeadbeef);
res = PageSetupDlgA(NULL);
ok( !res && (CommDlgExtendedError() == CDERR_INITIALIZATION),
"returned %u with %u and 0x%x (expected '0' and "
"CDERR_INITIALIZATION)\n", res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PAGESETUPDLGA));
pDlg->lStructSize = sizeof(PAGESETUPDLGA) -1;
SetLastError(0xdeadbeef);
res = PageSetupDlgA(pDlg);
ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
"returned %u with %u and 0x%x (expected '0' and "
"CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PAGESETUPDLGA));
pDlg->lStructSize = sizeof(PAGESETUPDLGA) +1;
pDlg->Flags = PSD_RETURNDEFAULT;
SetLastError(0xdeadbeef);
res = PageSetupDlgA(pDlg);
ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
"returned %u with %u and 0x%x (expected '0' and CDERR_STRUCTSIZE)\n",
res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PAGESETUPDLGA));
pDlg->lStructSize = sizeof(PAGESETUPDLGA);
pDlg->Flags = PSD_RETURNDEFAULT;
SetLastError(0xdeadbeef);
res = PageSetupDlgA(pDlg);
trace("after pagesetupdlga res = %d, le %d, ext error 0x%x\n",
res, GetLastError(), CommDlgExtendedError());
ok( res || (CommDlgExtendedError() == PDERR_NODEFAULTPRN),
"returned %u with %u and 0x%x (expected '!= 0' or '0' and "
"PDERR_NODEFAULTPRN)\n", res, GetLastError(), CommDlgExtendedError());
if (!res && (CommDlgExtendedError() == PDERR_NODEFAULTPRN)) {
skip("No printer configured.\n");
HeapFree(GetProcessHeap(), 0, pDlg);
return;
}
ok( pDlg->hDevMode && pDlg->hDevNames,
"got %p and %p (expected '!= NULL' for both)\n",
pDlg->hDevMode, pDlg->hDevNames);
GlobalFree(pDlg->hDevMode);
GlobalFree(pDlg->hDevNames);
HeapFree(GetProcessHeap(), 0, pDlg);
}
/* ##### */
static void test_PrintDlgA(void)
{
DWORD res;
LPPRINTDLGA pDlg;
pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PRINTDLGA)) * 2);
if (!pDlg) return;
/* will crash with unpatched wine */
SetLastError(0xdeadbeef);
res = PrintDlgA(NULL);
ok( !res && (CommDlgExtendedError() == CDERR_INITIALIZATION),
"returned %d with 0x%x and 0x%x (expected '0' and "
"CDERR_INITIALIZATION)\n", res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PRINTDLGA));
pDlg->lStructSize = sizeof(PRINTDLGA) - 1;
SetLastError(0xdeadbeef);
res = PrintDlgA(pDlg);
ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
"returned %d with 0x%x and 0x%x (expected '0' and "
"CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PRINTDLGA));
pDlg->lStructSize = sizeof(PRINTDLGA) + 1;
pDlg->Flags = PD_RETURNDEFAULT;
SetLastError(0xdeadbeef);
res = PrintDlgA(pDlg);
ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
"returned %u with %u and 0x%x (expected '0' and "
"CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PRINTDLGA));
pDlg->lStructSize = sizeof(PRINTDLGA);
pDlg->Flags = PD_RETURNDEFAULT;
SetLastError(0xdeadbeef);
res = PrintDlgA(pDlg);
ok( res || (CommDlgExtendedError() == PDERR_NODEFAULTPRN),
"returned %d with 0x%x and 0x%x (expected '!= 0' or '0' and "
"PDERR_NODEFAULTPRN)\n", res, GetLastError(), CommDlgExtendedError());
HeapFree(GetProcessHeap(), 0, pDlg);
}
START_TEST(printdlg)
{
test_PageSetupDlgA();
test_PrintDlgA();
}
/*
* Unit test suite for comdlg32 API functions: printer dialogs
*
* Copyright 2006-2007 Detlef Riekenberg
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wingdi.h"
#include "winuser.h"
#include "cderr.h"
#include "commdlg.h"
#include "wine/test.h"
/* ########################### */
static HMODULE hcomdlg32;
static HRESULT (WINAPI * pPrintDlgExA)(LPPRINTDLGEXA);
static HRESULT (WINAPI * pPrintDlgExW)(LPPRINTDLGEXW);
/* ########################### */
static const CHAR emptyA[] = "";
static const CHAR PrinterPortsA[] = "PrinterPorts";
/* ########################### */
static LPCSTR load_functions(void)
{
LPCSTR ptr;
ptr = "comdlg32.dll";
hcomdlg32 = LoadLibraryA(ptr);
if (!hcomdlg32) return ptr;
ptr = "PrintDlgExA";
pPrintDlgExA = (void *) GetProcAddress(hcomdlg32, ptr);
if (!pPrintDlgExA) return ptr;
ptr = "PrintDlgExW";
pPrintDlgExW = (void *) GetProcAddress(hcomdlg32, ptr);
if (!pPrintDlgExW) return ptr;
return NULL;
}
/* ########################### */
static void test_PageSetupDlgA(void)
{
LPPAGESETUPDLGA pDlg;
DWORD res;
pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PAGESETUPDLGA)) * 2);
if (!pDlg) return;
SetLastError(0xdeadbeef);
res = PageSetupDlgA(NULL);
ok( !res && (CommDlgExtendedError() == CDERR_INITIALIZATION),
"returned %u with %u and 0x%x (expected '0' and "
"CDERR_INITIALIZATION)\n", res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PAGESETUPDLGA));
pDlg->lStructSize = sizeof(PAGESETUPDLGA) -1;
SetLastError(0xdeadbeef);
res = PageSetupDlgA(pDlg);
ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
"returned %u with %u and 0x%x (expected '0' and "
"CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PAGESETUPDLGA));
pDlg->lStructSize = sizeof(PAGESETUPDLGA) +1;
pDlg->Flags = PSD_RETURNDEFAULT;
SetLastError(0xdeadbeef);
res = PageSetupDlgA(pDlg);
ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
"returned %u with %u and 0x%x (expected '0' and CDERR_STRUCTSIZE)\n",
res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PAGESETUPDLGA));
pDlg->lStructSize = sizeof(PAGESETUPDLGA);
pDlg->Flags = PSD_RETURNDEFAULT | PSD_NOWARNING;
SetLastError(0xdeadbeef);
res = PageSetupDlgA(pDlg);
ok( res || (CommDlgExtendedError() == PDERR_NODEFAULTPRN),
"returned %u with %u and 0x%x (expected '!= 0' or '0' and "
"PDERR_NODEFAULTPRN)\n", res, GetLastError(), CommDlgExtendedError());
if (!res && (CommDlgExtendedError() == PDERR_NODEFAULTPRN)) {
skip("No printer configured.\n");
HeapFree(GetProcessHeap(), 0, pDlg);
return;
}
ok( pDlg->hDevMode && pDlg->hDevNames,
"got %p and %p (expected '!= NULL' for both)\n",
pDlg->hDevMode, pDlg->hDevNames);
GlobalFree(pDlg->hDevMode);
GlobalFree(pDlg->hDevNames);
HeapFree(GetProcessHeap(), 0, pDlg);
}
/* ########################### */
static void test_PrintDlgA(void)
{
DWORD res;
LPPRINTDLGA pDlg;
DEVNAMES *pDevNames;
LPCSTR driver;
LPCSTR device;
LPCSTR port;
CHAR buffer[MAX_PATH];
LPSTR ptr;
pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PRINTDLGA)) * 2);
if (!pDlg) return;
/* will crash with unpatched wine */
SetLastError(0xdeadbeef);
res = PrintDlgA(NULL);
ok( !res && (CommDlgExtendedError() == CDERR_INITIALIZATION),
"returned %d with 0x%x and 0x%x (expected '0' and "
"CDERR_INITIALIZATION)\n", res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PRINTDLGA));
pDlg->lStructSize = sizeof(PRINTDLGA) - 1;
SetLastError(0xdeadbeef);
res = PrintDlgA(pDlg);
ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
"returned %d with 0x%x and 0x%x (expected '0' and "
"CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PRINTDLGA));
pDlg->lStructSize = sizeof(PRINTDLGA) + 1;
pDlg->Flags = PD_RETURNDEFAULT;
SetLastError(0xdeadbeef);
res = PrintDlgA(pDlg);
ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
"returned %u with %u and 0x%x (expected '0' and "
"CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PRINTDLGA));
pDlg->lStructSize = sizeof(PRINTDLGA);
pDlg->Flags = PD_RETURNDEFAULT;
SetLastError(0xdeadbeef);
res = PrintDlgA(pDlg);
ok( res || (CommDlgExtendedError() == PDERR_NODEFAULTPRN),
"returned %d with 0x%x and 0x%x (expected '!= 0' or '0' and "
"PDERR_NODEFAULTPRN)\n", res, GetLastError(), CommDlgExtendedError());
if (!res && (CommDlgExtendedError() == PDERR_NODEFAULTPRN)) {
skip("No printer configured.\n");
HeapFree(GetProcessHeap(), 0, pDlg);
return;
}
ok(pDlg->hDevNames != NULL, "(expected '!= NULL')\n");
pDevNames = GlobalLock(pDlg->hDevNames);
ok(pDevNames != NULL, "(expected '!= NULL')\n");
if (pDevNames) {
ok(pDevNames->wDriverOffset, "(expected '!= 0' for wDriverOffset)\n");
ok(pDevNames->wDeviceOffset, "(expected '!= 0' for wDeviceOffset)\n");
ok(pDevNames->wOutputOffset, "(expected '!= 0' for wOutputOffset)\n");
ok(pDevNames->wDefault == DN_DEFAULTPRN, "got 0x%x (expected DN_DEFAULTPRN)\n", pDevNames->wDefault);
driver = (LPCSTR)pDevNames + pDevNames->wDriverOffset;
device = (LPCSTR)pDevNames + pDevNames->wDeviceOffset;
port = (LPCSTR)pDevNames + pDevNames->wOutputOffset;
trace("driver '%s' device '%s' port '%s'\n", driver, device, port);
/* The Driver Entry does not include a Path */
ptr = strrchr(driver, '\\');
todo_wine {
ok( ptr == NULL, "got %p for '%s' (expected NULL for a simple name)\n", ptr, driver);
}
/* The Driver Entry does not have an extension (fixed to ".drv") */
ptr = strrchr(driver, '.');
todo_wine {
ok( ptr == NULL, "got %p for '%s' (expected NULL for no extension)\n", ptr, driver);
}
buffer[0] = '\0';
SetLastError(0xdeadbeef);
res = GetProfileStringA(PrinterPortsA, device, emptyA, buffer, sizeof(buffer));
ptr = strchr(buffer, ',');
todo_wine {
ok( (res > 1) && (ptr != NULL),
"got %u with %u and %p for '%s' (expected '>1' and '!= NULL')\n",
res, GetLastError(), ptr, buffer);
}
if (ptr) ptr[0] = '\0';
todo_wine {
ok( lstrcmpiA(driver, buffer) == 0,
"got driver '%s' (expected '%s')\n", driver, buffer);
}
}
GlobalUnlock(pDlg->hDevNames);
GlobalFree(pDlg->hDevMode);
GlobalFree(pDlg->hDevNames);
HeapFree(GetProcessHeap(), 0, pDlg);
}
/* ########################### */
static void test_PrintDlgExW(void)
{
LPPRINTDLGEXW pDlg;
HRESULT res;
/* Set CommDlgExtendedError != 0 */
PrintDlg(NULL);
SetLastError(0xdeadbeef);
res = pPrintDlgExW(NULL);
ok( (res == E_INVALIDARG),
"got 0x%x with %u and %u (expected 'E_INVALIDARG')\n",
res, GetLastError(), CommDlgExtendedError());
pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PRINTDLGEXW)) + 8);
if (!pDlg) return;
/* lStructSize must be exact */
ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
pDlg->lStructSize = sizeof(PRINTDLGEXW) - 1;
PrintDlg(NULL);
SetLastError(0xdeadbeef);
res = pPrintDlgExW(pDlg);
ok( (res == E_INVALIDARG),
"got 0x%x with %u and %u (expected 'E_INVALIDARG')\n",
res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
pDlg->lStructSize = sizeof(PRINTDLGEXW) + 1;
PrintDlg(NULL);
SetLastError(0xdeadbeef);
res = pPrintDlgExW(pDlg);
ok( (res == E_INVALIDARG),
"got 0x%x with %u and %u (expected 'E_INVALIDARG')\n",
res, GetLastError(), CommDlgExtendedError());
ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
pDlg->lStructSize = sizeof(PRINTDLGEXW);
SetLastError(0xdeadbeef);
res = pPrintDlgExW(pDlg);
ok( (res == E_HANDLE),
"got 0x%x with %u and %u (expected 'E_HANDLE')\n",
res, GetLastError(), CommDlgExtendedError());
HeapFree(GetProcessHeap(), 0, pDlg);
return;
}
/* ########################### */
START_TEST(printdlg)
{
LPCSTR ptr;
ptr = load_functions();
test_PageSetupDlgA();
test_PrintDlgA();
/* PrintDlgEx not present before w2k */
if (ptr) {
skip("%s\n", ptr);
return;
}
test_PrintDlgExW();
}

View file

@ -1,17 +1,17 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_filedlg(void);
extern void func_printdlg(void);
const struct test winetest_testlist[] =
{
{ "filedlg", func_filedlg },
{ "printdlg", func_printdlg },
{ 0, 0 }
};
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_filedlg(void);
extern void func_printdlg(void);
const struct test winetest_testlist[] =
{
{ "filedlg", func_filedlg },
{ "printdlg", func_printdlg },
{ 0, 0 }
};

View file

@ -2,9 +2,18 @@
<directory name="advapi32">
<xi:include href="advapi32/advapi32.rbuild" />
</directory>
<directory name="advpack">
<xi:include href="advpack/advpack.rbuild" />
</directory>
<directory name="browseui">
<xi:include href="browseui/browseui.rbuild" />
</directory>
<directory name="cabinet">
<xi:include href="cabinet/cabinet.rbuild" />
</directory>
<directory name="comcat">
<xi:include href="comcat/comcat.rbuild" />
</directory>
<directory name="comctl32">
<xi:include href="comctl32/comctl32.rbuild" />
</directory>
@ -23,6 +32,9 @@
<directory name="lz32">
<xi:include href="lz32/lz32.rbuild" />
</directory>
<directory name="mapi32">
<xi:include href="mapi32/mapi32.rbuild" />
</directory>
<directory name="mlang">
<xi:include href="mlang/mlang.rbuild" />
</directory>
@ -32,15 +44,30 @@
<directory name="msvcrt">
<xi:include href="msvcrt/msvcrt.rbuild" />
</directory>
<directory name="netapi32">
<xi:include href="netapi32/netapi32.rbuild" />
</directory>
<directory name="ntdll">
<xi:include href="ntdll/ntdll.rbuild" />
</directory>
<directory name="odbccp32">
<xi:include href="odbccp32/odbccp32.rbuild" />
</directory>
<directory name="psapi">
<xi:include href="psapi/psapi.rbuild" />
</directory>
<directory name="powrprof">
<xi:include href="powrprof/powrprof.rbuild" />
</directory>
<directory name="riched20">
<xi:include href="riched20/riched20.rbuild" />
</directory>
<directory name="rsabase">
<xi:include href="rsabase/rsabase.rbuild" />
</directory>
<directory name="rsaenh">
<xi:include href="rsaenh/rsaenh.rbuild" />
</directory>
<directory name="setupapi">
<xi:include href="setupapi/setupapi.rbuild" />
</directory>
@ -50,13 +77,22 @@
<directory name="shlwapi">
<xi:include href="shlwapi/shlwapi.rbuild" />
</directory>
<directory name="urlmon">
<xi:include href="urlmon/urlmon.rbuild" />
</directory>
<directory name="user32">
<xi:include href="user32/user32.rbuild" />
</directory>
<directory name="usp10">
<xi:include href="usp10/usp10.rbuild" />
</directory>
<directory name="uxtheme">
<xi:include href="uxtheme/uxtheme.rbuild" />
</directory>
<directory name="version">
<xi:include href="version/version.rbuild" />
</directory>
<directory name="wininet">
<xi:include href="wininet/wininet.rbuild" />
</directory>
</group>

View file

@ -1,9 +1,13 @@
<module name="lz32_winetest" type="win32cui" installbase="bin" installname="lz32_winetest.exe" allowwarnings="true">
<include base="lz32_winetest">.</include>
<define name="__USE_W32API" />
<library>kernel32</library>
<library>ntdll</library>
<library>lz32</library>
<file>testlist.c</file>
<file>lzexpand_main.c</file>
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="lz32_winetest" type="win32cui" installbase="bin" installname="lz32_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="lz32_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>lz32</library>
<library>kernel32</library>
<library>ntdll</library>
<file>lzexpand_main.c</file>
<file>testlist.c</file>
</module>

View file

@ -27,22 +27,39 @@
#include "wine/test.h"
/* Compressed file names end with underscore. */
static char filename [] = "testfile.xxx";
static char filename_[] = "testfile.xx_";
#if 0
static char filename[] = "testfile.xxx";
#endif
static WCHAR filenameW [] = {'t','e','s','t','f','i','l','e','.','x','x','x',0};
static WCHAR filenameW_[] = {'t','e','s','t','f','i','l','e','.','x','x','_',0};
static char dotless [] = "dotless";
static char dotless_[] = "dotless._";
static WCHAR dotlessW [] = {'d','o','t','l','e','s','s', 0};
static WCHAR dotlessW_[] = {'d','o','t','l','e','s','s','.','_', 0};
static char extless [] = "extless.";
static char extless_[] = "extless._";
static WCHAR extlessW [] = {'e','x','t','l','e','s','s','.', 0};
static WCHAR extlessW_[] = {'e','x','t','l','e','s','s','.','_', 0};
static char _terminated [] = "_terminated.xxxx_";
static char _terminated_[] = "_terminated.xxxx_";
static WCHAR _terminatedW [] = {'_','t','e','r','m','i','n','a','t','e','d','.','x','x','x','x','_', 0};
static WCHAR _terminatedW_[] = {'_','t','e','r','m','i','n','a','t','e','d','.','x','x','x','x','_', 0};
static char filename2[] = "testfile.yyy";
/* This is the hex string representation of the file created by compressing
a simple text file with the contents "This is a test file."
The file was created using COMPRESS.EXE from the Windows Server 2003
Resource Kit from Microsoft. The resource kit was retrieved from the
following URL:
following URL:
http://www.microsoft.com/downloads/details.aspx?FamilyID=9d467a69-57ff-4ae7-96ee-b18c4790cffd&displaylang=en
*/
static const unsigned char compressed_file[] =
static const unsigned char compressed_file[] =
{0x53,0x5A,0x44,0x44,0x88,0xF0,0x27,0x33,0x41,
0x74,0x75,0x14,0x00,0x00,0xDF,0x54,0x68,0x69,
0x73,0x20,0xF2,0xF0,0x61,0x20,0xFF,0x74,0x65,
@ -54,67 +71,404 @@ static const DWORD uncompressed_data_size = sizeof(uncompressed_data) - 1;
static char *buf;
static void test_lzopenfile(void)
static void full_file_path_name_in_a_CWD(const char *src, char *dst, BOOL expect_short)
{
DWORD retval;
char shortname[MAX_PATH];
retval = GetCurrentDirectoryA(MAX_PATH, dst);
ok(retval > 0, "GetCurrentDirectoryA returned %d, GLE=%d\n",
retval, GetLastError());
if(dst[retval-1] != '\\')
/* Append backslash only when it's missing */
lstrcatA(dst, "\\");
lstrcatA(dst, src);
if(expect_short)
{
memcpy(shortname, dst, MAX_PATH);
retval = GetShortPathName(shortname, dst, MAX_PATH-1);
ok(retval > 0, "GetShortPathName returned %d for '%s', GLE=%d\n",
retval, dst, GetLastError());
}
}
static void create_file(char *fname)
{
INT file;
OFSTRUCT ofs;
DWORD retval;
file = LZOpenFileA(fname, &ofs, OF_CREATE);
ok(file >= 0, "LZOpenFileA failed to create '%s'\n", fname);
LZClose(file);
retval = GetFileAttributesA(fname);
ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA('%s'): error %d\n", ofs.szPathName, GetLastError());
}
static void delete_file(char *fname)
{
INT file;
OFSTRUCT ofs;
DWORD retval;
file = LZOpenFileA(fname, &ofs, OF_DELETE);
ok(file >= 0, "LZOpenFileA failed to delete '%s'\n", fname);
LZClose(file);
retval = GetFileAttributesA(fname);
ok(retval == INVALID_FILE_ATTRIBUTES, "GetFileAttributesA succeeded on deleted file ('%s')\n", ofs.szPathName);
}
static void test_LZOpenFileA_existing_compressed(void)
{
OFSTRUCT test;
INT file;
char expected[MAX_PATH];
char short_expected[MAX_PATH];
char filled_0xA5[OFS_MAXPATHNAME];
/* Try to open existing compressed files: */
create_file(filename_);
create_file(dotless_);
create_file(extless_);
create_file(_terminated_);
memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(filename_, expected, FALSE);
SetLastError(0xfaceabee);
/* a, using 8.3-conformant file name. */
file = LZOpenFileA(filename, &test, OF_EXIST);
/* If the file "foo.xxx" does not exist, LZOpenFileA should then
check for the file "foo.xx_" and open that -- at least on some
operating systems. Doesn't seem to on my copy of Win98.
*/
if(file != LZERROR_BADINHANDLE) {
ok(file >= 0, "LZOpenFileA returns negative file descriptor for '%s'\n", filename);
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == 0, "LZOpenFileA set test.nErrCode to %d\n",
test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileA returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
} else { /* Win9x */
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"GetLastError() returns %d\n", GetLastError());
ok(test.cBytes == 0xA5,
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
ok(strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0,
"LZOpenFileA returned '%s', but was expected to return '%s'\n",
test.szPathName, filled_0xA5);
}
memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(dotless_, expected, FALSE);
SetLastError(0xfaceabee);
/* b, using dotless file name. */
file = LZOpenFileA(dotless, &test, OF_EXIST);
if(file != LZERROR_BADINHANDLE) {
ok(file >= 0, "LZOpenFileA returns negative file descriptor for '%s'\n", dotless);
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == 0, "LZOpenFileA set test.nErrCode to %d\n",
test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileA returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
} else { /* Win9x */
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"GetLastError() returns %d\n", GetLastError());
todo_wine
ok(test.cBytes == 0xA5,
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
todo_wine
ok(strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0,
"LZOpenFileA returned '%s', but was expected to return '%s'\n",
test.szPathName, filled_0xA5);
}
memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(extless_, expected, FALSE);
SetLastError(0xfaceabee);
/* c, using extensionless file name. */
file = LZOpenFileA(extless, &test, OF_EXIST);
if(file != LZERROR_BADINHANDLE) {
ok(file >= 0, "LZOpenFileA returns negative file descriptor for '%s'\n", extless);
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == 0, "LZOpenFileA set test.nErrCode to %d\n",
test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileA returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
} else { /* Win9x */
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"GetLastError() returns %d\n", GetLastError());
ok(test.cBytes == 0xA5,
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
ok(strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0,
"LZOpenFileA returned '%s', but was expected to return '%s'\n",
test.szPathName, filled_0xA5);
}
memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(_terminated_, expected, FALSE);
full_file_path_name_in_a_CWD(_terminated_, short_expected, TRUE);
/* d, using underscore-terminated file name. */
file = LZOpenFileA(_terminated, &test, OF_EXIST);
ok(file >= 0, "LZOpenFileA failed on switching to a compressed file name\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == 0, "LZOpenFileA set test.nErrCode to %d\n",
test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0 ||
lstrcmpA(test.szPathName, short_expected) == 0, /* Win9x */
"LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, short_expected);
LZClose(file);
delete_file(filename_);
delete_file(dotless_);
delete_file(extless_);
delete_file(_terminated_);
}
static void test_LZOpenFileA_nonexisting_compressed(void)
{
OFSTRUCT test;
INT file;
char expected[MAX_PATH];
char filled_0xA5[OFS_MAXPATHNAME];
/* Try to open nonexisting compressed files: */
memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(filename_, expected, FALSE);
SetLastError(0xfaceabee);
/* a, using 8.3-conformant file name. */
file = LZOpenFileA(filename, &test, OF_EXIST);
/* If the file "foo.xxx" does not exist, LZOpenFileA should then
check for the file "foo.xx_" and open that -- at least on some
operating systems. Doesn't seem to on my copy of Win98.
*/
ok(file == LZERROR_BADINHANDLE,
"LZOpenFileA succeeded on nonexistent file\n");
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"GetLastError() returns %d\n", GetLastError());
todo_wine
ok(test.cBytes == 0xA5,
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0 ||
strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, /* Win9x */
"LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, filled_0xA5);
memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(dotless_, expected, FALSE);
SetLastError(0xfaceabee);
/* b, using dotless file name. */
file = LZOpenFileA(dotless, &test, OF_EXIST);
ok(file == LZERROR_BADINHANDLE,
"LZOpenFileA succeeded on nonexistent file\n");
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"GetLastError() returns %d\n", GetLastError());
todo_wine
ok(test.cBytes == 0xA5,
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0 ||
strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, /* Win9x */
"LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, filled_0xA5);
memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(extless_, expected, FALSE);
SetLastError(0xfaceabee);
/* c, using extensionless file name. */
file = LZOpenFileA(extless, &test, OF_EXIST);
ok(file == LZERROR_BADINHANDLE,
"LZOpenFileA succeeded on nonexistent file\n");
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"GetLastError() returns %d\n", GetLastError());
todo_wine
ok(test.cBytes == 0xA5,
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0 ||
strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, /* Win9x */
"LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, filled_0xA5);
memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(_terminated_, expected, FALSE);
SetLastError(0xfaceabee);
/* d, using underscore-terminated file name. */
file = LZOpenFileA(_terminated, &test, OF_EXIST);
ok(file == LZERROR_BADINHANDLE,
"LZOpenFileA succeeded on nonexistent file\n");
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"GetLastError() returns %d\n", GetLastError());
todo_wine
ok(test.cBytes == 0xA5,
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0 ||
strncmp(test.szPathName, filled_0xA5, OFS_MAXPATHNAME) == 0, /* Win9x */
"LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, filled_0xA5);
}
static void test_LZOpenFileA(void)
{
OFSTRUCT test;
DWORD retval;
INT file;
static char badfilename_[] = "badfilename_";
char expected[MAX_PATH];
char short_expected[MAX_PATH];
SetLastError(0xfaceabee);
/* Check for nonexistent file. */
file = LZOpenFile("badfilename_", &test, OF_READ);
ok(file == LZERROR_BADINHANDLE,
"LZOpenFile succeeded on nonexistent file\n");
file = LZOpenFileA(badfilename_, &test, OF_READ);
ok(file == LZERROR_BADINHANDLE,
"LZOpenFileA succeeded on nonexistent file\n");
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"GetLastError() returns %d\n", GetLastError());
LZClose(file);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(filename_, expected, FALSE);
/* Create an empty file. */
file = LZOpenFile(filename_, &test, OF_CREATE);
ok(file >= 0, "LZOpenFile failed on creation\n");
file = LZOpenFileA(filename_, &test, OF_CREATE);
ok(file >= 0, "LZOpenFileA failed on creation\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileA returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
retval = GetFileAttributes(filename_);
ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributes: error %ld\n",
retval = GetFileAttributesA(filename_);
ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesA: error %d\n",
GetLastError());
/* Check various opening options. */
file = LZOpenFile(filename_, &test, OF_READ);
ok(file >= 0, "LZOpenFile failed on read\n");
LZClose(file);
file = LZOpenFile(filename_, &test, OF_WRITE);
ok(file >= 0, "LZOpenFile failed on write\n");
LZClose(file);
file = LZOpenFile(filename_, &test, OF_READWRITE);
ok(file >= 0, "LZOpenFile failed on read/write\n");
LZClose(file);
file = LZOpenFile(filename_, &test, OF_EXIST);
ok(file >= 0, "LZOpenFile failed on read/write\n");
/* Check various opening options: */
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(filename_, short_expected, TRUE);
/* a, for reading. */
file = LZOpenFileA(filename_, &test, OF_READ);
ok(file >= 0, "LZOpenFileA failed on read\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0 ||
lstrcmpA(test.szPathName, short_expected) == 0, /* Win9x */
"LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, short_expected);
LZClose(file);
memset(&test, 0xA5, sizeof(test));
/* If the file "foo.xxx" does not exist, LZOpenFile should then
check for the file "foo.xx_" and open that -- at least on some
operating systems. Doesn't seem to on my copy of Win98.
The Wine testing guidelines say we should accept the behavior of
any valid version of Windows. Thus it seems we cannot check this?!
Revisit this at some point to see if this can be tested somehow.
*/
#if 0
file = LZOpenFile(filename, &test, OF_EXIST);
ok(file != LZERROR_BADINHANDLE,
"LZOpenFile \"filename_\" check failed\n");
/* b, for writing. */
file = LZOpenFileA(filename_, &test, OF_WRITE);
ok(file >= 0, "LZOpenFileA failed on write\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0 ||
lstrcmpA(test.szPathName, short_expected) == 0, /* Win9x */
"LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, short_expected);
LZClose(file);
#endif
memset(&test, 0xA5, sizeof(test));
/* c, for reading and writing. */
file = LZOpenFileA(filename_, &test, OF_READWRITE);
ok(file >= 0, "LZOpenFileA failed on read/write\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0 ||
lstrcmpA(test.szPathName, short_expected) == 0, /* Win9x */
"LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, short_expected);
LZClose(file);
memset(&test, 0xA5, sizeof(test));
/* d, for checking file existence. */
file = LZOpenFileA(filename_, &test, OF_EXIST);
ok(file >= 0, "LZOpenFileA failed on read/write\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0 ||
lstrcmpA(test.szPathName, short_expected) == 0, /* Win9x */
"LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, short_expected);
LZClose(file);
memset(&test, 0xA5, sizeof(test));
/* Delete the file then make sure it doesn't exist anymore. */
file = LZOpenFile(filename_, &test, OF_DELETE);
ok(file >= 0, "LZOpenFile failed on delete\n");
file = LZOpenFileA(filename_, &test, OF_DELETE);
ok(file >= 0, "LZOpenFileA failed on delete\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileA set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS,
"LZOpenFileA set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0 ||
lstrcmpA(test.szPathName, short_expected) == 0, /* Win9x */
"LZOpenFileA returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, short_expected);
LZClose(file);
retval = GetFileAttributes(filename_);
ok(retval == INVALID_FILE_ATTRIBUTES,
"GetFileAttributes succeeded on deleted file\n");
retval = GetFileAttributesA(filename_);
ok(retval == INVALID_FILE_ATTRIBUTES,
"GetFileAttributesA succeeded on deleted file\n");
test_LZOpenFileA_existing_compressed();
test_LZOpenFileA_nonexisting_compressed();
}
static void test_lzread(void)
static void test_LZRead(void)
{
HANDLE file;
DWORD ret;
@ -123,15 +477,15 @@ static void test_lzread(void)
BOOL retok;
/* Create the compressed file. */
file = CreateFile(filename_, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
file = CreateFileA(filename_, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
ok(file != INVALID_HANDLE_VALUE, "Could not create test file\n");
retok = WriteFile(file, compressed_file, compressed_file_size, &ret, 0);
ok( retok, "WriteFile: error %ld\n", GetLastError());
ok( retok, "WriteFile: error %d\n", GetLastError());
ok(ret == compressed_file_size, "Wrote wrong number of bytes with WriteFile?\n");
CloseHandle(file);
cfile = LZOpenFile(filename_, &test, OF_READ);
ok(cfile > 0, "LZOpenFile failed\n");
cfile = LZOpenFileA(filename_, &test, OF_READ);
ok(cfile > 0, "LZOpenFileA failed\n");
ret = LZRead(cfile, buf, uncompressed_data_size);
ok(ret == uncompressed_data_size, "Read wrong number of bytes\n");
@ -148,11 +502,11 @@ static void test_lzread(void)
LZClose(cfile);
ret = DeleteFile(filename_);
ok(ret, "DeleteFile: error %ld\n", GetLastError());
ret = DeleteFileA(filename_);
ok(ret, "DeleteFileA: error %d\n", GetLastError());
}
static void test_lzcopy(void)
static void test_LZCopy(void)
{
HANDLE file;
DWORD ret;
@ -161,18 +515,18 @@ static void test_lzcopy(void)
BOOL retok;
/* Create the compressed file. */
file = CreateFile(filename_, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
ok(file != INVALID_HANDLE_VALUE,
"CreateFile: error %ld\n", GetLastError());
file = CreateFileA(filename_, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, 0);
ok(file != INVALID_HANDLE_VALUE,
"CreateFileA: error %d\n", GetLastError());
retok = WriteFile(file, compressed_file, compressed_file_size, &ret, 0);
ok( retok, "WriteFile error %ld\n", GetLastError());
ok( retok, "WriteFile error %d\n", GetLastError());
ok(ret == compressed_file_size, "Wrote wrong number of bytes\n");
CloseHandle(file);
source = LZOpenFile(filename_, &stest, OF_READ);
ok(source >= 0, "LZOpenFile failed on compressed file\n");
dest = LZOpenFile(filename2, &dtest, OF_CREATE);
ok(dest >= 0, "LZOpenFile failed on creating new file %d\n", dest);
source = LZOpenFileA(filename_, &stest, OF_READ);
ok(source >= 0, "LZOpenFileA failed on compressed file\n");
dest = LZOpenFileA(filename2, &dtest, OF_CREATE);
ok(dest >= 0, "LZOpenFileA failed on creating new file %d\n", dest);
ret = LZCopy(source, dest);
ok(ret > 0, "LZCopy error\n");
@ -180,29 +534,353 @@ static void test_lzcopy(void)
LZClose(source);
LZClose(dest);
file = CreateFile(filename2, GENERIC_READ, 0, NULL, OPEN_EXISTING,
0, 0);
file = CreateFileA(filename2, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
ok(file != INVALID_HANDLE_VALUE,
"CreateFile: error %ld\n", GetLastError());
"CreateFileA: error %d\n", GetLastError());
retok = ReadFile(file, buf, uncompressed_data_size*2, &ret, 0);
ok( retok && ret == uncompressed_data_size, "ReadFile: error %ld\n", GetLastError());
ok( retok && ret == uncompressed_data_size, "ReadFile: error %d\n", GetLastError());
/* Compare what we read with what we think we should read. */
ok(!memcmp(buf, uncompressed_data, uncompressed_data_size),
"buffer contents mismatch\n");
CloseHandle(file);
ret = DeleteFile(filename_);
ok(ret, "DeleteFile: error %ld\n", GetLastError());
ret = DeleteFile(filename2);
ok(ret, "DeleteFile: error %ld\n", GetLastError());
ret = DeleteFileA(filename_);
ok(ret, "DeleteFileA: error %d\n", GetLastError());
ret = DeleteFileA(filename2);
ok(ret, "DeleteFileA: error %d\n", GetLastError());
}
static void create_fileW(WCHAR *fnameW)
{
INT file;
OFSTRUCT ofs;
DWORD retval;
file = LZOpenFileW(fnameW, &ofs, OF_CREATE);
ok(file >= 0, "LZOpenFileW failed on creation\n");
LZClose(file);
retval = GetFileAttributesW(fnameW);
ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributesW('%s'): error %d\n", ofs.szPathName, GetLastError());
}
static void delete_fileW(WCHAR *fnameW)
{
INT file;
OFSTRUCT ofs;
DWORD retval;
file = LZOpenFileW(fnameW, &ofs, OF_DELETE);
ok(file >= 0, "LZOpenFileW failed on delete\n");
LZClose(file);
retval = GetFileAttributesW(fnameW);
ok(retval == INVALID_FILE_ATTRIBUTES, "GetFileAttributesW succeeded on deleted file ('%s')\n", ofs.szPathName);
}
static void test_LZOpenFileW_existing_compressed(void)
{
OFSTRUCT test;
INT file;
char expected[MAX_PATH];
/* Try to open existing compressed files: */
create_fileW(filenameW_);
create_fileW(dotlessW_);
create_fileW(extlessW_);
create_fileW(_terminatedW_);
full_file_path_name_in_a_CWD(filename_, expected, FALSE);
memset(&test, 0xA5, sizeof(test));
/* a, using 8.3-conformant file name. */
file = LZOpenFileW(filenameW, &test, OF_EXIST);
/* If the file "foo.xxx" does not exist, LZOpenFileW should then
check for the file "foo.xx_" and open that.
*/
ok(file >= 0, "LZOpenFileW failed on switching to a compressed file name\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS, "LZOpenFileW set test.nErrCode to %d\n",
test.nErrCode);
/* Note that W-function returns A-string by a OFSTRUCT.szPathName: */
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(dotless_, expected, FALSE);
/* b, using dotless file name. */
file = LZOpenFileW(dotlessW, &test, OF_EXIST);
ok(file >= 0, "LZOpenFileW failed on switching to a compressed file name\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS, "LZOpenFileW set test.nErrCode to %d\n",
test.nErrCode);
/* Note that W-function returns A-string by a OFSTRUCT.szPathName: */
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(extless_, expected, FALSE);
/* c, using extensionless file name. */
file = LZOpenFileW(extlessW, &test, OF_EXIST);
ok(file >= 0, "LZOpenFileW failed on switching to a compressed file name\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS, "LZOpenFileW set test.nErrCode to %d\n",
test.nErrCode);
/* Note that W-function returns A-string by a OFSTRUCT.szPathName: */
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(_terminated_, expected, FALSE);
/* d, using underscore-terminated file name. */
file = LZOpenFileW(_terminatedW, &test, OF_EXIST);
ok(file >= 0, "LZOpenFileW failed on switching to a compressed file name\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS, "LZOpenFileW set test.nErrCode to %d\n",
test.nErrCode);
/* Note that W-function returns A-string by a OFSTRUCT.szPathName: */
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
delete_fileW(filenameW_);
delete_fileW(dotlessW_);
delete_fileW(extlessW_);
delete_fileW(_terminatedW_);
}
static void test_LZOpenFileW_nonexisting_compressed(void)
{
OFSTRUCT test;
INT file;
char expected[MAX_PATH];
char filled_0xA5[OFS_MAXPATHNAME];
/* Try to open nonexisting compressed files: */
memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(filename_, expected, FALSE);
SetLastError(0xfaceabee);
/* a, using 8.3-conformant file name. */
file = LZOpenFileW(filenameW, &test, OF_EXIST);
/* If the file "foo.xxx" does not exist, LZOpenFileA should then
check for the file "foo.xx_" and open that -- at least on some
operating systems. Doesn't seem to on my copy of Win98.
*/
ok(file == LZERROR_BADINHANDLE,
"LZOpenFileW succeeded on nonexistent file\n");
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"GetLastError() returns %d\n", GetLastError());
todo_wine
ok(test.cBytes == 0xA5,
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
"LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, filled_0xA5);
memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(dotless_, expected, FALSE);
SetLastError(0xfaceabee);
/* b, using dotless file name. */
file = LZOpenFileW(dotlessW, &test, OF_EXIST);
ok(file == LZERROR_BADINHANDLE,
"LZOpenFileW succeeded on nonexistent file\n");
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"GetLastError() returns %d\n", GetLastError());
todo_wine
ok(test.cBytes == 0xA5,
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
"LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, filled_0xA5);
memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(extless_, expected, FALSE);
SetLastError(0xfaceabee);
/* c, using extensionless file name. */
file = LZOpenFileW(extlessW, &test, OF_EXIST);
ok(file == LZERROR_BADINHANDLE,
"LZOpenFileW succeeded on nonexistent file\n");
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"GetLastError() returns %d\n", GetLastError());
todo_wine
ok(test.cBytes == 0xA5,
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
"LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, filled_0xA5);
memset(&filled_0xA5, 0xA5, OFS_MAXPATHNAME);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(_terminated_, expected, FALSE);
SetLastError(0xfaceabee);
/* d, using underscore-terminated file name. */
file = LZOpenFileW(_terminatedW, &test, OF_EXIST);
ok(file == LZERROR_BADINHANDLE,
"LZOpenFileW succeeded on nonexistent file\n");
ok(GetLastError() == ERROR_FILE_NOT_FOUND,
"GetLastError() returns %d\n", GetLastError());
todo_wine
ok(test.cBytes == 0xA5,
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_FILE_NOT_FOUND,
"LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s' or '%s'\n",
test.szPathName, expected, filled_0xA5);
}
static void test_LZOpenFileW(void)
{
OFSTRUCT test;
DWORD retval;
INT file;
static WCHAR badfilenameW[] = {'b','a','d','f','i','l','e','n','a','m','e','.','x','t','n',0};
char expected[MAX_PATH];
SetLastError(0xfaceabee);
/* Check for nonexistent file. */
file = LZOpenFileW(badfilenameW, &test, OF_READ);
ok(GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
"GetLastError() returns %d\n", GetLastError());
if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
trace("LZOpenFileW call not implemented, skipping rest of the test\n");
return;
}
ok(file == LZERROR_BADINHANDLE, "LZOpenFileW succeeded on nonexistent file\n");
LZClose(file);
memset(&test, 0xA5, sizeof(test));
full_file_path_name_in_a_CWD(filename_, expected, FALSE);
/* Create an empty file. */
file = LZOpenFileW(filenameW_, &test, OF_CREATE);
ok(file >= 0, "LZOpenFile failed on creation\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS,
"LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
retval = GetFileAttributesW(filenameW_);
ok(retval != INVALID_FILE_ATTRIBUTES, "GetFileAttributes: error %d\n",
GetLastError());
/* Check various opening options: */
memset(&test, 0xA5, sizeof(test));
/* a, for reading. */
file = LZOpenFileW(filenameW_, &test, OF_READ);
ok(file >= 0, "LZOpenFileW failed on read\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS,
"LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
memset(&test, 0xA5, sizeof(test));
/* b, for writing. */
file = LZOpenFileW(filenameW_, &test, OF_WRITE);
ok(file >= 0, "LZOpenFileW failed on write\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS,
"LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
memset(&test, 0xA5, sizeof(test));
/* c, for reading and writing. */
file = LZOpenFileW(filenameW_, &test, OF_READWRITE);
ok(file >= 0, "LZOpenFileW failed on read/write\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS,
"LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
memset(&test, 0xA5, sizeof(test));
/* d, for checking file existence. */
file = LZOpenFileW(filenameW_, &test, OF_EXIST);
ok(file >= 0, "LZOpenFileW failed on read/write\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS,
"LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
memset(&test, 0xA5, sizeof(test));
/* Delete the file then make sure it doesn't exist anymore. */
file = LZOpenFileW(filenameW_, &test, OF_DELETE);
ok(file >= 0, "LZOpenFileW failed on delete\n");
ok(test.cBytes == sizeof(OFSTRUCT),
"LZOpenFileW set test.cBytes to %d\n", test.cBytes);
ok(test.nErrCode == ERROR_SUCCESS,
"LZOpenFileW set test.nErrCode to %d\n", test.nErrCode);
ok(lstrcmpA(test.szPathName, expected) == 0,
"LZOpenFileW returned '%s', but was expected to return '%s'\n",
test.szPathName, expected);
LZClose(file);
retval = GetFileAttributesW(filenameW_);
ok(retval == INVALID_FILE_ATTRIBUTES,
"GetFileAttributesW succeeded on deleted file\n");
test_LZOpenFileW_existing_compressed();
test_LZOpenFileW_nonexisting_compressed();
}
START_TEST(lzexpand_main)
{
buf = malloc(uncompressed_data_size * 2);
test_lzopenfile();
test_lzread();
test_lzcopy();
test_LZOpenFileA();
test_LZOpenFileW();
test_LZRead();
test_LZCopy();
free(buf);
}

View file

@ -0,0 +1,114 @@
/*
* Unit test suite for MAPI IMalloc functions
*
* Copyright 2004 Jon Griffiths
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winerror.h"
#include "winnt.h"
#include "mapiutil.h"
static HMODULE hMapi32 = 0;
static SCODE (WINAPI *pScInitMapiUtil)(ULONG);
static LPMALLOC (WINAPI *pMAPIGetDefaultMalloc)(void);
static void test_IMalloc(void)
{
LPVOID lpMem;
ULONG ulRef;
int iRet;
HRESULT hRet;
LPMALLOC lpMalloc;
LPVOID lpVoid;
pMAPIGetDefaultMalloc = (void*)GetProcAddress(hMapi32,
"MAPIGetDefaultMalloc@0");
if (!pMAPIGetDefaultMalloc)
return;
lpMalloc = pMAPIGetDefaultMalloc();
if (!lpMalloc)
return;
lpVoid = NULL;
hRet = IMalloc_QueryInterface(lpMalloc, &IID_IUnknown, &lpVoid);
ok (hRet == S_OK && lpVoid != NULL,
"IID_IUnknown: expected S_OK, non-null, got 0x%08x, %p\n",
hRet, lpVoid);
lpVoid = NULL;
hRet = IMalloc_QueryInterface(lpMalloc, &IID_IMalloc, &lpVoid);
ok (hRet == S_OK && lpVoid != NULL,
"IID_IIMalloc: expected S_OK, non-null, got 0x%08x, %p\n",
hRet, lpVoid);
/* Prove that native mapi uses LocalAlloc/LocalFree */
lpMem = IMalloc_Alloc(lpMalloc, 61);
ok (lpMem && IMalloc_GetSize(lpMalloc, lpMem) ==
LocalSize((HANDLE)lpMem),
"Expected non-null, same size, got %p, %s size\n", lpMem,
lpMem ? "different" : "same");
iRet = IMalloc_DidAlloc(lpMalloc, lpMem);
ok (iRet == -1, "DidAlloc, expected -1. got %d\n", iRet);
IMalloc_HeapMinimize(lpMalloc);
LocalFree(lpMem);
ulRef = IMalloc_AddRef(lpMalloc);
ok (ulRef == 1u, "AddRef expected 1, returned %d\n", ulRef);
ulRef = IMalloc_Release(lpMalloc);
ok (ulRef == 1u, "AddRef expected 1, returned %d\n", ulRef);
IMalloc_Release(lpMalloc);
}
START_TEST(imalloc)
{
SCODE ret;
hMapi32 = LoadLibraryA("mapi32.dll");
pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4");
if (!pScInitMapiUtil)
{
skip("ScInitMapiUtil is not available\n");
FreeLibrary(hMapi32);
return;
}
SetLastError(0xdeadbeef);
ret = pScInitMapiUtil(0);
if ((ret != S_OK) && (GetLastError() == ERROR_PROC_NOT_FOUND))
{
skip("ScInitMapiUtil is not implemented\n");
FreeLibrary(hMapi32);
return;
}
test_IMalloc();
FreeLibrary(hMapi32);
}

View file

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="mapi32_winetest" type="win32cui" installbase="bin" installname="mapi32_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="mapi32_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>kernel32</library>
<library>uuid</library>
<library>ntdll</library>
<file>imalloc.c</file>
<file>prop.c</file>
<file>util.c</file>
<file>testlist.c</file>
</module>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,19 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_imalloc(void);
extern void func_prop(void);
extern void func_util(void);
const struct test winetest_testlist[] =
{
{ "imalloc", func_imalloc },
{ "prop", func_prop },
{ "util", func_util },
{ 0, 0 }
};

View file

@ -0,0 +1,203 @@
/*
* Unit test suite for MAPI utility functions
*
* Copyright 2004 Jon Griffiths
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winerror.h"
#include "winnt.h"
#include "mapiutil.h"
#include "mapitags.h"
static HMODULE hMapi32 = 0;
static SCODE (WINAPI *pScInitMapiUtil)(ULONG);
static void (WINAPI *pSwapPword)(PUSHORT,ULONG);
static void (WINAPI *pSwapPlong)(PULONG,ULONG);
static void (WINAPI *pHexFromBin)(LPBYTE,int,LPWSTR);
static void (WINAPI *pFBinFromHex)(LPWSTR,LPBYTE);
static UINT (WINAPI *pUFromSz)(LPCSTR);
static ULONG (WINAPI *pUlFromSzHex)(LPCSTR);
static ULONG (WINAPI *pCbOfEncoded)(LPCSTR);
static BOOL (WINAPI *pIsBadBoundedStringPtr)(LPCSTR,ULONG);
static void test_SwapPword(void)
{
USHORT shorts[3];
pSwapPword = (void*)GetProcAddress(hMapi32, "SwapPword@8");
if (!pSwapPword)
return;
shorts[0] = 0xff01;
shorts[1] = 0x10ff;
shorts[2] = 0x2001;
pSwapPword(shorts, 2);
ok(shorts[0] == 0x01ff && shorts[1] == 0xff10 && shorts[2] == 0x2001,
"Expected {0x01ff,0xff10,0x2001}, got {0x%04x,0x%04x,0x%04x}\n",
shorts[0], shorts[1], shorts[2]);
}
static void test_SwapPlong(void)
{
ULONG longs[3];
pSwapPlong = (void*)GetProcAddress(hMapi32, "SwapPlong@8");
if (!pSwapPlong)
return;
longs[0] = 0xffff0001;
longs[1] = 0x1000ffff;
longs[2] = 0x20000001;
pSwapPlong(longs, 2);
ok(longs[0] == 0x0100ffff && longs[1] == 0xffff0010 && longs[2] == 0x20000001,
"Expected {0x0100ffff,0xffff0010,0x20000001}, got {0x%08x,0x%08x,0x%08x}\n",
longs[0], longs[1], longs[2]);
}
static void test_HexFromBin(void)
{
static char res[] = { "000102030405060708090A0B0C0D0E0F101112131415161"
"718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B"
"3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6"
"06162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F8081828384"
"85868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A"
"9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCD"
"CECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F"
"2F3F4F5F6F7F8F9FAFBFCFDFE\0X" };
BYTE data[255];
WCHAR strw[256];
BOOL bOk;
int i;
pHexFromBin = (void*)GetProcAddress(hMapi32, "HexFromBin@12");
pFBinFromHex = (void*)GetProcAddress(hMapi32, "FBinFromHex@8");
if (!pHexFromBin || !pFBinFromHex)
return;
for (i = 0; i < 255; i++)
data[i] = i;
memset(strw, 'X', sizeof(strw));
pHexFromBin(data, sizeof(data), strw);
ok(memcmp(strw, res, sizeof(res) - 1) == 0, "HexFromBin: Result differs\n");
memset(data, 0, sizeof(data));
pFBinFromHex((LPWSTR)res, data);
bOk = TRUE;
for (i = 0; i < 255; i++)
if (data[i] != i)
bOk = FALSE;
ok(bOk == TRUE, "FBinFromHex: Result differs\n");
}
static void test_UFromSz(void)
{
pUFromSz = (void*)GetProcAddress(hMapi32, "UFromSz@4");
if (!pUFromSz)
return;
ok(pUFromSz("105679") == 105679u,
"UFromSz: expected 105679, got %d\n", pUFromSz("105679"));
ok(pUFromSz(" 4") == 0, "UFromSz: exected 0. got %d\n",
pUFromSz(" 4"));
}
static void test_UlFromSzHex(void)
{
pUlFromSzHex = (void*)GetProcAddress(hMapi32, "UlFromSzHex@4");
if (!pUlFromSzHex)
return;
ok(pUlFromSzHex("fF") == 0xffu,
"UlFromSzHex: expected 0xff, got 0x%x\n", pUlFromSzHex("fF"));
ok(pUlFromSzHex(" c") == 0, "UlFromSzHex: exected 0x0. got 0x%x\n",
pUlFromSzHex(" c"));
}
static void test_CbOfEncoded(void)
{
char buff[129];
unsigned int i;
pCbOfEncoded = (void*)GetProcAddress(hMapi32, "CbOfEncoded@4");
if (!pCbOfEncoded)
return;
for (i = 0; i < sizeof(buff) - 1; i++)
{
ULONG ulRet, ulExpected = (((i | 3) >> 2) + 1) * 3;
memset(buff, '\0', sizeof(buff));
memset(buff, '?', i);
ulRet = pCbOfEncoded(buff);
ok(ulRet == ulExpected, "CbOfEncoded(length %d): expected %d, got %d\n",
i, ulExpected, ulRet);
}
}
static void test_IsBadBoundedStringPtr(void)
{
pIsBadBoundedStringPtr = (void*)GetProcAddress(hMapi32, "IsBadBoundedStringPtr@8");
if (!pIsBadBoundedStringPtr)
return;
ok(pIsBadBoundedStringPtr(NULL, 0) == TRUE, "IsBadBoundedStringPtr: expected TRUE\n");
ok(pIsBadBoundedStringPtr("TEST", 4) == TRUE, "IsBadBoundedStringPtr: expected TRUE\n");
ok(pIsBadBoundedStringPtr("TEST", 5) == FALSE, "IsBadBoundedStringPtr: expected FALSE\n");
}
START_TEST(util)
{
SCODE ret;
hMapi32 = LoadLibraryA("mapi32.dll");
pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4");
if (!pScInitMapiUtil)
{
skip("ScInitMapiUtil is not available\n");
FreeLibrary(hMapi32);
return;
}
SetLastError(0xdeadbeef);
ret = pScInitMapiUtil(0);
if ((ret != S_OK) && (GetLastError() == ERROR_PROC_NOT_FOUND))
{
skip("ScInitMapiUtil is not implemented\n");
FreeLibrary(hMapi32);
return;
}
test_SwapPword();
test_SwapPlong();
test_HexFromBin();
test_UFromSz();
test_UlFromSzHex();
test_CbOfEncoded();
test_IsBadBoundedStringPtr();
FreeLibrary(hMapi32);
}

View file

@ -629,7 +629,7 @@ static void IMLangFontLink_Test(IMLangFontLink* iMLFL)
"IMLangFontLink_CodePageToCodePages failed\n");
ok (dwCodePages != 0, "No CodePages returned\n");
ok(IMLangFontLink_CodePagesToCodePage(iMLFL, dwCodePages, 1035,
&CodePage)==S_OK,
&CodePage)==S_OK,
"IMLangFontLink_CodePagesToCodePage failed\n");
ok(CodePage == 932, "Incorrect CodePage Returned (%i)\n",CodePage);
@ -644,12 +644,12 @@ static void IMLangFontLink_Test(IMLangFontLink* iMLFL)
dwManyCodePages = dwManyCodePages | dwCodePages;
ok(IMLangFontLink_CodePagesToCodePage(iMLFL, dwManyCodePages, 1256,
&CodePage)==S_OK,
&CodePage)==S_OK,
"IMLangFontLink_CodePagesToCodePage failed\n");
ok(CodePage == 1256, "Incorrect CodePage Returned (%i)\n",CodePage);
ok(IMLangFontLink_CodePagesToCodePage(iMLFL, dwManyCodePages, 936,
&CodePage)==S_OK,
&CodePage)==S_OK,
"IMLangFontLink_CodePagesToCodePage failed\n");
ok(CodePage == 1252, "Incorrect CodePage Returned (%i)\n",CodePage);
}
@ -677,6 +677,7 @@ static void test_rfc1766(IMultiLanguage2 *iML2)
ok(n == 1, "couldn't fetch 1 RFC1766INFO structure\n");
ok(IsValidLocale(info.lcid, LCID_SUPPORTED), "invalid lcid %04x\n", info.lcid);
}
IEnumRfc1766_Release(pEnumRfc1766);
}
static void test_GetLcidFromRfc1766(IMultiLanguage2 *iML2)
@ -783,6 +784,6 @@ START_TEST(mlang)
IMLangFontLink_Test(iMLFL);
IMLangFontLink_Release(iMLFL);
CoUninitialize();
}

View file

@ -1,9 +1,9 @@
<module name="mlang_winetest" type="win32cui" installbase="bin" installname="mlang_winetest.exe" allowwarnings="true">
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="mlang_winetest" type="win32cui" installbase="bin" installname="mlang_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="mlang_winetest">.</include>
<define name="__USE_W32API" />
<define name="_WIN32_IE">0x600</define>
<define name="_WIN32_WINNT">0x501</define>
<define name="WINVER">0x501</define>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>ole32</library>
<library>gdi32</library>

View file

@ -0,0 +1,345 @@
/*
* Copyright 2002 Andriy Palamarchuk
*
* Conformance test of the access functions.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <windef.h>
#include <winbase.h>
#include <winerror.h>
#include <lmaccess.h>
#include <lmerr.h>
#include <lmapibuf.h>
#include "wine/test.h"
WCHAR user_name[UNLEN + 1];
WCHAR computer_name[MAX_COMPUTERNAME_LENGTH + 1];
static const WCHAR sNonexistentUser[] = {'N','o','n','e','x','i','s','t','e','n','t',' ',
'U','s','e','r',0};
static WCHAR sTooLongName[] = {'T','h','i','s',' ','i','s',' ','a',' ','b','a','d',
' ','u','s','e','r','n','a','m','e',0};
static WCHAR sTooLongPassword[] = {'a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h',
'a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h',
'a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h',
'a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h',
'a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h',
'a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h',
'a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h',
'a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h',
'a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h',
'a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h',
'a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h','a','b','c','d','e','f','g','h',
'a', 0};
static WCHAR sTestUserName[] = {'t', 'e', 's', 't', 'u', 's', 'e', 'r', 0};
static WCHAR sTestUserOldPass[] = {'o', 'l', 'd', 'p', 'a', 's', 's', 0};
static WCHAR sTestUserNewPass[] = {'n', 'e', 'w', 'p', 'a', 's', 's', 0};
static const WCHAR sBadNetPath[] = {'\\','\\','B','a',' ',' ','p','a','t','h',0};
static const WCHAR sInvalidName[] = {'\\',0};
static const WCHAR sInvalidName2[] = {'\\','\\',0};
static const WCHAR sEmptyStr[] = { 0 };
static NET_API_STATUS (WINAPI *pNetApiBufferFree)(LPVOID)=NULL;
static NET_API_STATUS (WINAPI *pNetApiBufferSize)(LPVOID,LPDWORD)=NULL;
static NET_API_STATUS (WINAPI *pNetQueryDisplayInformation)(LPWSTR,DWORD,DWORD,DWORD,DWORD,LPDWORD,PVOID*)=NULL;
static NET_API_STATUS (WINAPI *pNetUserGetInfo)(LPCWSTR,LPCWSTR,DWORD,LPBYTE*)=NULL;
static NET_API_STATUS (WINAPI *pNetUserModalsGet)(LPCWSTR,DWORD,LPBYTE*)=NULL;
static NET_API_STATUS (WINAPI *pNetUserAdd)(LPCWSTR,DWORD,LPBYTE,LPDWORD)=NULL;
static NET_API_STATUS (WINAPI *pNetUserChangePassword)(LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR)=NULL;
static NET_API_STATUS (WINAPI *pNetUserDel)(LPCWSTR,LPCWSTR)=NULL;
static int init_access_tests(void)
{
DWORD dwSize;
BOOL rc;
user_name[0] = 0;
dwSize = sizeof(user_name);
rc=GetUserNameW(user_name, &dwSize);
if (rc==FALSE && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
{
skip("GetUserNameW is not available.\n");
return 0;
}
ok(rc, "User Name Retrieved\n");
computer_name[0] = 0;
dwSize = sizeof(computer_name);
ok(GetComputerNameW(computer_name, &dwSize), "Computer Name Retrieved\n");
return 1;
}
static NET_API_STATUS create_test_user(void)
{
USER_INFO_1 usri;
usri.usri1_name = sTestUserName;
usri.usri1_password = sTestUserOldPass;
usri.usri1_priv = USER_PRIV_USER;
usri.usri1_home_dir = NULL;
usri.usri1_comment = NULL;
usri.usri1_flags = UF_SCRIPT;
usri.usri1_script_path = NULL;
return pNetUserAdd(NULL, 1, (LPBYTE)&usri, NULL);
}
static NET_API_STATUS delete_test_user(void)
{
return pNetUserDel(NULL, sTestUserName);
}
static void run_usergetinfo_tests(void)
{
NET_API_STATUS rc;
PUSER_INFO_0 ui0 = NULL;
PUSER_INFO_10 ui10 = NULL;
DWORD dwSize;
if((rc = create_test_user()) != NERR_Success )
{
skip("Skipping usergetinfo_tests, create_test_user failed: 0x%08x\n", rc);
return;
}
/* Level 0 */
rc=pNetUserGetInfo(NULL, sTestUserName, 0, (LPBYTE *)&ui0);
ok(rc == NERR_Success, "NetUserGetInfo level 0 failed: 0x%08x.\n", rc);
ok(!lstrcmpW(sTestUserName, ui0->usri0_name),"Username mismatch for level 0.\n");
pNetApiBufferSize(ui0, &dwSize);
ok(dwSize >= (sizeof(USER_INFO_0) +
(lstrlenW(ui0->usri0_name) + 1) * sizeof(WCHAR)),
"Is allocated with NetApiBufferAllocate\n");
/* Level 10 */
rc=pNetUserGetInfo(NULL, sTestUserName, 10, (LPBYTE *)&ui10);
ok(rc == NERR_Success, "NetUserGetInfo level 10 failed: 0x%08x.\n", rc);
ok(!lstrcmpW(sTestUserName, ui10->usri10_name), "Username mismatch for level 10.\n");
pNetApiBufferSize(ui10, &dwSize);
ok(dwSize >= (sizeof(USER_INFO_10) +
(lstrlenW(ui10->usri10_name) + 1 +
lstrlenW(ui10->usri10_comment) + 1 +
lstrlenW(ui10->usri10_usr_comment) + 1 +
lstrlenW(ui10->usri10_full_name) + 1) * sizeof(WCHAR)),
"Is allocated with NetApiBufferAllocate\n");
pNetApiBufferFree(ui0);
pNetApiBufferFree(ui10);
/* errors handling */
rc=pNetUserGetInfo(NULL, sTestUserName, 10000, (LPBYTE *)&ui0);
ok(rc == ERROR_INVALID_LEVEL,"Invalid Level: rc=%d\n",rc);
rc=pNetUserGetInfo(NULL, sNonexistentUser, 0, (LPBYTE *)&ui0);
ok(rc == NERR_UserNotFound,"Invalid User Name: rc=%d\n",rc);
todo_wine {
/* FIXME - Currently Wine can't verify whether the network path is good or bad */
rc=pNetUserGetInfo(sBadNetPath, sTestUserName, 0, (LPBYTE *)&ui0);
ok(rc == ERROR_BAD_NETPATH || rc == ERROR_NETWORK_UNREACHABLE,
"Bad Network Path: rc=%d\n",rc);
}
rc=pNetUserGetInfo(sEmptyStr, sTestUserName, 0, (LPBYTE *)&ui0);
ok(rc == ERROR_BAD_NETPATH || rc == NERR_Success,
"Bad Network Path: rc=%d\n",rc);
rc=pNetUserGetInfo(sInvalidName, sTestUserName, 0, (LPBYTE *)&ui0);
ok(rc == ERROR_INVALID_NAME,"Invalid Server Name: rc=%d\n",rc);
rc=pNetUserGetInfo(sInvalidName2, sTestUserName, 0, (LPBYTE *)&ui0);
ok(rc == ERROR_INVALID_NAME,"Invalid Server Name: rc=%d\n",rc);
if(delete_test_user() != NERR_Success)
trace("Deleting the test user failed. You might have to manually delete it.\n");
}
/* checks Level 1 of NetQueryDisplayInformation
* FIXME: Needs to be rewritten to not depend on the spelling of the users,
* ideally based on the admin and guest user SIDs/RIDs.*/
static void run_querydisplayinformation1_tests(void)
{
PNET_DISPLAY_USER Buffer, rec;
DWORD Result, EntryCount;
DWORD i = 0;
BOOL hasAdmin = FALSE;
BOOL hasGuest = FALSE;
static const WCHAR sAdminUserName[] = {'A','d','m','i','n','i','s','t','r','a',
't','o','r',0};
static const WCHAR sGuestUserName[] = {'G','u','e','s','t',0};
do
{
Result = pNetQueryDisplayInformation(
NULL, 1, i, 1000, MAX_PREFERRED_LENGTH, &EntryCount,
(PVOID *)&Buffer);
ok((Result == ERROR_SUCCESS) || (Result == ERROR_MORE_DATA),
"Information Retrieved\n");
rec = Buffer;
for(; EntryCount > 0; EntryCount--)
{
if (!lstrcmpW(rec->usri1_name, sAdminUserName))
{
ok(!hasAdmin, "One admin user\n");
ok(rec->usri1_flags & UF_SCRIPT, "UF_SCRIPT flag is set\n");
ok(rec->usri1_flags & UF_NORMAL_ACCOUNT, "UF_NORMAL_ACCOUNT flag is set\n");
hasAdmin = TRUE;
}
else if (!lstrcmpW(rec->usri1_name, sGuestUserName))
{
ok(!hasGuest, "One guest record\n");
ok(rec->usri1_flags & UF_SCRIPT, "UF_SCRIPT flag is set\n");
ok(rec->usri1_flags & UF_NORMAL_ACCOUNT, "UF_NORMAL_ACCOUNT flag is set\n");
hasGuest = TRUE;
}
i = rec->usri1_next_index;
rec++;
}
pNetApiBufferFree(Buffer);
} while (Result == ERROR_MORE_DATA);
ok(hasAdmin, "Has Administrator account\n");
}
static void run_usermodalsget_tests(void)
{
NET_API_STATUS rc;
USER_MODALS_INFO_2 * umi2 = NULL;
rc = pNetUserModalsGet(NULL, 2, (LPBYTE *)&umi2);
ok(rc == ERROR_SUCCESS, "NetUserModalsGet failed, rc = %d\n", rc);
if (umi2)
pNetApiBufferFree(umi2);
}
static void run_userhandling_tests(void)
{
NET_API_STATUS ret;
USER_INFO_1 usri;
usri.usri1_priv = USER_PRIV_USER;
usri.usri1_home_dir = NULL;
usri.usri1_comment = NULL;
usri.usri1_flags = UF_SCRIPT;
usri.usri1_script_path = NULL;
usri.usri1_name = sTooLongName;
usri.usri1_password = sTestUserOldPass;
ret = pNetUserAdd(NULL, 1, (LPBYTE)&usri, NULL);
ok(ret == NERR_BadUsername, "Adding user with too long username returned 0x%08x\n", ret);
usri.usri1_name = sTestUserName;
usri.usri1_password = sTooLongPassword;
ret = pNetUserAdd(NULL, 1, (LPBYTE)&usri, NULL);
ok(ret == NERR_PasswordTooShort, "Adding user with too long password returned 0x%08x\n", ret);
usri.usri1_name = sTooLongName;
usri.usri1_password = sTooLongPassword;
ret = pNetUserAdd(NULL, 1, (LPBYTE)&usri, NULL);
ok(ret == NERR_BadUsername,
"Adding user with too long username/password returned 0x%08x\n", ret);
usri.usri1_name = sTestUserName;
usri.usri1_password = sTestUserOldPass;
ret = pNetUserAdd(NULL, 5, (LPBYTE)&usri, NULL);
ok(ret == ERROR_INVALID_LEVEL, "Adding user with level 5 returned 0x%08x\n", ret);
ret = pNetUserAdd(NULL, 1, (LPBYTE)&usri, NULL);
if(ret == ERROR_ACCESS_DENIED)
{
skip("Insufficient permissions to add users. Skipping test.\n");
return;
}
if(ret == NERR_UserExists)
{
skip("User already exists, skipping test to not mess up the system\n");
return;
}
ok(ret == NERR_Success, "Adding user failed with error 0x%08x\n", ret);
if(ret != NERR_Success)
return;
ret = pNetUserChangePassword(NULL, sNonexistentUser, sTestUserOldPass,
sTestUserNewPass);
ok(ret == NERR_UserNotFound,
"Changing password for nonexistent user returned 0x%08x.\n", ret);
ret = pNetUserChangePassword(NULL, sTestUserName, sTestUserOldPass,
sTestUserOldPass);
ok(ret == NERR_Success,
"Changing old password to old password returned 0x%08x.\n", ret);
ret = pNetUserChangePassword(NULL, sTestUserName, sTestUserNewPass,
sTestUserOldPass);
ok(ret == ERROR_INVALID_PASSWORD,
"Trying to change password giving an invalid password returned 0x%08x.\n", ret);
ret = pNetUserChangePassword(NULL, sTestUserName, sTestUserOldPass,
sTooLongPassword);
ok(ret == ERROR_PASSWORD_RESTRICTION,
"Changing to a password that's too long returned 0x%08x.\n", ret);
ret = pNetUserChangePassword(NULL, sTestUserName, sTestUserOldPass,
sTestUserNewPass);
ok(ret == NERR_Success, "Changing the password correctly returned 0x%08x.\n", ret);
ret = pNetUserDel(NULL, sTestUserName);
ok(ret == NERR_Success, "Deleting the user failed.\n");
ret = pNetUserDel(NULL, sTestUserName);
ok(ret == NERR_UserNotFound, "Deleting a nonexistent user returned 0x%08x\n",ret);
}
START_TEST(access)
{
HMODULE hnetapi32=LoadLibraryA("netapi32.dll");
pNetApiBufferFree=(void*)GetProcAddress(hnetapi32,"NetApiBufferFree");
pNetApiBufferSize=(void*)GetProcAddress(hnetapi32,"NetApiBufferSize");
pNetQueryDisplayInformation=(void*)GetProcAddress(hnetapi32,"NetQueryDisplayInformation");
pNetUserGetInfo=(void*)GetProcAddress(hnetapi32,"NetUserGetInfo");
pNetUserModalsGet=(void*)GetProcAddress(hnetapi32,"NetUserModalsGet");
pNetUserAdd=(void*)GetProcAddress(hnetapi32, "NetUserAdd");
pNetUserChangePassword=(void*)GetProcAddress(hnetapi32, "NetUserChangePassword");
pNetUserDel=(void*)GetProcAddress(hnetapi32, "NetUserDel");
/* These functions were introduced with NT. It's safe to assume that
* if one is not available, none are.
*/
if (!pNetApiBufferFree) {
skip("Needed functions are not available\n");
FreeLibrary(hnetapi32);
return;
}
if (init_access_tests()) {
run_userhandling_tests();
run_usergetinfo_tests();
run_querydisplayinformation1_tests();
run_usermodalsget_tests();
}
FreeLibrary(hnetapi32);
}

View file

@ -0,0 +1,107 @@
/*
* Copyright 2002 Andriy Palamarchuk
*
* Conformance test of the network buffer function.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "wine/test.h"
#include <windef.h>
#include <winbase.h>
#include <winerror.h>
#include <lmcons.h>
#include <lmerr.h>
#include <lmapibuf.h>
#include <lmaccess.h>
static NET_API_STATUS (WINAPI *pNetApiBufferAllocate)(DWORD,LPVOID*)=NULL;
static NET_API_STATUS (WINAPI *pNetApiBufferFree)(LPVOID)=NULL;
static NET_API_STATUS (WINAPI *pNetApiBufferReallocate)(LPVOID,DWORD,LPVOID*)=NULL;
static NET_API_STATUS (WINAPI *pNetApiBufferSize)(LPVOID,LPDWORD)=NULL;
static void run_apibuf_tests(void)
{
VOID *p;
DWORD dwSize;
NET_API_STATUS res;
/* test normal logic */
ok(pNetApiBufferAllocate(1024, (LPVOID *)&p) == NERR_Success,
"Reserved memory\n");
ok(pNetApiBufferSize(p, &dwSize) == NERR_Success, "Got size\n");
ok(dwSize >= 1024, "The size is correct\n");
ok(pNetApiBufferReallocate(p, 1500, (LPVOID *) &p) == NERR_Success,
"Reallocated\n");
ok(pNetApiBufferSize(p, &dwSize) == NERR_Success, "Got size\n");
ok(dwSize >= 1500, "The size is correct\n");
ok(pNetApiBufferFree(p) == NERR_Success, "Freed\n");
/* test errors handling */
ok(pNetApiBufferFree(p) == NERR_Success, "Freed\n");
ok(pNetApiBufferSize(p, &dwSize) == NERR_Success, "Got size\n");
ok(pNetApiBufferSize(NULL, &dwSize) == ERROR_INVALID_PARAMETER, "Error for NULL pointer\n");
/* border reallocate cases */
ok(pNetApiBufferReallocate(0, 1500, (LPVOID *) &p) == NERR_Success, "Reallocate with OldBuffer = NULL failed\n");
ok(p != NULL, "No memory got allocated\n");
ok(pNetApiBufferAllocate(1024, (LPVOID *)&p) == NERR_Success, "Memory not reserved\n");
ok(pNetApiBufferReallocate(p, 0, (LPVOID *) &p) == NERR_Success, "Not freed\n");
ok(p == NULL, "Pointer not cleared\n");
/* 0-length buffer */
ok(pNetApiBufferAllocate(0, (LPVOID *)&p) == NERR_Success,
"Reserved memory\n");
ok(pNetApiBufferSize(p, &dwSize) == NERR_Success, "Got size\n");
ok(dwSize < 0xFFFFFFFF, "The size of the 0-length buffer\n");
ok(pNetApiBufferFree(p) == NERR_Success, "Freed\n");
/* NULL-Pointer */
/* NT: ERROR_INVALID_PARAMETER, lasterror is untouched) */
SetLastError(0xdeadbeef);
res = pNetApiBufferAllocate(0, (LPVOID *)NULL);
ok( (res == ERROR_INVALID_PARAMETER) && (GetLastError() == 0xdeadbeef),
"returned %d with 0x%x (expected ERROR_INVALID_PARAMETER with "
"0xdeadbeef)\n", res, GetLastError());
SetLastError(0xdeadbeef);
res = pNetApiBufferAllocate(1024, (LPVOID *)NULL);
ok( (res == ERROR_INVALID_PARAMETER) && (GetLastError() == 0xdeadbeef),
"returned %d with 0x%x (expected ERROR_INVALID_PARAMETER with "
"0xdeadbeef)\n", res, GetLastError());
}
START_TEST(apibuf)
{
HMODULE hnetapi32=LoadLibraryA("netapi32.dll");
pNetApiBufferAllocate=(void*)GetProcAddress(hnetapi32,"NetApiBufferAllocate");
pNetApiBufferFree=(void*)GetProcAddress(hnetapi32,"NetApiBufferFree");
pNetApiBufferReallocate=(void*)GetProcAddress(hnetapi32,"NetApiBufferReallocate");
pNetApiBufferSize=(void*)GetProcAddress(hnetapi32,"NetApiBufferSize");
if (pNetApiBufferAllocate && pNetApiBufferFree && pNetApiBufferReallocate && pNetApiBufferSize)
run_apibuf_tests();
else
skip("Needed functions are not available\n");
FreeLibrary(hnetapi32);
}

View file

@ -0,0 +1,93 @@
/*
* Copyright 2005 Paul Vriens
*
* Conformance test of the ds functions.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <wine/test.h>
#include <windef.h>
#include <winbase.h>
#include <winerror.h>
#include <dsrole.h>
static DWORD (WINAPI *pDsRoleGetPrimaryDomainInformation)(LPCWSTR, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL, PBYTE*);
static void (WINAPI *pDsRoleFreeMemory)(PVOID);
static void test_params(void)
{
DWORD ret;
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC dpdi;
SetLastError(0xdeadbeef);
ret = pDsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, NULL);
ok( ret == ERROR_INVALID_PARAMETER, "Expected error ERROR_INVALID_PARAMETER, got (%d)\n", ret);
SetLastError(0xdeadbeef);
ret = pDsRoleGetPrimaryDomainInformation(NULL, 0, NULL);
ok( ret == ERROR_INVALID_PARAMETER, "Expected error ERROR_INVALID_PARAMETER, got (%d)\n", ret);
SetLastError(0xdeadbeef);
ret = pDsRoleGetPrimaryDomainInformation(NULL, 4, NULL);
ok( ret == ERROR_INVALID_PARAMETER, "Expected error ERROR_INVALID_PARAMETER, got (%d)\n", ret);
SetLastError(0xdeadbeef);
ret = pDsRoleGetPrimaryDomainInformation(NULL, 4, (PBYTE *)&dpdi);
ok( ret == ERROR_INVALID_PARAMETER, "Expected error ERROR_INVALID_PARAMETER, got (%d)\n", ret);
}
static void test_get(void)
{
DWORD ret;
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC dpdi;
PDSROLE_UPGRADE_STATUS_INFO dusi;
PDSROLE_OPERATION_STATE_INFO dosi;
SetLastError(0xdeadbeef);
ret = pDsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, (PBYTE *)&dpdi);
ok( ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got (%d)\n", ret);
pDsRoleFreeMemory(&dpdi);
SetLastError(0xdeadbeef);
ret = pDsRoleGetPrimaryDomainInformation(NULL, DsRoleUpgradeStatus, (PBYTE *)&dusi);
todo_wine { ok( ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got (%d)\n", ret); }
pDsRoleFreeMemory(&dusi);
SetLastError(0xdeadbeef);
ret = pDsRoleGetPrimaryDomainInformation(NULL, DsRoleOperationState, (PBYTE *)&dosi);
todo_wine { ok( ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got (%d)\n", ret); }
pDsRoleFreeMemory(&dosi);
}
START_TEST(ds)
{
HMODULE hnetapi32 = LoadLibrary("netapi32.dll");
pDsRoleGetPrimaryDomainInformation=(void*)GetProcAddress(hnetapi32,"DsRoleGetPrimaryDomainInformation");
if (pDsRoleGetPrimaryDomainInformation)
{
pDsRoleFreeMemory=(void*)GetProcAddress(hnetapi32,"DsRoleFreeMemory");
test_params();
test_get();
}
else
skip("DsRoleGetPrimaryDomainInformation is not available\n");
FreeLibrary(hnetapi32);
}

View file

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="netapi32_winetest" type="win32cui" installbase="bin" installname="netapi32_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="netapi32_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>netapi32</library>
<library>advapi32</library>
<library>kernel32</library>
<library>ntdll</library>
<file>access.c</file>
<file>apibuf.c</file>
<file>ds.c</file>
<file>wksta.c</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,21 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_access(void);
extern void func_apibuf(void);
extern void func_ds(void);
extern void func_wksta(void);
const struct test winetest_testlist[] =
{
{ "access", func_access },
{ "apibuf", func_apibuf },
{ "ds", func_ds },
{ "wksta", func_wksta },
{ 0, 0 }
};

View file

@ -0,0 +1,197 @@
/*
* Copyright 2002 Andriy Palamarchuk
*
* Conformance test of the workstation functions.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winnls.h"
#include "winresrc.h" /* Ensure we use Unicode defns with native headers */
#include "nb30.h"
#include "lmcons.h"
#include "lmerr.h"
#include "lmwksta.h"
#include "lmapibuf.h"
static NET_API_STATUS (WINAPI *pNetApiBufferFree)(LPVOID)=NULL;
static NET_API_STATUS (WINAPI *pNetApiBufferSize)(LPVOID,LPDWORD)=NULL;
static NET_API_STATUS (WINAPI *pNetpGetComputerName)(LPWSTR*)=NULL;
static NET_API_STATUS (WINAPI *pNetWkstaUserGetInfo)(LPWSTR,DWORD,PBYTE*)=NULL;
static NET_API_STATUS (WINAPI *pNetWkstaTransportEnum)(LPWSTR,DWORD,LPBYTE*,
DWORD,LPDWORD,LPDWORD,LPDWORD)=NULL;
WCHAR user_name[UNLEN + 1];
WCHAR computer_name[MAX_COMPUTERNAME_LENGTH + 1];
static int init_wksta_tests(void)
{
DWORD dwSize;
BOOL rc;
user_name[0] = 0;
dwSize = sizeof(user_name);
rc=GetUserNameW(user_name, &dwSize);
if (rc==FALSE && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED) {
skip("GetUserNameW is not implemented\n");
return 0;
}
ok(rc, "User Name Retrieved\n");
computer_name[0] = 0;
dwSize = sizeof(computer_name);
ok(GetComputerNameW(computer_name, &dwSize), "Computer Name Retrieved\n");
return 1;
}
static void run_get_comp_name_tests(void)
{
LPWSTR ws = NULL;
ok(pNetpGetComputerName(&ws) == NERR_Success, "Computer name is retrieved\n");
ok(!lstrcmpW(computer_name, ws), "This is really computer name\n");
pNetApiBufferFree(ws);
}
static void run_wkstausergetinfo_tests(void)
{
LPWKSTA_USER_INFO_0 ui0 = NULL;
LPWKSTA_USER_INFO_1 ui1 = NULL;
LPWKSTA_USER_INFO_1101 ui1101 = NULL;
DWORD dwSize;
/* Level 0 */
ok(pNetWkstaUserGetInfo(NULL, 0, (LPBYTE *)&ui0) == NERR_Success,
"NetWkstaUserGetInfo is successful\n");
ok(!lstrcmpW(user_name, ui0->wkui0_username), "This is really user name\n");
pNetApiBufferSize(ui0, &dwSize);
ok(dwSize >= (sizeof(WKSTA_USER_INFO_0) +
lstrlenW(ui0->wkui0_username) * sizeof(WCHAR)),
"Is allocated with NetApiBufferAllocate\n");
/* Level 1 */
ok(pNetWkstaUserGetInfo(NULL, 1, (LPBYTE *)&ui1) == NERR_Success,
"NetWkstaUserGetInfo is successful\n");
ok(lstrcmpW(ui1->wkui1_username, ui0->wkui0_username) == 0,
"the same name as returned for level 0\n");
pNetApiBufferSize(ui1, &dwSize);
ok(dwSize >= (sizeof(WKSTA_USER_INFO_1) +
(lstrlenW(ui1->wkui1_username) +
lstrlenW(ui1->wkui1_logon_domain) +
lstrlenW(ui1->wkui1_oth_domains) +
lstrlenW(ui1->wkui1_logon_server)) * sizeof(WCHAR)),
"Is allocated with NetApiBufferAllocate\n");
/* Level 1101 */
ok(pNetWkstaUserGetInfo(NULL, 1101, (LPBYTE *)&ui1101) == NERR_Success,
"NetWkstaUserGetInfo is successful\n");
ok(lstrcmpW(ui1101->wkui1101_oth_domains, ui1->wkui1_oth_domains) == 0,
"the same oth_domains as returned for level 1\n");
pNetApiBufferSize(ui1101, &dwSize);
ok(dwSize >= (sizeof(WKSTA_USER_INFO_1101) +
lstrlenW(ui1101->wkui1101_oth_domains) * sizeof(WCHAR)),
"Is allocated with NetApiBufferAllocate\n");
pNetApiBufferFree(ui0);
pNetApiBufferFree(ui1);
pNetApiBufferFree(ui1101);
/* errors handling */
ok(pNetWkstaUserGetInfo(NULL, 10000, (LPBYTE *)&ui0) == ERROR_INVALID_LEVEL,
"Invalid level\n");
}
static void run_wkstatransportenum_tests(void)
{
LPBYTE bufPtr;
NET_API_STATUS apiReturn;
DWORD entriesRead, totalEntries;
/* 1st check: is param 2 (level) correct? (only if param 5 passed?) */
apiReturn = pNetWkstaTransportEnum(NULL, 1, NULL, MAX_PREFERRED_LENGTH,
NULL, &totalEntries, NULL);
ok(apiReturn == ERROR_INVALID_LEVEL || apiReturn == ERROR_INVALID_PARAMETER,
"NetWkstaTransportEnum returned %d\n", apiReturn);
/* 2nd check: is param 5 passed? (only if level passes?) */
apiReturn = pNetWkstaTransportEnum(NULL, 0, NULL, MAX_PREFERRED_LENGTH,
NULL, &totalEntries, NULL);
/* if no network adapter present, bail, the rest of the test will fail */
if (apiReturn == ERROR_NETWORK_UNREACHABLE)
return;
ok(apiReturn == STATUS_ACCESS_VIOLATION || apiReturn == ERROR_INVALID_PARAMETER,
"NetWkstaTransportEnum returned %d\n", apiReturn);
/* 3rd check: is param 3 passed? */
apiReturn = pNetWkstaTransportEnum(NULL, 0, NULL, MAX_PREFERRED_LENGTH,
NULL, NULL, NULL);
ok(apiReturn == STATUS_ACCESS_VIOLATION || apiReturn == RPC_X_NULL_REF_POINTER || apiReturn == ERROR_INVALID_PARAMETER,
"NetWkstaTransportEnum returned %d\n", apiReturn);
/* 4th check: is param 6 passed? */
apiReturn = pNetWkstaTransportEnum(NULL, 0, &bufPtr, MAX_PREFERRED_LENGTH,
&entriesRead, NULL, NULL);
ok(apiReturn == RPC_X_NULL_REF_POINTER, "null pointer\n");
/* final check: valid return, actually get data back */
apiReturn = pNetWkstaTransportEnum(NULL, 0, &bufPtr, MAX_PREFERRED_LENGTH,
&entriesRead, &totalEntries, NULL);
ok(apiReturn == NERR_Success || apiReturn == ERROR_NETWORK_UNREACHABLE,
"NetWkstaTransportEnum returned %d\n", apiReturn);
if (apiReturn == NERR_Success) {
/* WKSTA_TRANSPORT_INFO_0 *transports = (WKSTA_TRANSPORT_INFO_0 *)bufPtr; */
ok(bufPtr != NULL, "got data back\n");
ok(entriesRead > 0, "read at least one transport\n");
ok(totalEntries > 0, "at least one transport\n");
pNetApiBufferFree(bufPtr);
}
}
START_TEST(wksta)
{
HMODULE hnetapi32=LoadLibraryA("netapi32.dll");
pNetApiBufferFree=(void*)GetProcAddress(hnetapi32,"NetApiBufferFree");
pNetApiBufferSize=(void*)GetProcAddress(hnetapi32,"NetApiBufferSize");
pNetpGetComputerName=(void*)GetProcAddress(hnetapi32,"NetpGetComputerName");
pNetWkstaUserGetInfo=(void*)GetProcAddress(hnetapi32,"NetWkstaUserGetInfo");
pNetWkstaTransportEnum=(void*)GetProcAddress(hnetapi32,"NetWkstaTransportEnum");
/* These functions were introduced with NT. It's safe to assume that
* if one is not available, none are.
*/
if (!pNetApiBufferFree) {
skip("Needed functions are not available\n");
FreeLibrary(hnetapi32);
return;
}
if (init_wksta_tests()) {
run_get_comp_name_tests();
run_wkstausergetinfo_tests();
run_wkstatransportenum_tests();
}
FreeLibrary(hnetapi32);
}

View file

@ -0,0 +1,132 @@
/*
* Copyright 2007 Bill Medland
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wine/test.h>
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "odbcinst.h"
static void test_SQLConfigMode(void)
{
BOOL bool_ret;
DWORD error_code;
RETCODE sql_ret;
UWORD config_mode;
int i;
ok(SQLGetConfigMode(NULL), "SQLGetConfigMode(NULL) should succeed\n");
bool_ret = SQLGetConfigMode(&config_mode);
ok(bool_ret && config_mode == ODBC_BOTH_DSN, "Failed to get the initial SQLGetConfigMode or it was not both\n");
bool_ret = SQLSetConfigMode(3);
sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
ok(!bool_ret && sql_ret == SQL_SUCCESS_WITH_INFO && error_code == ODBC_ERROR_INVALID_PARAM_SEQUENCE, "SQLSetConfigMode with invalid argument did not fail correctly\n");
ok (ODBC_SYSTEM_DSN == 2 && ODBC_USER_DSN == 1 && ODBC_BOTH_DSN == 0, "SQLSetConfigMode modes not as expected\n");
for (i = ODBC_SYSTEM_DSN; i >= ODBC_BOTH_DSN; --i)
{
ok(SQLSetConfigMode((UWORD)i), "SQLSetConfigMode Failed to set config mode\n");
bool_ret = SQLGetConfigMode(&config_mode);
ok(bool_ret && config_mode == i, "Failed to confirm SQLSetConfigMode.\n");
}
/* And that leaves it correctly on BOTH */
}
static void test_SQLInstallerError(void)
{
RETCODE sql_ret;
/* MSDN states that the error number should be between 1 and 8. Passing 0 is an error */
sql_ret = SQLInstallerError(0, NULL, NULL, 0, NULL);
ok(sql_ret == SQL_ERROR, "SQLInstallerError(0...) failed with %d instead of SQL_ERROR\n", sql_ret);
/* However numbers greater than 8 do not return SQL_ERROR.
* I am currenly unsure as to whether it should return SQL_NO_DATA or "the same as for error 8";
* I have never been able to generate 8 errors to test it
*/
sql_ret = SQLInstallerError(65535, NULL, NULL, 0, NULL);
ok(sql_ret == SQL_NO_DATA, "SQLInstallerError(>8...) failed with %d instead of SQL_NO_DATA\n", sql_ret);
/* Force an error to work with. This should generate ODBC_ERROR_INVALID_BUFF_LEN */
ok(!SQLGetInstalledDrivers(0, 0, 0), "Failed to force an error for testing\n");
sql_ret = SQLInstallerError(2, NULL, NULL, 0, NULL);
ok(sql_ret == SQL_NO_DATA, "Too many errors when forcing an error for testing\n");
/* Null pointers are acceptable in all obvious places */
sql_ret = SQLInstallerError(1, NULL, NULL, 0, NULL);
ok(sql_ret == SQL_SUCCESS_WITH_INFO, "SQLInstallerError(null addresses) failed with %d instead of SQL_SUCCESS_WITH_INFO\n", sql_ret);
}
static void test_SQLInstallDriverManager(void)
{
BOOL bool_ret;
RETCODE sql_ret;
DWORD error_code;
CHAR target_path[MAX_PATH];
WORD path_out;
/* NULL check */
bool_ret = SQLInstallDriverManager(NULL, 0, NULL);
sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
ok(!bool_ret, "SQLInstallDriverManager unexpectedly succeeded\n");
todo_wine
ok(sql_ret == SQL_SUCCESS_WITH_INFO && error_code == ODBC_ERROR_INVALID_BUFF_LEN,
"Expected SQLInstallDriverManager to fail with ODBC_ERROR_INVALID_BUFF_LEN\n");
/* Length smaller than MAX_PATH */
bool_ret = SQLInstallDriverManager(target_path, MAX_PATH / 2, NULL);
sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
todo_wine {
ok(!bool_ret, "SQLInstallDriverManager unexpectedly succeeded\n");
ok(sql_ret == SQL_SUCCESS_WITH_INFO && error_code == ODBC_ERROR_INVALID_BUFF_LEN,
"Expected SQLInstallDriverManager to fail with ODBC_ERROR_INVALID_BUFF_LEN\n");
}
path_out = 0xcafe;
bool_ret = SQLInstallDriverManager(target_path, MAX_PATH / 2, &path_out);
sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
todo_wine {
ok(!bool_ret, "SQLInstallDriverManager unexpectedly succeeded\n");
ok(sql_ret == SQL_SUCCESS_WITH_INFO && error_code == ODBC_ERROR_INVALID_BUFF_LEN,
"Expected SQLInstallDriverManager to fail with ODBC_ERROR_INVALID_BUFF_LEN\n");
ok(path_out == 0xcafe, "Expected path_out to not have changed\n");
}
/* Length OK */
bool_ret = SQLInstallDriverManager(target_path, MAX_PATH, NULL);
sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
ok(bool_ret, "SQLInstallDriverManager unexpectedly failed\n");
ok(sql_ret == SQL_NO_DATA, "Expected SQL_NO_DATA, got %d\n", sql_ret);
path_out = 0xcafe;
bool_ret = SQLInstallDriverManager(target_path, MAX_PATH, &path_out);
sql_ret = SQLInstallerErrorW(1, &error_code, NULL, 0, NULL);
ok(bool_ret, "SQLInstallDriverManager unexpectedly failed\n");
ok(sql_ret == SQL_NO_DATA, "Expected SQL_NO_DATA, got %d\n", sql_ret);
/* path_out should in practice be less than 0xcafe */
ok(path_out != 0xcafe, "Expected path_out to show the correct amount of bytes\n");
}
START_TEST(misc)
{
test_SQLConfigMode();
test_SQLInstallerError();
test_SQLInstallDriverManager();
}

View file

@ -0,0 +1,14 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="odbccp32_winetest" type="win32cui" installbase="bin" installname="odbccp32_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="odbccp32_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>odbccp32</library>
<library>user32</library>
<library>kernel32</library>
<library>ntdll</library>
<file>misc.c</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,15 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_misc(void);
const struct test winetest_testlist[] =
{
{ "misc", func_misc },
{ 0, 0 }
};

View file

@ -0,0 +1,381 @@
/*
* Clipboard unit tests
*
* Copyright 2006 Kevin Koltzau
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "wine/test.h"
#define InitFormatEtc(fe, cf, med) \
{\
(fe).cfFormat=cf;\
(fe).dwAspect=DVASPECT_CONTENT;\
(fe).ptd=NULL;\
(fe).tymed=med;\
(fe).lindex=-1;\
};
typedef struct DataObjectImpl {
const IDataObjectVtbl *lpVtbl;
LONG ref;
FORMATETC *fmtetc;
UINT fmtetc_cnt;
HANDLE text;
} DataObjectImpl;
typedef struct EnumFormatImpl {
const IEnumFORMATETCVtbl *lpVtbl;
LONG ref;
FORMATETC *fmtetc;
UINT fmtetc_cnt;
UINT cur;
} EnumFormatImpl;
static HRESULT EnumFormatImpl_Create(FORMATETC *fmtetc, UINT size, LPENUMFORMATETC *lplpformatetc);
static HRESULT WINAPI EnumFormatImpl_QueryInterface(IEnumFORMATETC *iface, REFIID riid, LPVOID *ppvObj)
{
EnumFormatImpl *This = (EnumFormatImpl*)iface;
if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumFORMATETC)) {
IEnumFORMATETC_AddRef(iface);
*ppvObj = (LPVOID)This;
return S_OK;
}
*ppvObj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI EnumFormatImpl_AddRef(IEnumFORMATETC *iface)
{
EnumFormatImpl *This = (EnumFormatImpl*)iface;
LONG ref = InterlockedIncrement(&This->ref);
return ref;
}
static ULONG WINAPI EnumFormatImpl_Release(IEnumFORMATETC *iface)
{
EnumFormatImpl *This = (EnumFormatImpl*)iface;
ULONG ref = InterlockedDecrement(&This->ref);
if(!ref) {
HeapFree(GetProcessHeap(), 0, This->fmtetc);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
static HRESULT WINAPI EnumFormatImpl_Next(IEnumFORMATETC *iface, ULONG celt,
FORMATETC *rgelt, ULONG *pceltFetched)
{
EnumFormatImpl *This = (EnumFormatImpl*)iface;
ULONG count = 0;
if(!rgelt)
return E_INVALIDARG;
count = min(celt, This->fmtetc_cnt-This->cur);
if(count > 0) {
memcpy(rgelt, This->fmtetc+This->cur, count*sizeof(FORMATETC));
This->cur += count;
}
if(pceltFetched)
*pceltFetched = count;
return count == celt ? S_OK : S_FALSE;
}
static HRESULT WINAPI EnumFormatImpl_Skip(IEnumFORMATETC *iface, ULONG celt)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI EnumFormatImpl_Reset(IEnumFORMATETC *iface)
{
EnumFormatImpl *This = (EnumFormatImpl*)iface;
This->cur = 0;
return S_OK;
}
static HRESULT WINAPI EnumFormatImpl_Clone(IEnumFORMATETC *iface, IEnumFORMATETC **ppenum)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static const IEnumFORMATETCVtbl VT_EnumFormatImpl = {
EnumFormatImpl_QueryInterface,
EnumFormatImpl_AddRef,
EnumFormatImpl_Release,
EnumFormatImpl_Next,
EnumFormatImpl_Skip,
EnumFormatImpl_Reset,
EnumFormatImpl_Clone
};
static HRESULT EnumFormatImpl_Create(FORMATETC *fmtetc, UINT fmtetc_cnt, IEnumFORMATETC **lplpformatetc)
{
EnumFormatImpl *ret;
ret = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumFormatImpl));
ret->lpVtbl = &VT_EnumFormatImpl;
ret->ref = 1;
ret->cur = 0;
ret->fmtetc_cnt = fmtetc_cnt;
ret->fmtetc = HeapAlloc(GetProcessHeap(), 0, fmtetc_cnt*sizeof(FORMATETC));
memcpy(ret->fmtetc, fmtetc, fmtetc_cnt*sizeof(FORMATETC));
*lplpformatetc = (LPENUMFORMATETC)ret;
return S_OK;
}
static HRESULT WINAPI DataObjectImpl_QueryInterface(IDataObject *iface, REFIID riid, LPVOID *ppvObj)
{
DataObjectImpl *This = (DataObjectImpl*)iface;
if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDataObject)) {
IDataObject_AddRef(iface);
*ppvObj = (LPVOID)This;
return S_OK;
}
*ppvObj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI DataObjectImpl_AddRef(IDataObject* iface)
{
DataObjectImpl *This = (DataObjectImpl*)iface;
ULONG ref = InterlockedIncrement(&This->ref);
return ref;
}
static ULONG WINAPI DataObjectImpl_Release(IDataObject* iface)
{
DataObjectImpl *This = (DataObjectImpl*)iface;
ULONG ref = InterlockedDecrement(&This->ref);
if(!ref) {
if(This->text) GlobalFree(This->text);
if(This->fmtetc) GlobalFree(This->fmtetc);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
static HRESULT WINAPI DataObjectImpl_GetData(IDataObject* iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
{
DataObjectImpl *This = (DataObjectImpl*)iface;
if(pformatetc->lindex != -1)
return DV_E_LINDEX;
if(!(pformatetc->tymed & TYMED_HGLOBAL))
return DV_E_TYMED;
if(This->text && pformatetc->cfFormat == CF_TEXT)
U(*pmedium).hGlobal = This->text;
else
return DV_E_FORMATETC;
pmedium->tymed = TYMED_HGLOBAL;
pmedium->pUnkForRelease = (LPUNKNOWN)iface;
IUnknown_AddRef(pmedium->pUnkForRelease);
return S_OK;
}
static HRESULT WINAPI DataObjectImpl_GetDataHere(IDataObject* iface, FORMATETC *pformatetc, STGMEDIUM *pmedium)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI DataObjectImpl_QueryGetData(IDataObject* iface, FORMATETC *pformatetc)
{
DataObjectImpl *This = (DataObjectImpl*)iface;
UINT i;
BOOL foundFormat = FALSE;
if(pformatetc->lindex != -1)
return DV_E_LINDEX;
for(i=0; i<This->fmtetc_cnt; i++) {
if(This->fmtetc[i].cfFormat == pformatetc->cfFormat) {
foundFormat = TRUE;
if(This->fmtetc[i].tymed == pformatetc->tymed)
return S_OK;
}
}
return foundFormat?DV_E_FORMATETC:DV_E_TYMED;
}
static HRESULT WINAPI DataObjectImpl_GetCanonicalFormatEtc(IDataObject* iface, FORMATETC *pformatectIn,
FORMATETC *pformatetcOut)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI DataObjectImpl_SetData(IDataObject* iface, FORMATETC *pformatetc,
STGMEDIUM *pmedium, BOOL fRelease)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI DataObjectImpl_EnumFormatEtc(IDataObject* iface, DWORD dwDirection,
IEnumFORMATETC **ppenumFormatEtc)
{
DataObjectImpl *This = (DataObjectImpl*)iface;
if(dwDirection != DATADIR_GET) {
ok(0, "unexpected direction %d\n", dwDirection);
return E_NOTIMPL;
}
return EnumFormatImpl_Create(This->fmtetc, This->fmtetc_cnt, ppenumFormatEtc);
}
static HRESULT WINAPI DataObjectImpl_DAdvise(IDataObject* iface, FORMATETC *pformatetc, DWORD advf,
IAdviseSink *pAdvSink, DWORD *pdwConnection)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI DataObjectImpl_DUnadvise(IDataObject* iface, DWORD dwConnection)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI DataObjectImpl_EnumDAdvise(IDataObject* iface, IEnumSTATDATA **ppenumAdvise)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static const IDataObjectVtbl VT_DataObjectImpl =
{
DataObjectImpl_QueryInterface,
DataObjectImpl_AddRef,
DataObjectImpl_Release,
DataObjectImpl_GetData,
DataObjectImpl_GetDataHere,
DataObjectImpl_QueryGetData,
DataObjectImpl_GetCanonicalFormatEtc,
DataObjectImpl_SetData,
DataObjectImpl_EnumFormatEtc,
DataObjectImpl_DAdvise,
DataObjectImpl_DUnadvise,
DataObjectImpl_EnumDAdvise
};
static HRESULT DataObjectImpl_CreateText(LPCSTR text, LPDATAOBJECT *lplpdataobj)
{
DataObjectImpl *obj;
obj = HeapAlloc(GetProcessHeap(), 0, sizeof(DataObjectImpl));
obj->lpVtbl = &VT_DataObjectImpl;
obj->ref = 1;
obj->text = GlobalAlloc(GMEM_MOVEABLE, strlen(text) + 1);
strcpy(GlobalLock(obj->text), text);
GlobalUnlock(obj->text);
obj->fmtetc_cnt = 1;
obj->fmtetc = HeapAlloc(GetProcessHeap(), 0, obj->fmtetc_cnt*sizeof(FORMATETC));
InitFormatEtc(obj->fmtetc[0], CF_TEXT, TYMED_HGLOBAL);
*lplpdataobj = (LPDATAOBJECT)obj;
return S_OK;
}
static void test_set_clipboard(void)
{
HRESULT hr;
ULONG ref;
LPDATAOBJECT data1, data2;
hr = DataObjectImpl_CreateText("data1", &data1);
ok(SUCCEEDED(hr), "Failed to create data1 object: 0x%08x\n", hr);
if(FAILED(hr))
return;
hr = DataObjectImpl_CreateText("data2", &data2);
ok(SUCCEEDED(hr), "Failed to create data2 object: 0x%08x\n", hr);
if(FAILED(hr))
return;
hr = OleSetClipboard(data1);
todo_wine
ok(hr == CO_E_NOTINITIALIZED, "OleSetClipboard should have failed with CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
CoInitialize(NULL);
hr = OleSetClipboard(data1);
todo_wine
ok(hr == CO_E_NOTINITIALIZED, "OleSetClipboard should have failed with CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
CoUninitialize();
hr = OleInitialize(NULL);
ok(hr == S_OK, "OleInitialize failed with error 0x%08x\n", hr);
hr = OleSetClipboard(data1);
ok(hr == S_OK, "failed to set clipboard to data1, hr = 0x%08x\n", hr);
hr = OleIsCurrentClipboard(data1);
ok(hr == S_OK, "expected current clipboard to be data1, hr = 0x%08x\n", hr);
hr = OleIsCurrentClipboard(data2);
ok(hr == S_FALSE, "did not expect current clipboard to be data2, hr = 0x%08x\n", hr);
hr = OleSetClipboard(data2);
ok(hr == S_OK, "failed to set clipboard to data2, hr = 0x%08x\n", hr);
hr = OleIsCurrentClipboard(data1);
ok(hr == S_FALSE, "did not expect current clipboard to be data1, hr = 0x%08x\n", hr);
hr = OleIsCurrentClipboard(data2);
ok(hr == S_OK, "expected current clipboard to be data2, hr = 0x%08x\n", hr);
hr = OleFlushClipboard();
ok(hr == S_OK, "failed to flush clipboard, hr = 0x%08x\n", hr);
hr = OleIsCurrentClipboard(data1);
ok(hr == S_FALSE, "did not expect current clipboard to be data1, hr = 0x%08x\n", hr);
hr = OleIsCurrentClipboard(data2);
ok(hr == S_FALSE, "did not expect current clipboard to be data2, hr = 0x%08x\n", hr);
ok(OleSetClipboard(NULL) == S_OK, "failed to clear clipboard, hr = 0x%08x\n", hr);
ref = IDataObject_Release(data1);
ok(ref == 0, "expected data1 ref=0, got %d\n", ref);
ref = IDataObject_Release(data2);
ok(ref == 0, "expected data2 ref=0, got %d\n", ref);
OleUninitialize();
}
START_TEST(clipboard)
{
test_set_clipboard();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,147 @@
/*
* Drag and Drop Tests
*
* Copyright 2007 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define _WIN32_DCOM
#define COBJMACROS
#define CONST_VTABLE
#include <stdarg.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "wine/test.h"
/* functions that are not present on all versions of Windows */
HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
static int droptarget_addref_called;
static int droptarget_release_called;
/* helper macros to make tests a bit leaner */
#define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
static HRESULT WINAPI DropTarget_QueryInterface(IDropTarget* iface, REFIID riid,
void** ppvObject)
{
trace("DropTarget_QueryInterface\n");
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IDropTarget))
{
IUnknown_AddRef(iface);
*ppvObject = iface;
return S_OK;
}
*ppvObject = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI DropTarget_AddRef(IDropTarget* iface)
{
droptarget_addref_called++;
return 2;
}
static ULONG WINAPI DropTarget_Release(IDropTarget* iface)
{
droptarget_release_called++;
return 1;
}
static HRESULT WINAPI DropTarget_DragEnter(IDropTarget* iface,
IDataObject* pDataObj,
DWORD grfKeyState, POINTL pt,
DWORD* pdwEffect)
{
return E_NOTIMPL;
}
static HRESULT WINAPI DropTarget_DragOver(IDropTarget* iface,
DWORD grfKeyState,
POINTL pt,
DWORD* pdwEffect)
{
return E_NOTIMPL;
}
static HRESULT WINAPI DropTarget_DragLeave(IDropTarget* iface)
{
return E_NOTIMPL;
}
static HRESULT WINAPI DropTarget_Drop(IDropTarget* iface,
IDataObject* pDataObj, DWORD grfKeyState,
POINTL pt, DWORD* pdwEffect)
{
return E_NOTIMPL;
}
static const IDropTargetVtbl DropTarget_VTbl =
{
DropTarget_QueryInterface,
DropTarget_AddRef,
DropTarget_Release,
DropTarget_DragEnter,
DropTarget_DragOver,
DropTarget_DragLeave,
DropTarget_Drop
};
static IDropTarget DropTarget = { &DropTarget_VTbl };
START_TEST(dragdrop)
{
HRESULT hr;
hr = RegisterDragDrop(GetDesktopWindow(), &DropTarget);
ok(hr == E_OUTOFMEMORY, "RegisterDragDrop without OLE initialized should have returned E_OUTOFMEMORY instead of 0x%08x\n", hr);
OleInitialize(NULL);
hr = RegisterDragDrop(GetDesktopWindow(), NULL);
ok(hr == E_INVALIDARG, "RegisterDragDrop with NULL IDropTarget * should return E_INVALIDARG instead of 0x%08x\n", hr);
hr = RegisterDragDrop(NULL, &DropTarget);
ok(hr == DRAGDROP_E_INVALIDHWND, "RegisterDragDrop with NULL hwnd should return DRAGDROP_E_INVALIDHWND instead of 0x%08x\n", hr);
hr = RegisterDragDrop((HWND)0xdeadbeef, &DropTarget);
ok(hr == DRAGDROP_E_INVALIDHWND, "RegisterDragDrop with garbage hwnd should return DRAGDROP_E_INVALIDHWND instead of 0x%08x\n", hr);
ok(droptarget_addref_called == 0, "DropTarget_AddRef shouldn't have been called\n");
hr = RegisterDragDrop(GetDesktopWindow(), &DropTarget);
ok_ole_success(hr, "RegisterDragDrop");
ok(droptarget_addref_called == 1, "DropTarget_AddRef should have been called once, not %d times\n", droptarget_addref_called);
hr = RegisterDragDrop(GetDesktopWindow(), &DropTarget);
ok(hr == DRAGDROP_E_ALREADYREGISTERED, "RegisterDragDrop with already registered hwnd should return DRAGDROP_E_ALREADYREGISTERED instead of 0x%08x\n", hr);
ok(droptarget_release_called == 0, "DropTarget_Release shouldn't have been called\n");
OleUninitialize();
ok(droptarget_release_called == 0, "DropTarget_Release shouldn't have been called\n");
hr = RevokeDragDrop(GetDesktopWindow());
ok_ole_success(hr, "RevokeDragDrop");
ok(droptarget_release_called == 1, "DropTarget_Release should have been called once, not %d times\n", droptarget_release_called);
hr = RevokeDragDrop(NULL);
ok(hr == DRAGDROP_E_INVALIDHWND, "RevokeDragDrop with NULL hwnd should return DRAGDROP_E_INVALIDHWND instead of 0x%08x\n", hr);
}

View file

@ -0,0 +1,111 @@
/*
* Error Info Tests
*
* Copyright 2007 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#define CONST_VTABLE
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "wine/test.h"
#define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
static const CLSID CLSID_WineTest =
{ /* 9474ba1a-258b-490b-bc13-516e9239ace0 */
0x9474ba1a,
0x258b,
0x490b,
{0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe0}
};
static void test_error_info(void)
{
HRESULT hr;
ICreateErrorInfo *pCreateErrorInfo;
IErrorInfo *pErrorInfo;
static WCHAR wszDescription[] = {'F','a','i','l','e','d',' ','S','p','r','o','c','k','e','t',0};
static WCHAR wszHelpFile[] = {'s','p','r','o','c','k','e','t','.','h','l','p',0};
static WCHAR wszSource[] = {'s','p','r','o','c','k','e','t',0};
hr = CreateErrorInfo(&pCreateErrorInfo);
ok_ole_success(hr, "CreateErrorInfo");
hr = ICreateErrorInfo_SetDescription(pCreateErrorInfo, NULL);
ok_ole_success(hr, "ICreateErrorInfo_SetDescription");
hr = ICreateErrorInfo_SetDescription(pCreateErrorInfo, wszDescription);
ok_ole_success(hr, "ICreateErrorInfo_SetDescription");
hr = ICreateErrorInfo_SetGUID(pCreateErrorInfo, &CLSID_WineTest);
ok_ole_success(hr, "ICreateErrorInfo_SetGUID");
hr = ICreateErrorInfo_SetHelpContext(pCreateErrorInfo, 0xdeadbeef);
ok_ole_success(hr, "ICreateErrorInfo_SetHelpContext");
hr = ICreateErrorInfo_SetHelpFile(pCreateErrorInfo, NULL);
ok_ole_success(hr, "ICreateErrorInfo_SetHelpFile");
hr = ICreateErrorInfo_SetHelpFile(pCreateErrorInfo, wszHelpFile);
ok_ole_success(hr, "ICreateErrorInfo_SetHelpFile");
hr = ICreateErrorInfo_SetSource(pCreateErrorInfo, NULL);
ok_ole_success(hr, "ICreateErrorInfo_SetSource");
hr = ICreateErrorInfo_SetSource(pCreateErrorInfo, wszSource);
ok_ole_success(hr, "ICreateErrorInfo_SetSource");
hr = ICreateErrorInfo_QueryInterface(pCreateErrorInfo, &IID_IErrorInfo, (void **)&pErrorInfo);
ok_ole_success(hr, "ICreateErrorInfo_QueryInterface");
ICreateErrorInfo_Release(pCreateErrorInfo);
hr = SetErrorInfo(0, pErrorInfo);
ok_ole_success(hr, "SetErrorInfo");
IErrorInfo_Release(pErrorInfo);
pErrorInfo = NULL;
hr = GetErrorInfo(0, &pErrorInfo);
ok_ole_success(hr, "GetErrorInfo");
IErrorInfo_Release(pErrorInfo);
hr = GetErrorInfo(0, &pErrorInfo);
ok(hr == S_FALSE, "GetErrorInfo should have returned S_FALSE instead of 0x%08x\n", hr);
ok(!pErrorInfo, "pErrorInfo should be set to NULL\n");
hr = SetErrorInfo(0, NULL);
ok_ole_success(hr, "SetErrorInfo");
hr = GetErrorInfo(0xdeadbeef, &pErrorInfo);
ok(hr == E_INVALIDARG, "GetErrorInfo should have returned E_INVALIDARG instead of 0x%08x\n", hr);
hr = SetErrorInfo(0xdeadbeef, NULL);
ok(hr == E_INVALIDARG, "SetErrorInfo should have returned E_INVALIDARG instead of 0x%08x\n", hr);
}
START_TEST(errorinfo)
{
test_error_info();
}

View file

@ -0,0 +1,318 @@
/*
* Stream on HGLOBAL Tests
*
* Copyright 2006 Robert Shearman (for CodeWeavers)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "wine/test.h"
#define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
static char const * const *expected_method_list;
#define CHECK_EXPECTED_METHOD(method_name) \
do { \
ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \
if (*expected_method_list) \
{ \
ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \
*expected_method_list, method_name); \
expected_method_list++; \
} \
} while(0)
static void test_streamonhglobal(IStream *pStream)
{
const char data[] = "Test String";
ULARGE_INTEGER ull;
LARGE_INTEGER ll;
char buffer[128];
ULONG read;
STATSTG statstg;
HRESULT hr;
ull.QuadPart = sizeof(data);
hr = IStream_SetSize(pStream, ull);
ok_ole_success(hr, "IStream_SetSize");
hr = IStream_Write(pStream, data, sizeof(data), NULL);
ok_ole_success(hr, "IStream_Write");
ll.QuadPart = 0;
hr = IStream_Seek(pStream, ll, STREAM_SEEK_SET, NULL);
ok_ole_success(hr, "IStream_Seek");
/* should return S_OK, not S_FALSE */
hr = IStream_Read(pStream, buffer, sizeof(buffer), &read);
ok_ole_success(hr, "IStream_Read");
ok(read == sizeof(data), "IStream_Read returned read %d\n", read);
/* ignores HighPart */
ull.u.HighPart = -1;
ull.u.LowPart = 0;
hr = IStream_SetSize(pStream, ull);
ok_ole_success(hr, "IStream_SetSize");
hr = IStream_Commit(pStream, STGC_DEFAULT);
ok_ole_success(hr, "IStream_Commit");
hr = IStream_Revert(pStream);
ok_ole_success(hr, "IStream_Revert");
hr = IStream_LockRegion(pStream, ull, ull, LOCK_WRITE);
ok(hr == STG_E_INVALIDFUNCTION, "IStream_LockRegion should have returned STG_E_INVALIDFUNCTION instead of 0x%08x\n", hr);
hr = IStream_Stat(pStream, &statstg, STATFLAG_DEFAULT);
ok_ole_success(hr, "IStream_Stat");
ok(statstg.type == STGTY_STREAM, "statstg.type should have been STGTY_STREAM instead of %d\n", statstg.type);
/* test OOM condition */
ull.u.HighPart = -1;
ull.u.LowPart = -1;
hr = IStream_SetSize(pStream, ull);
ok(hr == E_OUTOFMEMORY, "IStream_SetSize with large size should have returned E_OUTOFMEMORY instead of 0x%08x\n", hr);
}
static HRESULT WINAPI TestStream_QueryInterface(IStream *iface, REFIID riid, void **ppv)
{
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_ISequentialStream) ||
IsEqualIID(riid, &IID_IStream))
{
*ppv = iface;
IUnknown_AddRef(iface);
return S_OK;
}
*ppv = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI TestStream_AddRef(IStream *iface)
{
return 2;
}
static ULONG WINAPI TestStream_Release(IStream *iface)
{
return 1;
}
static HRESULT WINAPI TestStream_Read(IStream *iface, void *pv, ULONG cb, ULONG *pcbRead)
{
CHECK_EXPECTED_METHOD("TestStream_Read");
return E_NOTIMPL;
}
static HRESULT WINAPI TestStream_Write(IStream *iface, const void *pv, ULONG cb, ULONG *pcbWritten)
{
CHECK_EXPECTED_METHOD("TestStream_Write");
*pcbWritten = 5;
return S_OK;
}
static HRESULT WINAPI TestStream_Seek(IStream *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
{
CHECK_EXPECTED_METHOD("TestStream_Seek");
return E_NOTIMPL;
}
static HRESULT WINAPI TestStream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
{
CHECK_EXPECTED_METHOD("TestStream_SetSize");
return E_NOTIMPL;
}
static HRESULT WINAPI TestStream_CopyTo(IStream *iface, IStream *pStream, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
{
CHECK_EXPECTED_METHOD("TestStream_CopyTo");
return E_NOTIMPL;
}
static HRESULT WINAPI TestStream_Commit(IStream *iface, DWORD grfCommitFlags)
{
CHECK_EXPECTED_METHOD("TestStream_Commit");
return E_NOTIMPL;
}
static HRESULT WINAPI TestStream_Revert(IStream *iface)
{
CHECK_EXPECTED_METHOD("TestStream_Revert");
return E_NOTIMPL;
}
static HRESULT WINAPI TestStream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
{
CHECK_EXPECTED_METHOD("TestStream_LockRegion");
return E_NOTIMPL;
}
static HRESULT WINAPI TestStream_UnlockRegion(IStream *iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
{
CHECK_EXPECTED_METHOD("TestStream_UnlockRegion");
return E_NOTIMPL;
}
static HRESULT WINAPI TestStream_Stat(IStream *iface, STATSTG *pstatstg, DWORD grfStatFlag)
{
CHECK_EXPECTED_METHOD("TestStream_Stat");
return E_NOTIMPL;
}
static HRESULT WINAPI TestStream_Clone(IStream *iface, IStream **pStream)
{
CHECK_EXPECTED_METHOD("TestStream_Clone");
return E_NOTIMPL;
}
static /*const*/ IStreamVtbl StreamVtbl =
{
TestStream_QueryInterface,
TestStream_AddRef,
TestStream_Release,
TestStream_Read,
TestStream_Write,
TestStream_Seek,
TestStream_SetSize,
TestStream_CopyTo,
TestStream_Commit,
TestStream_Revert,
TestStream_LockRegion,
TestStream_UnlockRegion,
TestStream_Stat,
TestStream_Clone
};
static IStream Test_Stream = { &StreamVtbl };
static void test_copyto(void)
{
IStream *pStream, *pStream2;
HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
static const char szHello[] = "Hello";
ULARGE_INTEGER cb;
static const char *methods_copyto[] =
{
"TestStream_Write",
NULL
};
ULONG written;
ULARGE_INTEGER ullRead;
ULARGE_INTEGER ullWritten;
ULARGE_INTEGER libNewPosition;
static const LARGE_INTEGER llZero;
char buffer[15];
expected_method_list = methods_copyto;
hr = IStream_Write(pStream, szHello, sizeof(szHello), &written);
ok_ole_success(hr, "IStream_Write");
ok(written == sizeof(szHello), "only %d bytes written\n", written);
hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
ok_ole_success(hr, "IStream_Seek");
cb.QuadPart = sizeof(szHello);
hr = IStream_CopyTo(pStream, &Test_Stream, cb, &ullRead, &ullWritten);
ok(ullWritten.QuadPart == 5, "ullWritten was %d instead\n", (ULONG)ullWritten.QuadPart);
ok(ullRead.QuadPart == sizeof(szHello), "only %d bytes read\n", (ULONG)ullRead.QuadPart);
ok_ole_success(hr, "IStream_CopyTo");
ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
hr = IStream_Clone(pStream, &pStream2);
ok_ole_success(hr, "IStream_Clone");
hr = IStream_Seek(pStream2, llZero, STREAM_SEEK_CUR, &libNewPosition);
ok_ole_success(hr, "IStream_Seek");
ok(libNewPosition.QuadPart == sizeof(szHello), "libNewPosition wasn't set correctly for the cloned stream\n");
hr = IStream_Seek(pStream2, llZero, STREAM_SEEK_SET, NULL);
ok_ole_success(hr, "IStream_Seek");
hr = IStream_Read(pStream2, buffer, sizeof(buffer), NULL);
ok_ole_success(hr, "IStream_Read");
ok(!strcmp(buffer, szHello), "read data \"%s\" didn't match originally written data\n", buffer);
IStream_Release(pStream2);
IStream_Release(pStream);
}
static void test_freed_hglobal(void)
{
HRESULT hr;
IStream *pStream;
HGLOBAL hglobal;
char *p;
char buffer[10];
ULARGE_INTEGER ull;
ULONG read, written;
hglobal = GlobalAlloc(GMEM_DDESHARE|GMEM_NODISCARD|GMEM_MOVEABLE, strlen("Rob") + 1);
ok(hglobal != NULL, "GlobalAlloc failed with error %d\n", GetLastError());
p = GlobalLock(hglobal);
strcpy(p, "Rob");
GlobalUnlock(hglobal);
hr = CreateStreamOnHGlobal(hglobal, FALSE, &pStream);
ok_ole_success(hr, "CreateStreamOnHGlobal");
hr = IStream_Read(pStream, buffer, sizeof(buffer), &read);
ok_ole_success(hr, "IStream_Read");
ok(!strcmp(buffer, "Rob"), "buffer data %s differs\n", buffer);
ok(read == strlen("Rob") + 1, "read should be 4 instead of %d\n", read);
GlobalFree(hglobal);
memset(buffer, 0, sizeof(buffer));
read = -1;
hr = IStream_Read(pStream, buffer, sizeof(buffer), &read);
ok_ole_success(hr, "IStream_Read");
ok(buffer[0] == 0, "buffer data should be untouched\n");
ok(read == 0, "read should be 0 instead of %d\n", read);
ull.QuadPart = sizeof(buffer);
hr = IStream_SetSize(pStream, ull);
ok(hr == E_OUTOFMEMORY, "IStream_SetSize with invalid HGLOBAL should return E_OUTOFMEMORY instead of 0x%08x\n", hr);
hr = IStream_Write(pStream, buffer, sizeof(buffer), &written);
ok(hr == E_OUTOFMEMORY, "IStream_Write with invalid HGLOBAL should return E_OUTOFMEMORY instead of 0x%08x\n", hr);
ok(written == 0, "written should be 0 instead of %d\n", written);
IStream_Release(pStream);
}
START_TEST(hglobalstream)
{
HRESULT hr;
IStream *pStream;
hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
ok_ole_success(hr, "CreateStreamOnHGlobal");
test_streamonhglobal(pStream);
IStream_Release(pStream);
test_copyto();
test_freed_hglobal();
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,29 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="ole32_winetest" type="win32cui" installbase="bin" installname="ole32_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="ole32_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>oleaut32</library>
<library>ole32</library>
<library>user32</library>
<library>gdi32</library>
<library>advapi32</library>
<library>kernel32</library>
<library>uuid</library>
<library>ntdll</library>
<file>clipboard.c</file>
<file>compobj.c</file>
<file>dragdrop.c</file>
<file>errorinfo.c</file>
<file>hglobalstream.c</file>
<file>marshal.c</file>
<file>moniker.c</file>
<file>ole2.c</file>
<file>propvariant.c</file>
<file>stg_prop.c</file>
<file>storage32.c</file>
<file>usrmarshal.c</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,242 @@
/*
* PropVariant Tests
*
* Copyright 2004 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "windows.h"
#include "wine/test.h"
/* invalid in all versions */
#define PROP_INV 255
/* valid in v0 and above (NT4+) */
#define PROP_V0 0
/* valid in v1 and above (Win2k+) */
#define PROP_V1 1
/* valid in v1a and above (WinXP+) */
#define PROP_V1A 2
struct valid_mapping
{
BYTE simple;
BYTE with_array;
BYTE with_vector;
BYTE byref;
} valid_types[] =
{
{ PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_EMPTY */
{ PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_NULL */
{ PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_I2 */
{ PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_I4 */
{ PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_R4 */
{ PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_R8 */
{ PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_CY */
{ PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_DATE */
{ PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_BSTR */
{ PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 }, /* VT_DISPATCH */
{ PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_ERROR */
{ PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_BOOL */
{ PROP_V1 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_VARIANT */
{ PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 }, /* VT_UNKNOWN */
{ PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 }, /* VT_DECIMAL */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 15 */
{ PROP_V1 , PROP_V1 , PROP_V1 , PROP_V1 }, /* VT_I1 */
{ PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_UI1 */
{ PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_UI2 */
{ PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 }, /* VT_UI4 */
{ PROP_V0 , PROP_V1A, PROP_V0 , PROP_V1A }, /* VT_I8 */
{ PROP_V0 , PROP_V1A, PROP_V0 , PROP_V1A }, /* VT_UI8 */
{ PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 }, /* VT_INT */
{ PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 }, /* VT_UINT */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_VOID */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_HRESULT */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_PTR */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_SAFEARRAY */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_CARRAY */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_USERDEFINED */
{ PROP_V0 , PROP_INV, PROP_V0 , PROP_INV }, /* VT_LPSTR */
{ PROP_V0 , PROP_INV, PROP_V0 , PROP_INV }, /* VT_LPWSTR */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 32 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 33 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 34 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 35 */
{ PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 }, /* VT_RECORD */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_INT_PTR */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_UINT_PTR */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 39 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 40 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 41 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 42 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 43 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 44 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 45 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 46 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 47 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 48 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 49 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 50 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 51 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 52 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 53 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 54 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 55 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 56 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 57 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 58 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 59 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 60 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 61 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 62 */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 63 */
{ PROP_V0 , PROP_INV, PROP_V0 , PROP_INV }, /* VT_FILETIME */
{ PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_BLOB */
{ PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_STREAM */
{ PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_STORAGE */
{ PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_STREAMED_OBJECT */
{ PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_STORED_OBJECT */
{ PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_BLOB_OBJECT */
{ PROP_V0 , PROP_INV, PROP_V0 , PROP_INV } /* VT_CF */
};
static const char* wine_vtypes[VT_CLSID+1] =
{
"VT_EMPTY","VT_NULL","VT_I2","VT_I4","VT_R4","VT_R8","VT_CY","VT_DATE",
"VT_BSTR","VT_DISPATCH","VT_ERROR","VT_BOOL","VT_VARIANT","VT_UNKNOWN",
"VT_DECIMAL","15","VT_I1","VT_UI1","VT_UI2","VT_UI4","VT_I8","VT_UI8",
"VT_INT","VT_UINT","VT_VOID","VT_HRESULT","VT_PTR","VT_SAFEARRAY",
"VT_CARRAY","VT_USERDEFINED","VT_LPSTR","VT_LPWSTR","32","33","34","35",
"VT_RECORD","VT_INT_PTR","VT_UINT_PTR","39","40","41","42","43","44","45",
"46","47","48","49","50","51","52","53","54","55","56","57","58","59","60",
"61","62","63","VT_FILETIME","VT_BLOB","VT_STREAM","VT_STORAGE",
"VT_STREAMED_OBJECT","VT_STORED_OBJECT","VT_BLOB_OBJECT","VT_CF","VT_CLSID"
};
static void test_validtypes(void)
{
PROPVARIANT propvar;
HRESULT hr;
unsigned int i;
BYTE version;
memset(&propvar, 0, sizeof(propvar));
/* detect version */
propvar.vt = VT_I2 | VT_ARRAY;
hr = PropVariantClear(&propvar);
if (hr == S_OK)
{
propvar.vt = VT_I8 | VT_ARRAY;
hr = PropVariantClear(&propvar);
if (hr == S_OK)
{
version = PROP_V1A;
trace("detected prop variant v1a\n");
}
else
{
version = PROP_V1;
trace("detected prop variant v1\n");
}
}
else
{
version = PROP_V0;
trace("detected prop variant v0\n");
}
for (i = 0; i < sizeof(valid_types)/sizeof(valid_types[0]); i++)
{
BOOL expected_result;
propvar.vt = i;
hr = PropVariantClear(&propvar);
expected_result = (valid_types[i].simple <= version ? TRUE : FALSE);
ok(expected_result == !(hr == STG_E_INVALIDPARAMETER),
"PropVariantClear(%s) should have returned 0x%08x, but returned 0x%08x\n",
wine_vtypes[i],
expected_result ? S_OK : STG_E_INVALIDPARAMETER, hr);
propvar.vt = i | VT_ARRAY;
hr = PropVariantClear(&propvar);
expected_result = (valid_types[i].with_array <= version ? TRUE : FALSE);
ok(expected_result == !(hr == STG_E_INVALIDPARAMETER),
"PropVariantClear(%s|VT_ARRAY) should have returned 0x%08x, but returned 0x%08x\n",
wine_vtypes[i],
expected_result ? S_OK : STG_E_INVALIDPARAMETER, hr);
propvar.vt = i | VT_VECTOR;
hr = PropVariantClear(&propvar);
expected_result = (valid_types[i].with_vector <= version ? TRUE : FALSE);
ok(expected_result == !(hr == STG_E_INVALIDPARAMETER),
"PropVariantClear(%s|VT_VECTOR) should have returned 0x%08x, but returned 0x%08x\n",
wine_vtypes[i],
expected_result ? S_OK : STG_E_INVALIDPARAMETER, hr);
propvar.vt = i | VT_BYREF;
hr = PropVariantClear(&propvar);
expected_result = (valid_types[i].byref <= version ? TRUE : FALSE);
ok(expected_result == !(hr == STG_E_INVALIDPARAMETER),
"PropVariantClear(%s|VT_BYREF) should have returned 0x%08x, but returned 0x%08x\n",
wine_vtypes[i],
expected_result ? S_OK : STG_E_INVALIDPARAMETER, hr);
}
}
static void test_copy(void)
{
static char szTestString[] = "Test String";
static WCHAR wszTestString[] = {'T','e','s','t',' ','S','t','r','i','n','g',0};
PROPVARIANT propvarSrc;
PROPVARIANT propvarDst;
HRESULT hr;
propvarSrc.vt = VT_BSTR;
U(propvarSrc).bstrVal = SysAllocString(wszTestString);
hr = PropVariantCopy(&propvarDst, &propvarSrc);
ok(hr == S_OK, "PropVariantCopy(...VT_BSTR...) failed\n");
ok(!lstrcmpW(U(propvarSrc).bstrVal, U(propvarDst).bstrVal), "BSTR not copied properly\n");
hr = PropVariantClear(&propvarSrc);
ok(hr == S_OK, "PropVariantClear(...VT_BSTR...) failed\n");
hr = PropVariantClear(&propvarDst);
ok(hr == S_OK, "PropVariantClear(...VT_BSTR...) failed\n");
propvarSrc.vt = VT_LPWSTR;
U(propvarSrc).pwszVal = wszTestString;
hr = PropVariantCopy(&propvarDst, &propvarSrc);
ok(hr == S_OK, "PropVariantCopy(...VT_LPWSTR...) failed\n");
ok(!lstrcmpW(U(propvarSrc).pwszVal, U(propvarDst).pwszVal), "Wide string not copied properly\n");
hr = PropVariantClear(&propvarDst);
ok(hr == S_OK, "PropVariantClear(...VT_LPWSTR...) failed\n");
memset(&propvarSrc, 0, sizeof(propvarSrc));
propvarSrc.vt = VT_LPSTR;
U(propvarSrc).pszVal = szTestString;
hr = PropVariantCopy(&propvarDst, &propvarSrc);
ok(hr == S_OK, "PropVariantCopy(...VT_LPSTR...) failed\n");
ok(!strcmp(U(propvarSrc).pszVal, U(propvarDst).pszVal), "String not copied properly\n");
hr = PropVariantClear(&propvarDst);
ok(hr == S_OK, "PropVariantClear(...VT_LPSTR...) failed\n");
memset(&propvarSrc, 0, sizeof(propvarSrc));
}
START_TEST(propvariant)
{
test_validtypes();
test_copy();
}

View file

@ -0,0 +1,529 @@
/* IPropertyStorage unit tests
* Copyright 2005 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
#define COBJMACROS
#include "objbase.h"
#include "wine/test.h"
#ifndef PID_BEHAVIOR
#define PID_BEHAVIOR 0x80000003
#endif
static HRESULT (WINAPI *pFmtIdToPropStgName)(const FMTID *, LPOLESTR);
static HRESULT (WINAPI *pPropStgNameToFmtId)(const LPOLESTR, FMTID *);
static HRESULT (WINAPI *pStgCreatePropSetStg)(IStorage *, DWORD, IPropertySetStorage **);
static void init_function_pointers(void)
{
HMODULE hmod = GetModuleHandleA("ole32.dll");
pFmtIdToPropStgName = (void*)GetProcAddress(hmod, "FmtIdToPropStgName");
pPropStgNameToFmtId = (void*)GetProcAddress(hmod, "PropStgNameToFmtId");
pStgCreatePropSetStg = (void*)GetProcAddress(hmod, "StgCreatePropSetStg");
}
/* FIXME: this creates an ANSI storage, try to find conditions under which
* Unicode translation fails
*/
static void testProps(void)
{
static const WCHAR szDot[] = { '.',0 };
static const WCHAR szPrefix[] = { 's','t','g',0 };
static WCHAR propName[] = { 'p','r','o','p',0 };
static char val[] = "l33t auth0r";
WCHAR filename[MAX_PATH];
HRESULT hr;
IStorage *storage = NULL;
IPropertySetStorage *propSetStorage = NULL;
IPropertyStorage *propertyStorage = NULL;
PROPSPEC spec;
PROPVARIANT var;
CLIPDATA clipdata;
unsigned char clipcontent[] = "foobar";
if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
return;
DeleteFileW(filename);
hr = StgCreateDocfile(filename,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, &storage);
ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
if(!pStgCreatePropSetStg)
{
IStorage_Release(storage);
DeleteFileW(filename);
return;
}
hr = pStgCreatePropSetStg(storage, 0, &propSetStorage);
ok(hr == S_OK, "StgCreatePropSetStg failed: 0x%08x\n", hr);
hr = IPropertySetStorage_Create(propSetStorage,
&FMTID_SummaryInformation, NULL, PROPSETFLAG_ANSI,
STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
&propertyStorage);
ok(hr == S_OK, "IPropertySetStorage_Create failed: 0x%08x\n", hr);
hr = IPropertyStorage_WriteMultiple(propertyStorage, 0, NULL, NULL, 0);
ok(hr == S_OK, "WriteMultiple with 0 args failed: 0x%08x\n", hr);
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, NULL, NULL, 0);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got 0x%08x\n", hr);
/* test setting one that I can't set */
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PID_DICTIONARY;
var.vt = VT_I4;
U(var).lVal = 1;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var, 0);
ok(hr == STG_E_INVALIDPARAMETER,
"Expected STG_E_INVALIDPARAMETER, got 0x%08x\n", hr);
/* test setting one by name with an invalid propidNameFirst */
spec.ulKind = PRSPEC_LPWSTR;
U(spec).lpwstr = (LPOLESTR)propName;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var,
PID_DICTIONARY);
ok(hr == STG_E_INVALIDPARAMETER,
"Expected STG_E_INVALIDPARAMETER, got 0x%08x\n", hr);
/* test setting behavior (case-sensitive) */
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PID_BEHAVIOR;
U(var).lVal = 1;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var, 0);
ok(hr == STG_E_INVALIDPARAMETER,
"Expected STG_E_INVALIDPARAMETER, got 0x%08x\n", hr);
/* set one by value.. */
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PID_FIRST_USABLE;
U(var).lVal = 1;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var, 0);
ok(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
/* set one by name */
spec.ulKind = PRSPEC_LPWSTR;
U(spec).lpwstr = (LPOLESTR)propName;
U(var).lVal = 2;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var,
PID_FIRST_USABLE);
ok(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
/* set a string value */
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PIDSI_AUTHOR;
var.vt = VT_LPSTR;
U(var).pszVal = val;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var, 0);
ok(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
/* set a clipboard value */
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PIDSI_THUMBNAIL;
var.vt = VT_CF;
clipdata.cbSize = sizeof clipcontent + sizeof (ULONG);
clipdata.ulClipFmt = CF_ENHMETAFILE;
clipdata.pClipData = clipcontent;
U(var).pclipdata = &clipdata;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var, 0);
ok(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
/* check reading */
hr = IPropertyStorage_ReadMultiple(propertyStorage, 0, NULL, NULL);
ok(hr == S_FALSE, "ReadMultiple with 0 args failed: 0x%08x\n", hr);
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, NULL, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got 0x%08x\n", hr);
/* read by propid */
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PID_FIRST_USABLE;
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_OK, "ReadMultiple failed: 0x%08x\n", hr);
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);
/* read by name */
spec.ulKind = PRSPEC_LPWSTR;
U(spec).lpwstr = (LPOLESTR)propName;
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_OK, "ReadMultiple failed: 0x%08x\n", hr);
ok(var.vt == VT_I4 && U(var).lVal == 2,
"Didn't get expected type or value for property (got type %d, value %ld)\n",
var.vt, U(var).lVal);
/* read string value */
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PIDSI_AUTHOR;
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_OK, "ReadMultiple failed: 0x%08x\n", hr);
ok(var.vt == VT_LPSTR && !lstrcmpA(U(var).pszVal, val),
"Didn't get expected type or value for property (got type %d, value %s)\n",
var.vt, U(var).pszVal);
/* read clipboard format */
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PIDSI_THUMBNAIL;
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(SUCCEEDED(hr), "ReadMultiple failed: 0x%08x\n", hr);
ok(var.vt == VT_CF, "variant type wrong\n");
ok(U(var).pclipdata->ulClipFmt == CF_ENHMETAFILE,
"clipboard type wrong\n");
ok(U(var).pclipdata->cbSize == sizeof clipcontent + sizeof (ULONG),
"clipboard size wrong\n");
ok(!memcmp(U(var).pclipdata->pClipData, clipcontent, sizeof clipcontent),
"clipboard contents wrong\n");
ok(S_OK == PropVariantClear(&var), "failed to clear variant\n");
/* check deleting */
hr = IPropertyStorage_DeleteMultiple(propertyStorage, 0, NULL);
ok(hr == S_OK, "DeleteMultiple with 0 args failed: 0x%08x\n", hr);
hr = IPropertyStorage_DeleteMultiple(propertyStorage, 1, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got 0x%08x\n", hr);
/* contrary to what the docs say, you can't delete the dictionary */
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PID_DICTIONARY;
hr = IPropertyStorage_DeleteMultiple(propertyStorage, 1, &spec);
ok(hr == STG_E_INVALIDPARAMETER,
"Expected STG_E_INVALIDPARAMETER, got 0x%08x\n", hr);
/* now delete the first value.. */
U(spec).propid = PID_FIRST_USABLE;
hr = IPropertyStorage_DeleteMultiple(propertyStorage, 1, &spec);
ok(hr == S_OK, "DeleteMultiple failed: 0x%08x\n", hr);
/* and check that it's no longer readable */
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_FALSE, "Expected S_FALSE, got 0x%08x\n", hr);
hr = IPropertyStorage_Commit(propertyStorage, STGC_DEFAULT);
ok(hr == S_OK, "Commit failed: 0x%08x\n", hr);
/* check reverting */
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PID_FIRST_USABLE;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var, 0);
ok(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
hr = IPropertyStorage_Revert(propertyStorage);
ok(hr == S_OK, "Revert failed: 0x%08x\n", hr);
/* now check that it's still not there */
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_FALSE, "Expected S_FALSE, got 0x%08x\n", hr);
/* set an integer value again */
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PID_FIRST_USABLE;
var.vt = VT_I4;
U(var).lVal = 1;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var, 0);
ok(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
/* commit it */
hr = IPropertyStorage_Commit(propertyStorage, STGC_DEFAULT);
ok(hr == S_OK, "Commit failed: 0x%08x\n", hr);
/* set it to a string value */
var.vt = VT_LPSTR;
U(var).pszVal = (LPSTR)val;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var, 0);
ok(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
/* revert it */
hr = IPropertyStorage_Revert(propertyStorage);
ok(hr == S_OK, "Revert failed: 0x%08x\n", hr);
/* Oddly enough, there's no guarantee that a successful revert actually
* implies the value wasn't saved. Maybe transactional mode needs to be
* used for that?
*/
IPropertyStorage_Release(propertyStorage);
propertyStorage = NULL;
IPropertySetStorage_Release(propSetStorage);
propSetStorage = NULL;
IStorage_Release(storage);
storage = NULL;
/* now open it again */
hr = StgOpenStorage(filename, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
NULL, 0, &storage);
ok(hr == S_OK, "StgOpenStorage failed: 0x%08x\n", hr);
hr = pStgCreatePropSetStg(storage, 0, &propSetStorage);
ok(hr == S_OK, "StgCreatePropSetStg failed: 0x%08x\n", hr);
hr = IPropertySetStorage_Open(propSetStorage, &FMTID_SummaryInformation,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE, &propertyStorage);
ok(hr == S_OK, "IPropertySetStorage_Open failed: 0x%08x\n", hr);
/* check properties again */
spec.ulKind = PRSPEC_LPWSTR;
U(spec).lpwstr = (LPOLESTR)propName;
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_OK, "ReadMultiple failed: 0x%08x\n", hr);
ok(var.vt == VT_I4 && U(var).lVal == 2,
"Didn't get expected type or value for property (got type %d, value %ld)\n",
var.vt, U(var).lVal);
spec.ulKind = PRSPEC_PROPID;
U(spec).propid = PIDSI_AUTHOR;
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_OK, "ReadMultiple failed: 0x%08x\n", hr);
ok(var.vt == VT_LPSTR && !lstrcmpA(U(var).pszVal, val),
"Didn't get expected type or value for property (got type %d, value %s)\n",
var.vt, U(var).pszVal);
IPropertyStorage_Release(propertyStorage);
IPropertySetStorage_Release(propSetStorage);
IStorage_Release(storage);
DeleteFileW(filename);
}
static void testCodepage(void)
{
static const WCHAR szDot[] = { '.',0 };
static const WCHAR szPrefix[] = { 's','t','g',0 };
static CHAR aval[] = "hi";
static 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(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
if(!pStgCreatePropSetStg)
{
IStorage_Release(storage);
DeleteFileW(fileName);
return;
}
hr = pStgCreatePropSetStg(storage, 0, &propSetStorage);
ok(hr == S_OK, "StgCreatePropSetStg failed: 0x%08x\n", hr);
hr = IPropertySetStorage_Create(propSetStorage,
&FMTID_SummaryInformation, NULL, PROPSETFLAG_DEFAULT,
STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
&propertyStorage);
ok(hr == S_OK, "IPropertySetStorage_Create failed: 0x%08x\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(hr == S_OK, "ReadMultiple failed: 0x%08x\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(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
/* check code page */
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_OK, "ReadMultiple failed: 0x%08x\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(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
/* check code page */
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_OK, "ReadMultiple failed: 0x%08x\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 = aval;
hr = IPropertyStorage_WriteMultiple(propertyStorage, 1, &spec, &var, 0);
ok(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_OK, "ReadMultiple failed: 0x%08x\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(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_OK, "ReadMultiple failed: 0x%08x\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%08x\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(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
hr = pStgCreatePropSetStg(storage, 0, &propSetStorage);
ok(hr == S_OK, "StgCreatePropSetStg failed: 0x%08x\n", hr);
hr = IPropertySetStorage_Create(propSetStorage,
&FMTID_SummaryInformation, NULL, PROPSETFLAG_ANSI,
STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
&propertyStorage);
ok(hr == S_OK, "IPropertySetStorage_Create failed: 0x%08x\n", hr);
/* check code page before it's been explicitly set */
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_OK, "ReadMultiple failed: 0x%08x\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(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
/* check code page */
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_OK, "ReadMultiple failed: 0x%08x\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 unsigned 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(hr == S_OK, "WriteMultiple failed: 0x%08x\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(hr == S_OK, "WriteMultiple failed: 0x%08x\n", hr);
/* Check returned string */
hr = IPropertyStorage_ReadMultiple(propertyStorage, 1, &spec, &var);
ok(hr == S_OK, "ReadMultiple failed: 0x%08x\n", hr);
ok(var.vt == VT_LPSTR && !strcmp(U(var).pszVal, (LPCSTR)strVal),
"Didn't get expected type or value for property\n");
}
IPropertyStorage_Release(propertyStorage);
IPropertySetStorage_Release(propSetStorage);
IStorage_Release(storage);
DeleteFileW(fileName);
}
static void testFmtId(void)
{
WCHAR szSummaryInfo[] = { 5,'S','u','m','m','a','r','y',
'I','n','f','o','r','m','a','t','i','o','n',0 };
WCHAR szDocSummaryInfo[] = { 5,'D','o','c','u','m','e','n','t',
'S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',
0 };
WCHAR szIID_IPropSetStg[] = { 5,'0','j','a','a','a','a','a',
'a','A','a','a','a','a','a','d','a','A','a','a','a','a','a','a','a','G',
'c',0 };
WCHAR name[32];
FMTID fmtid;
HRESULT hr;
if (pFmtIdToPropStgName) {
hr = pFmtIdToPropStgName(NULL, name);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got 0x%08x\n", hr);
hr = pFmtIdToPropStgName(&FMTID_SummaryInformation, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got 0x%08x\n", hr);
hr = pFmtIdToPropStgName(&FMTID_SummaryInformation, name);
ok(hr == S_OK, "FmtIdToPropStgName failed: 0x%08x\n", hr);
ok(!memcmp(name, szSummaryInfo, (lstrlenW(szSummaryInfo) + 1) *
sizeof(WCHAR)), "Got wrong name for FMTID_SummaryInformation\n");
hr = pFmtIdToPropStgName(&FMTID_DocSummaryInformation, name);
ok(hr == S_OK, "FmtIdToPropStgName failed: 0x%08x\n", hr);
ok(!memcmp(name, szDocSummaryInfo, (lstrlenW(szDocSummaryInfo) + 1) *
sizeof(WCHAR)), "Got wrong name for FMTID_DocSummaryInformation\n");
hr = pFmtIdToPropStgName(&FMTID_UserDefinedProperties, name);
ok(hr == S_OK, "FmtIdToPropStgName failed: 0x%08x\n", hr);
ok(!memcmp(name, szDocSummaryInfo, (lstrlenW(szDocSummaryInfo) + 1) *
sizeof(WCHAR)), "Got wrong name for FMTID_DocSummaryInformation\n");
hr = pFmtIdToPropStgName(&IID_IPropertySetStorage, name);
ok(hr == S_OK, "FmtIdToPropStgName failed: 0x%08x\n", hr);
ok(!memcmp(name, szIID_IPropSetStg, (lstrlenW(szIID_IPropSetStg) + 1) *
sizeof(WCHAR)), "Got wrong name for IID_IPropertySetStorage\n");
}
if(pPropStgNameToFmtId) {
/* test args first */
hr = pPropStgNameToFmtId(NULL, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got 0x%08x\n", hr);
hr = pPropStgNameToFmtId(NULL, &fmtid);
ok(hr == STG_E_INVALIDNAME, "Expected STG_E_INVALIDNAME, got 0x%08x\n",
hr);
hr = pPropStgNameToFmtId(szDocSummaryInfo, NULL);
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got 0x%08x\n", hr);
/* test the known format IDs */
hr = pPropStgNameToFmtId(szSummaryInfo, &fmtid);
ok(hr == S_OK, "PropStgNameToFmtId failed: 0x%08x\n", hr);
ok(!memcmp(&fmtid, &FMTID_SummaryInformation, sizeof(fmtid)),
"Got unexpected FMTID, expected FMTID_SummaryInformation\n");
hr = pPropStgNameToFmtId(szDocSummaryInfo, &fmtid);
ok(hr == S_OK, "PropStgNameToFmtId failed: 0x%08x\n", hr);
ok(!memcmp(&fmtid, &FMTID_DocSummaryInformation, sizeof(fmtid)),
"Got unexpected FMTID, expected FMTID_DocSummaryInformation\n");
/* test another GUID */
hr = pPropStgNameToFmtId(szIID_IPropSetStg, &fmtid);
ok(hr == S_OK, "PropStgNameToFmtId failed: 0x%08x\n", hr);
ok(!memcmp(&fmtid, &IID_IPropertySetStorage, sizeof(fmtid)),
"Got unexpected FMTID, expected IID_IPropertySetStorage\n");
/* now check case matching */
CharUpperW(szDocSummaryInfo + 1);
hr = pPropStgNameToFmtId(szDocSummaryInfo, &fmtid);
ok(hr == S_OK, "PropStgNameToFmtId failed: 0x%08x\n", hr);
ok(!memcmp(&fmtid, &FMTID_DocSummaryInformation, sizeof(fmtid)),
"Got unexpected FMTID, expected FMTID_DocSummaryInformation\n");
CharUpperW(szIID_IPropSetStg + 1);
hr = pPropStgNameToFmtId(szIID_IPropSetStg, &fmtid);
ok(hr == S_OK, "PropStgNameToFmtId failed: 0x%08x\n", hr);
ok(!memcmp(&fmtid, &IID_IPropertySetStorage, sizeof(fmtid)),
"Got unexpected FMTID, expected IID_IPropertySetStorage\n");
}
}
START_TEST(stg_prop)
{
init_function_pointers();
testProps();
testCodepage();
testFmtId();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,37 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_clipboard(void);
extern void func_compobj(void);
extern void func_dragdrop(void);
extern void func_errorinfo(void);
extern void func_hglobalstream(void);
extern void func_marshal(void);
extern void func_moniker(void);
extern void func_ole2(void);
extern void func_propvariant(void);
extern void func_stg_prop(void);
extern void func_storage32(void);
extern void func_usrmarshal(void);
const struct test winetest_testlist[] =
{
{ "clipboard", func_clipboard },
{ "compobj", func_compobj },
{ "dragdrop", func_dragdrop },
{ "errorinfo", func_errorinfo },
{ "hglobalstream", func_hglobalstream },
{ "marshal", func_marshal },
{ "moniker", func_moniker },
{ "ole2", func_ole2 },
{ "propvariant", func_propvariant },
{ "stg_prop", func_stg_prop },
{ "storage32", func_storage32 },
{ "usrmarshal", func_usrmarshal },
{ 0, 0 }
};

View file

@ -0,0 +1,494 @@
/*
* User Marshaling Tests
*
* Copyright 2004-2006 Robert Shearman for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#define CONST_VTABLE
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "objidl.h"
#include "wine/test.h"
ULONG __RPC_USER HMETAFILE_UserSize(ULONG *, unsigned long, HMETAFILE *);
unsigned char * __RPC_USER HMETAFILE_UserMarshal(ULONG *, unsigned char *, HMETAFILE *);
unsigned char * __RPC_USER HMETAFILE_UserUnmarshal(ULONG *, unsigned char *, HMETAFILE *);
void __RPC_USER HMETAFILE_UserFree(ULONG *, HMETAFILE *);
static const char cf_marshaled[] =
{
0x9, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
0x9, 0x0, 0x0, 0x0,
'M', 0x0, 'y', 0x0,
'F', 0x0, 'o', 0x0,
'r', 0x0, 'm', 0x0,
'a', 0x0, 't', 0x0,
0x0, 0x0
};
static void test_marshal_CLIPFORMAT(void)
{
unsigned char *buffer;
ULONG size;
ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
wireCLIPFORMAT wirecf;
CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat");
CLIPFORMAT cf2;
size = CLIPFORMAT_UserSize(&flags, 0, &cf);
ok(size == sizeof(*wirecf) + sizeof(cf_marshaled), "Wrong size %d\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
CLIPFORMAT_UserMarshal(&flags, buffer, &cf);
wirecf = (wireCLIPFORMAT)buffer;
ok(wirecf->fContext == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", wirecf->fContext);
ok(wirecf->u.dwValue == cf, "Marshaled value should be 0x%04x instead of 0x%04x\n", cf, wirecf->u.dwValue);
ok(!memcmp(wirecf+1, cf_marshaled, sizeof(cf_marshaled)), "Marshaled data differs\n");
CLIPFORMAT_UserUnmarshal(&flags, buffer, &cf2);
ok(cf == cf2, "Didn't unmarshal properly\n");
HeapFree(GetProcessHeap(), 0, buffer);
CLIPFORMAT_UserFree(&flags, &cf2);
}
static void test_marshal_HWND(void)
{
unsigned char *buffer;
ULONG size;
ULONG flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
HWND hwnd = GetDesktopWindow();
HWND hwnd2;
wireHWND wirehwnd;
size = HWND_UserSize(&flags, 0, &hwnd);
ok(size == sizeof(*wirehwnd), "Wrong size %d\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
HWND_UserMarshal(&flags, buffer, &hwnd);
wirehwnd = (wireHWND)buffer;
ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehwnd->fContext);
ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %p\n", hwnd, (HANDLE)wirehwnd->u.hRemote);
HWND_UserUnmarshal(&flags, buffer, &hwnd2);
ok(hwnd == hwnd2, "Didn't unmarshal properly\n");
HeapFree(GetProcessHeap(), 0, buffer);
HWND_UserFree(&flags, &hwnd2);
}
static void test_marshal_HGLOBAL(void)
{
unsigned char *buffer;
ULONG size;
ULONG flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
HGLOBAL hglobal;
HGLOBAL hglobal2;
unsigned char *wirehglobal;
int i;
hglobal = NULL;
flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
size = HGLOBAL_UserSize(&flags, 0, &hglobal);
/* native is poorly programmed and allocates 4 bytes more than it needs to
* here - Wine doesn't have to emulate that */
ok((size == 8) || (size == 12), "Size should be 12, instead of %d\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
wirehglobal = buffer;
ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
wirehglobal += sizeof(ULONG);
ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+4 should be HGLOBAL\n");
HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
ok(hglobal2 == hglobal, "Didn't unmarshal properly\n");
HeapFree(GetProcessHeap(), 0, buffer);
HGLOBAL_UserFree(&flags, &hglobal2);
hglobal = GlobalAlloc(0, 4);
buffer = GlobalLock(hglobal);
for (i = 0; i < 4; i++)
buffer[i] = i;
GlobalUnlock(hglobal);
flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
size = HGLOBAL_UserSize(&flags, 0, &hglobal);
/* native is poorly programmed and allocates 4 bytes more than it needs to
* here - Wine doesn't have to emulate that */
ok((size == 24) || (size == 28), "Size should be 24 or 28, instead of %d\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
wirehglobal = buffer;
ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
wirehglobal += sizeof(ULONG);
ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0x4 should be HGLOBAL\n");
wirehglobal += sizeof(ULONG);
ok(*(ULONG *)wirehglobal == 4, "buffer+0x8 should be size of HGLOBAL\n");
wirehglobal += sizeof(ULONG);
ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0xc should be HGLOBAL\n");
wirehglobal += sizeof(ULONG);
ok(*(ULONG *)wirehglobal == 4, "buffer+0x10 should be size of HGLOBAL\n");
wirehglobal += sizeof(ULONG);
for (i = 0; i < 4; i++)
ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
HeapFree(GetProcessHeap(), 0, buffer);
HGLOBAL_UserFree(&flags, &hglobal2);
GlobalFree(hglobal);
}
static HENHMETAFILE create_emf(void)
{
RECT rect = {0, 0, 100, 100};
HDC hdc = CreateEnhMetaFile(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, NULL, "Test String", strlen("Test String"), NULL);
return CloseEnhMetaFile(hdc);
}
static void test_marshal_HENHMETAFILE(void)
{
unsigned char *buffer;
ULONG size;
ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
HENHMETAFILE hemf;
HENHMETAFILE hemf2 = NULL;
unsigned char *wirehemf;
hemf = create_emf();
size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
wirehemf = buffer;
ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
wirehemf += sizeof(DWORD);
ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
wirehemf += sizeof(DWORD);
ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
wirehemf += sizeof(DWORD);
ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
wirehemf += sizeof(DWORD);
ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD *)wirehemf);
wirehemf += sizeof(DWORD);
/* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
* at this point */
HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
HeapFree(GetProcessHeap(), 0, buffer);
HENHMETAFILE_UserFree(&flags, &hemf2);
DeleteEnhMetaFile(hemf);
/* test NULL emf */
hemf = NULL;
size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
ok(size == 8, "size should be 8 bytes, not %d\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
wirehemf = buffer;
ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
wirehemf += sizeof(DWORD);
ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
wirehemf += sizeof(DWORD);
HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
HeapFree(GetProcessHeap(), 0, buffer);
HENHMETAFILE_UserFree(&flags, &hemf2);
}
static HMETAFILE create_mf(void)
{
RECT rect = {0, 0, 100, 100};
HDC hdc = CreateMetaFile(NULL);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, "Test String", strlen("Test String"), NULL);
return CloseMetaFile(hdc);
}
static void test_marshal_HMETAFILE(void)
{
unsigned char *buffer;
ULONG size;
ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
HMETAFILE hmf;
HMETAFILE hmf2 = NULL;
unsigned char *wirehmf;
hmf = create_mf();
size = HMETAFILE_UserSize(&flags, 0, &hmf);
ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
HMETAFILE_UserMarshal(&flags, buffer, &hmf);
wirehmf = buffer;
ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf);
wirehmf += sizeof(DWORD);
ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf);
wirehmf += sizeof(DWORD);
ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf);
wirehmf += sizeof(DWORD);
ok(*(DWORD *)wirehmf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehmf);
wirehmf += sizeof(DWORD);
ok(*(WORD *)wirehmf == 1, "wirestgm + 0x10 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmf);
wirehmf += sizeof(DWORD);
/* ... rest of data not tested - refer to tests for GetMetaFileBits
* at this point */
HMETAFILE_UserUnmarshal(&flags, buffer, &hmf2);
ok(hmf2 != NULL, "HMETAFILE didn't unmarshal\n");
HeapFree(GetProcessHeap(), 0, buffer);
HMETAFILE_UserFree(&flags, &hmf2);
DeleteMetaFile(hmf);
/* test NULL emf */
hmf = NULL;
size = HMETAFILE_UserSize(&flags, 0, &hmf);
ok(size == 8, "size should be 8 bytes, not %d\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
HMETAFILE_UserMarshal(&flags, buffer, &hmf);
wirehmf = buffer;
ok(*(DWORD *)wirehmf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmf);
wirehmf += sizeof(DWORD);
ok(*(DWORD *)wirehmf == (DWORD)(DWORD_PTR)hmf, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmf);
wirehmf += sizeof(DWORD);
HMETAFILE_UserUnmarshal(&flags, buffer, &hmf2);
ok(hmf2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
HeapFree(GetProcessHeap(), 0, buffer);
HMETAFILE_UserFree(&flags, &hmf2);
}
#define USER_MARSHAL_PTR_PREFIX \
( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \
( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) )
static void test_marshal_HMETAFILEPICT(void)
{
unsigned char *buffer, *buffer_end;
ULONG size;
ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
HMETAFILEPICT hmfp;
HMETAFILEPICT hmfp2 = NULL;
METAFILEPICT *pmfp;
unsigned char *wirehmfp;
hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(*pmfp));
pmfp = GlobalLock(hmfp);
pmfp->mm = MM_ISOTROPIC;
pmfp->xExt = 1;
pmfp->yExt = 2;
pmfp->hMF = create_mf();
GlobalUnlock(hmfp);
size = HMETAFILEPICT_UserSize(&flags, 0, &hmfp);
ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
trace("size is %d\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
buffer_end = HMETAFILEPICT_UserMarshal(&flags, buffer, &hmfp);
wirehmfp = buffer;
ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
wirehmfp += sizeof(DWORD);
ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp);
wirehmfp += sizeof(DWORD);
ok(*(DWORD *)wirehmfp == MM_ISOTROPIC, "wirestgm + 0x8 should be MM_ISOTROPIC instead of 0x%08x\n", *(DWORD *)wirehmfp);
wirehmfp += sizeof(DWORD);
ok(*(DWORD *)wirehmfp == 1, "wirestgm + 0xc should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp);
wirehmfp += sizeof(DWORD);
ok(*(DWORD *)wirehmfp == 2, "wirestgm + 0x10 should be 2 instead of 0x%08x\n", *(DWORD *)wirehmfp);
wirehmfp += sizeof(DWORD);
ok(*(DWORD *)wirehmfp == USER_MARSHAL_PTR_PREFIX, "wirestgm + 0x14 should be \"User\" instead of 0x%08x\n", *(DWORD *)wirehmfp);
wirehmfp += sizeof(DWORD);
ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x18 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
wirehmfp += sizeof(DWORD);
pmfp = GlobalLock(hmfp);
ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)pmfp->hMF, "wirestgm + 0x1c should be pmfp->hMF instead of 0x%08x\n", *(DWORD *)wirehmfp);
GlobalUnlock(hmfp);
wirehmfp += sizeof(DWORD);
/* Note use (buffer_end - buffer) instead of size here, because size is an
* overestimate with native */
ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x28), "wirestgm + 0x20 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp);
wirehmfp += sizeof(DWORD);
ok(*(DWORD *)wirehmfp == (buffer_end - buffer - 0x28), "wirestgm + 0x24 should be size - 0x34 instead of 0x%08x\n", *(DWORD *)wirehmfp);
wirehmfp += sizeof(DWORD);
ok(*(WORD *)wirehmfp == 1, "wirehmfp + 0x28 should be 1 instead of 0x%08x\n", *(DWORD *)wirehmfp);
wirehmfp += sizeof(DWORD);
/* ... rest of data not tested - refer to tests for GetMetaFileBits
* at this point */
HMETAFILEPICT_UserUnmarshal(&flags, buffer, &hmfp2);
ok(hmfp2 != NULL, "HMETAFILEPICT didn't unmarshal\n");
HeapFree(GetProcessHeap(), 0, buffer);
HMETAFILEPICT_UserFree(&flags, &hmfp2);
pmfp = GlobalLock(hmfp);
DeleteMetaFile(pmfp->hMF);
GlobalUnlock(hmfp);
GlobalFree(hmfp);
/* test NULL emf */
hmfp = NULL;
size = HMETAFILEPICT_UserSize(&flags, 0, &hmfp);
ok(size == 8, "size should be 8 bytes, not %d\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
HMETAFILEPICT_UserMarshal(&flags, buffer, &hmfp);
wirehmfp = buffer;
ok(*(DWORD *)wirehmfp == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehmfp);
wirehmfp += sizeof(DWORD);
ok(*(DWORD *)wirehmfp == (DWORD)(DWORD_PTR)hmfp, "wirestgm + 0x4 should be hmf instead of 0x%08x\n", *(DWORD *)wirehmfp);
wirehmfp += sizeof(DWORD);
hmfp2 = NULL;
HMETAFILEPICT_UserUnmarshal(&flags, buffer, &hmfp2);
ok(hmfp2 == NULL, "NULL HMETAFILE didn't unmarshal\n");
HeapFree(GetProcessHeap(), 0, buffer);
HMETAFILEPICT_UserFree(&flags, &hmfp2);
}
static HRESULT WINAPI Test_IUnknown_QueryInterface(
LPUNKNOWN iface,
REFIID riid,
LPVOID *ppvObj)
{
if (ppvObj == NULL) return E_POINTER;
if (IsEqualGUID(riid, &IID_IUnknown))
{
*ppvObj = (LPVOID)iface;
IUnknown_AddRef(iface);
return S_OK;
}
*ppvObj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
{
return 2; /* non-heap-based object */
}
static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
{
return 1; /* non-heap-based object */
}
static const IUnknownVtbl TestUnknown_Vtbl =
{
Test_IUnknown_QueryInterface,
Test_IUnknown_AddRef,
Test_IUnknown_Release,
};
static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
ULONG __RPC_USER WdtpInterfacePointer_UserSize(ULONG *, ULONG, ULONG, IUnknown *, REFIID);
unsigned char * __RPC_USER WdtpInterfacePointer_UserMarshal(ULONG *, ULONG, unsigned char *, IUnknown *, REFIID);
unsigned char * __RPC_USER WdtpInterfacePointer_UserUnmarshal(ULONG *, unsigned char *, IUnknown **, REFIID);
void __RPC_USER WdtpInterfacePointer_UserFree(IUnknown *);
static void test_marshal_WdtpInterfacePointer(void)
{
unsigned char *buffer, *buffer_end;
ULONG size;
MIDL_STUB_MESSAGE stubmsg;
USER_MARSHAL_CB umcb;
IUnknown *unk;
IUnknown *unk2;
unsigned char *wireip;
const IID *iid;
memset(&stubmsg, 0xcc, sizeof(stubmsg));
stubmsg.dwDestContext = MSHCTX_INPROC;
stubmsg.pvDestContext = NULL;
memset(&umcb, 0xcc, sizeof(umcb));
umcb.Flags = MAKELONG(MSHCTX_INPROC, NDR_LOCAL_DATA_REPRESENTATION);
umcb.pStubMsg = &stubmsg;
/* shows that the WdtpInterfacePointer functions don't marshal anything for
* NULL pointers, so code using these functions must handle that case
* itself */
unk = NULL;
size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 0, unk, &IID_IUnknown);
ok(size == 0, "size should be 0 bytes, not %d\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, buffer, unk, &IID_IUnknown);
wireip = buffer;
HeapFree(GetProcessHeap(), 0, buffer);
unk = &Test_Unknown;
size = WdtpInterfacePointer_UserSize(&umcb.Flags, umcb.Flags, 0, unk, &IID_IUnknown);
todo_wine
ok(size == 108, "size should be 108 bytes, not %d\n", size);
buffer = HeapAlloc(GetProcessHeap(), 0, size);
buffer_end = WdtpInterfacePointer_UserMarshal(&umcb.Flags, umcb.Flags, buffer, unk, &IID_IUnknown);
wireip = buffer;
if (size >= 28)
{
ok(*(DWORD *)wireip == 0x44, "wireip + 0x0 should be 0x4c instead of 0x%08x\n", *(DWORD *)wireip);
wireip += sizeof(DWORD);
ok(*(DWORD *)wireip == 0x44, "wireip + 0x8 should be 0x4c instead of 0x%08x\n", *(DWORD *)wireip);
wireip += sizeof(DWORD);
ok(*(DWORD *)wireip == 0x574f454d /* 'MEOW' */, "wireip + 0xc should be 0x574f454d instead of 0x%08x\n", *(DWORD *)wireip);
wireip += sizeof(DWORD);
ok(*(DWORD *)wireip == 0x1, "wireip + 0x10 should be 0x1 instead of 0x%08x\n", *(DWORD *)wireip);
wireip += sizeof(DWORD);
iid = (const IID *)buffer;
ok(!IsEqualIID(iid, &IID_IUnknown),
"wireip + 0x14 should be IID_IUnknown instead of {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
iid->Data1, iid->Data2, iid->Data3,
iid->Data4[0], iid->Data4[1], iid->Data4[2], iid->Data4[3],
iid->Data4[4], iid->Data4[5], iid->Data4[6], iid->Data4[7]);
ok(*(DWORD *)wireip == 0, "wireip + 0x14 should be 0 instead of 0x%08x\n", *(DWORD *)wireip);
wireip += sizeof(IID);
ok(*(DWORD *)wireip == 0, "wireip + 0x20 should be 0 instead of 0x%08x\n", *(DWORD *)wireip);
wireip += sizeof(DWORD);
ok(*(DWORD *)wireip == 5, "wireip + 0x24 should be 5 instead of %d\n", *(DWORD *)wireip);
wireip += sizeof(DWORD);
/* the rest is dynamic so can't really be tested */
}
unk2 = NULL;
WdtpInterfacePointer_UserUnmarshal(&umcb.Flags, buffer, &unk2, &IID_IUnknown);
todo_wine
ok(unk2 != NULL, "IUnknown object didn't unmarshal properly\n");
HeapFree(GetProcessHeap(), 0, buffer);
WdtpInterfacePointer_UserFree(unk2);
}
START_TEST(usrmarshal)
{
CoInitialize(NULL);
test_marshal_CLIPFORMAT();
test_marshal_HWND();
test_marshal_HGLOBAL();
test_marshal_HENHMETAFILE();
test_marshal_HMETAFILE();
test_marshal_HMETAFILEPICT();
test_marshal_WdtpInterfacePointer();
CoUninitialize();
}

View file

@ -0,0 +1,31 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<group>
<module name="oleaut32_winetest" type="win32cui" installbase="bin" installname="oleaut32_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="oleaut32_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>oleaut32</library>
<library>ole32</library>
<library>shlwapi</library>
<library>rpcrt4</library>
<library>user32</library>
<library>gdi32</library>
<library>advapi32</library>
<library>kernel32</library>
<library>uuid</library>
<library>ntdll</library>
<file>olefont.c</file>
<file>olepicture.c</file>
<file>safearray.c</file>
<file>tmarshal.c</file>
<file>typelib.c</file>
<file>usrmarshal.c</file>
<file>varformat.c</file>
<file>vartest.c</file>
<file>vartype.c</file>
<file>tmarshal.rc</file>
<file>testlist.c</file>
</module>
</group>

View file

@ -0,0 +1,828 @@
/*
* OLEFONT test program
*
* Copyright 2003 Marcus Meissner
* Copyright 2006 (Google) Benjamin Arai
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <time.h>
#define COBJMACROS
#include <wine/test.h>
#include <windef.h>
#include <winbase.h>
#include <winuser.h>
#include <wingdi.h>
#include <winnls.h>
#include <winerror.h>
#include <winnt.h>
#include <wtypes.h>
#include <olectl.h>
#include <ocidl.h>
static WCHAR MSSansSerif_font[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f',0};
static WCHAR system_font[] = { 'S','y','s','t','e','m',0 };
static WCHAR arial_font[] = { 'A','r','i','a','l',0 };
static HMODULE hOleaut32;
static HRESULT (WINAPI *pOleCreateFontIndirect)(LPFONTDESC,REFIID,LPVOID*);
#define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
/* Create a font with cySize given by lo_size, hi_size, */
/* SetRatio to ratio_logical, ratio_himetric, */
/* check that resulting hfont has height hfont_height. */
/* Various checks along the way. */
static void test_ifont_sizes(long lo_size, long hi_size,
long ratio_logical, long ratio_himetric,
long hfont_height, const char * test_name)
{
FONTDESC fd;
LPVOID pvObj = NULL;
IFont* ifnt = NULL;
HFONT hfont;
LOGFONT lf;
CY psize;
HRESULT hres;
fd.cbSizeofstruct = sizeof(FONTDESC);
fd.lpstrName = system_font;
S(fd.cySize).Lo = lo_size;
S(fd.cySize).Hi = hi_size;
fd.sWeight = 0;
fd.sCharset = 0;
fd.fItalic = 0;
fd.fUnderline = 0;
fd.fStrikethrough = 0;
/* Create font, test that it worked. */
hres = pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj);
ifnt = pvObj;
ok(hres == S_OK,"%s: OCFI returns 0x%08x instead of S_OK.\n",
test_name, hres);
ok(pvObj != NULL,"%s: OCFI returns NULL.\n", test_name);
/* Read back size. Hi part was ignored. */
hres = IFont_get_Size(ifnt, &psize);
ok(hres == S_OK,"%s: IFont_get_size returns 0x%08x instead of S_OK.\n",
test_name, hres);
ok(S(psize).Lo == lo_size && S(psize).Hi == 0,
"%s: get_Size: Lo=%d, Hi=%d; expected Lo=%ld, Hi=%ld.\n",
test_name, S(psize).Lo, S(psize).Hi, lo_size, 0L);
/* Change ratio, check size unchanged. Standard is 72, 2540. */
hres = IFont_SetRatio(ifnt, ratio_logical, ratio_himetric);
ok(hres == S_OK,"%s: IFont_SR returns 0x%08x instead of S_OK.\n",
test_name, hres);
hres = IFont_get_Size(ifnt, &psize);
ok(hres == S_OK,"%s: IFont_get_size returns 0x%08x instead of S_OK.\n",
test_name, hres);
ok(S(psize).Lo == lo_size && S(psize).Hi == 0,
"%s: gS after SR: Lo=%d, Hi=%d; expected Lo=%ld, Hi=%ld.\n",
test_name, S(psize).Lo, S(psize).Hi, lo_size, 0L);
/* Check hFont size with this ratio. This tests an important */
/* conversion for which MSDN is very wrong. */
hres = IFont_get_hFont (ifnt, &hfont);
ok(hres == S_OK, "%s: IFont_get_hFont returns 0x%08x instead of S_OK.\n",
test_name, hres);
hres = GetObject (hfont, sizeof(LOGFONT), &lf);
ok(lf.lfHeight == hfont_height,
"%s: hFont has lf.lfHeight=%d, expected %ld.\n",
test_name, lf.lfHeight, hfont_height);
/* Free IFont. */
IFont_Release(ifnt);
}
static void test_QueryInterface(void)
{
LPVOID pvObj = NULL;
HRESULT hres;
IFont* font = NULL;
LONG ret;
hres = pOleCreateFontIndirect(NULL, &IID_IFont, &pvObj);
font = pvObj;
ok(hres == S_OK,"OCFI (NULL,..) does not return 0, but 0x%08x\n",hres);
ok(font != NULL,"OCFI (NULL,..) returns NULL, instead of !NULL\n");
pvObj = NULL;
hres = IFont_QueryInterface( font, &IID_IFont, &pvObj);
/* Test if QueryInterface increments ref counter for IFONTs */
ret = IFont_AddRef(font);
ok(ret == 3, "IFont_QI expected ref value 3 but instead got %12u\n",ret);
IFont_Release(font);
ok(hres == S_OK,"IFont_QI does not return S_OK, but 0x%08x\n", hres);
ok(pvObj != NULL,"IFont_QI does return NULL, instead of a ptr\n");
/* Orignial ref and QueryInterface ref both have to be released */
IFont_Release(font);
IFont_Release(font);
}
static void test_type_info(void)
{
LPVOID pvObj = NULL;
HRESULT hres;
IFontDisp* fontdisp = NULL;
ITypeInfo* pTInfo;
WCHAR name_Name[] = {'N','a','m','e',0};
BSTR names[3];
UINT n;
LCID en_us = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
SORT_DEFAULT);
DISPPARAMS dispparams;
VARIANT varresult;
pOleCreateFontIndirect(NULL, &IID_IFontDisp, &pvObj);
fontdisp = pvObj;
hres = IFontDisp_GetTypeInfo(fontdisp, 0, en_us, &pTInfo);
ok(hres == S_OK, "GTI returned 0x%08x instead of S_OK.\n", hres);
ok(pTInfo != NULL, "GTI returned NULL.\n");
hres = ITypeInfo_GetNames(pTInfo, DISPID_FONT_NAME, names, 3, &n);
ok(hres == S_OK, "GetNames returned 0x%08x instead of S_OK.\n", hres);
ok(n == 1, "GetNames returned %d names instead of 1.\n", n);
ok(!lstrcmpiW(names[0],name_Name), "DISPID_FONT_NAME doesn't get 'Names'.\n");
ITypeInfo_Release(pTInfo);
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
dispparams.cArgs = 0;
dispparams.rgvarg = NULL;
VariantInit(&varresult);
hres = IFontDisp_Invoke(fontdisp, DISPID_FONT_NAME, &IID_NULL,
LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult,
NULL, NULL);
ok(hres == S_OK, "IFontDisp_Invoke return 0x%08x instead of S_OK.\n", hres);
VariantClear(&varresult);
IFontDisp_Release(fontdisp);
}
static HRESULT WINAPI FontEventsDisp_QueryInterface(
IFontEventsDisp *iface,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
{
if (IsEqualIID(riid, &IID_IFontEventsDisp) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
{
IUnknown_AddRef(iface);
*ppvObject = iface;
return S_OK;
}
else
{
*ppvObject = NULL;
return E_NOINTERFACE;
}
}
static ULONG WINAPI FontEventsDisp_AddRef(
IFontEventsDisp *iface)
{
return 2;
}
static ULONG WINAPI FontEventsDisp_Release(
IFontEventsDisp *iface)
{
return 1;
}
static int fonteventsdisp_invoke_called = 0;
static HRESULT WINAPI FontEventsDisp_Invoke(
IFontEventsDisp __RPC_FAR * iface,
/* [in] */ DISPID dispIdMember,
/* [in] */ REFIID riid,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
/* [out] */ VARIANT __RPC_FAR *pVarResult,
/* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
/* [out] */ UINT __RPC_FAR *puArgErr)
{
static const WCHAR wszBold[] = {'B','o','l','d',0};
ok(wFlags == INVOKE_FUNC, "invoke flags should have been INVOKE_FUNC instead of 0x%x\n", wFlags);
ok(dispIdMember == DISPID_FONT_CHANGED, "dispIdMember should have been DISPID_FONT_CHANGED instead of 0x%x\n", dispIdMember);
ok(pDispParams->cArgs == 1, "pDispParams->cArgs should have been 1 instead of %d\n", pDispParams->cArgs);
ok(V_VT(&pDispParams->rgvarg[0]) == VT_BSTR, "VT of first param should have been VT_BSTR instead of %d\n", V_VT(&pDispParams->rgvarg[0]));
ok(!lstrcmpW(V_BSTR(&pDispParams->rgvarg[0]), wszBold), "String in first param should have been \"Bold\"\n");
fonteventsdisp_invoke_called++;
return S_OK;
}
static IFontEventsDispVtbl FontEventsDisp_Vtbl =
{
FontEventsDisp_QueryInterface,
FontEventsDisp_AddRef,
FontEventsDisp_Release,
NULL,
NULL,
NULL,
FontEventsDisp_Invoke
};
static IFontEventsDisp FontEventsDisp = { &FontEventsDisp_Vtbl };
static void test_font_events_disp(void)
{
IFont *pFont;
IFont *pFont2;
IConnectionPointContainer *pCPC;
IConnectionPoint *pCP;
FONTDESC fontdesc;
HRESULT hr;
DWORD dwCookie;
IFontDisp *pFontDisp;
DISPPARAMS dispparams;
VARIANTARG vararg;
fontdesc.cbSizeofstruct = sizeof(fontdesc);
fontdesc.lpstrName = MSSansSerif_font;
fontdesc.cySize.int64 = 12 * 10000; /* 12 pt */
fontdesc.sWeight = FW_NORMAL;
fontdesc.sCharset = 0;
fontdesc.fItalic = FALSE;
fontdesc.fUnderline = FALSE;
fontdesc.fStrikethrough = FALSE;
hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&pFont);
ok_ole_success(hr, "OleCreateFontIndirect");
hr = IFont_QueryInterface(pFont, &IID_IConnectionPointContainer, (void **)&pCPC);
ok_ole_success(hr, "IFont_QueryInterface");
hr = IConnectionPointContainer_FindConnectionPoint(pCPC, &IID_IFontEventsDisp, &pCP);
ok_ole_success(hr, "IConnectionPointContainer_FindConnectionPoint");
IConnectionPointContainer_Release(pCPC);
hr = IConnectionPoint_Advise(pCP, (IUnknown *)&FontEventsDisp, &dwCookie);
ok_ole_success(hr, "IConnectionPoint_Advise");
IConnectionPoint_Release(pCP);
hr = IFont_put_Bold(pFont, TRUE);
ok_ole_success(hr, "IFont_put_Bold");
ok(fonteventsdisp_invoke_called == 1, "IFontEventDisp::Invoke wasn't called once\n");
hr = IFont_QueryInterface(pFont, &IID_IFontDisp, (void **)&pFontDisp);
ok_ole_success(hr, "IFont_QueryInterface");
V_VT(&vararg) = VT_BOOL;
V_BOOL(&vararg) = VARIANT_FALSE;
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
dispparams.cArgs = 1;
dispparams.rgvarg = &vararg;
hr = IFontDisp_Invoke(pFontDisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
IFontDisp_Release(pFontDisp);
ok(fonteventsdisp_invoke_called == 2, "IFontEventDisp::Invoke was called %d times instead of twice\n",
fonteventsdisp_invoke_called);
hr = IFont_Clone(pFont, &pFont2);
ok_ole_success(hr, "IFont_Clone");
IFont_Release(pFont);
hr = IFont_put_Bold(pFont2, FALSE);
ok_ole_success(hr, "IFont_put_Bold");
/* this test shows that the notification routine isn't called again */
ok(fonteventsdisp_invoke_called == 2, "IFontEventDisp::Invoke was called %d times instead of twice\n",
fonteventsdisp_invoke_called);
IFont_Release(pFont2);
}
static void test_names_ids(WCHAR* w_name_1, const char* a_name_1,
WCHAR* w_name_2, const char* a_name_2,
LCID lcid, DISPID id_1, DISPID id_2,
HRESULT hres_expect, int numnames)
{
LPVOID pvObj = NULL;
IFontDisp *fontdisp = NULL;
HRESULT hres;
DISPID rgDispId[2] = {0xdeadbeef, 0xdeadbeef};
LPOLESTR names[2] = {w_name_1, w_name_2};
pOleCreateFontIndirect(NULL, &IID_IFontDisp, &pvObj);
fontdisp = pvObj;
hres = IFontDisp_GetIDsOfNames(fontdisp, &IID_NULL, names, numnames,
lcid, rgDispId);
/* test hres */
ok(hres == hres_expect,
"GetIDsOfNames: \"%s\", \"%s\" returns 0x%08x, expected 0x%08x.\n",
a_name_1, a_name_2, hres, hres_expect);
/* test first DISPID */
ok(rgDispId[0]==id_1,
"GetIDsOfNames: \"%s\" gets DISPID 0x%08x, expected 0x%08x.\n",
a_name_1, rgDispId[0], id_1);
/* test second DISPID is present */
if (numnames == 2)
{
ok(rgDispId[1]==id_2,
"GetIDsOfNames: ..., \"%s\" gets DISPID 0x%08x, expected 0x%08x.\n",
a_name_2, rgDispId[1], id_2);
}
IFontDisp_Release(fontdisp);
}
static void test_GetIDsOfNames(void)
{
WCHAR name_Name[] = {'N','a','m','e',0};
WCHAR name_Italic[] = {'I','t','a','l','i','c',0};
WCHAR name_Size[] = {'S','i','z','e',0};
WCHAR name_Bold[] = {'B','o','l','d',0};
WCHAR name_Underline[] = {'U','n','d','e','r','l','i','n','e',0};
WCHAR name_Strikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
WCHAR name_Weight[] = {'W','e','i','g','h','t',0};
WCHAR name_Charset[] = {'C','h','a','r','s','e','t',0};
WCHAR name_Foo[] = {'F','o','o',0};
WCHAR name_nAmE[] = {'n','A','m','E',0};
WCHAR name_Nom[] = {'N','o','m',0};
LCID en_us = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
SORT_DEFAULT);
LCID fr_fr = MAKELCID(MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH),
SORT_DEFAULT);
/* Test DISPID_FONTs for the various properties. */
test_names_ids(name_Name, "Name", NULL, "", en_us,
DISPID_FONT_NAME, 0, S_OK,1);
test_names_ids(name_Size, "Size", NULL, "", en_us,
DISPID_FONT_SIZE, 0, S_OK,1);
test_names_ids(name_Bold, "Bold", NULL, "", en_us,
DISPID_FONT_BOLD, 0, S_OK,1);
test_names_ids(name_Italic, "Italic", NULL, "", en_us,
DISPID_FONT_ITALIC, 0, S_OK,1);
test_names_ids(name_Underline, "Underline", NULL, "", en_us,
DISPID_FONT_UNDER, 0, S_OK,1);
test_names_ids(name_Strikethrough, "Strikethrough", NULL, "", en_us,
DISPID_FONT_STRIKE, 0, S_OK,1);
test_names_ids(name_Weight, "Weight", NULL, "", en_us,
DISPID_FONT_WEIGHT, 0, S_OK,1);
test_names_ids(name_Charset, "Charset", NULL, "", en_us,
DISPID_FONT_CHARSET, 0, S_OK,1);
/* Capitalization doesn't matter. */
test_names_ids(name_nAmE, "nAmE", NULL, "", en_us,
DISPID_FONT_NAME, 0, S_OK,1);
/* Unknown name. */
test_names_ids(name_Foo, "Foo", NULL, "", en_us,
DISPID_UNKNOWN, 0, DISP_E_UNKNOWNNAME,1);
/* Pass several names: first is processed, */
/* second gets DISPID_UNKNOWN and doesn't affect retval. */
test_names_ids(name_Italic, "Italic", name_Name, "Name", en_us,
DISPID_FONT_ITALIC, DISPID_UNKNOWN, S_OK,2);
test_names_ids(name_Italic, "Italic", name_Foo, "Foo", en_us,
DISPID_FONT_ITALIC, DISPID_UNKNOWN, S_OK,2);
/* Locale ID has no effect. */
test_names_ids(name_Name, "Name", NULL, "", fr_fr,
DISPID_FONT_NAME, 0, S_OK,1);
test_names_ids(name_Nom, "This is not a font", NULL, "", fr_fr,
DISPID_UNKNOWN, 0, DISP_E_UNKNOWNNAME,1);
/* One of the arguments are invalid */
test_names_ids(name_Name, "Name", NULL, "", en_us,
0xdeadbeef, 0xdeadbeef, E_INVALIDARG,0);
test_names_ids(name_Italic, "Italic", NULL, "", en_us,
0xdeadbeef, 0xdeadbeef, E_INVALIDARG,0);
test_names_ids(name_Foo, "Foo", NULL, "", en_us,
0xdeadbeef, 0xdeadbeef, E_INVALIDARG,0);
/* Crazy locale ID? */
test_names_ids(name_Name, "Name", NULL, "", -1,
DISPID_FONT_NAME, 0, S_OK,1);
}
static void test_Invoke(void)
{
IFontDisp *fontdisp;
HRESULT hr;
VARIANTARG vararg;
DISPPARAMS dispparams;
VARIANT varresult;
hr = pOleCreateFontIndirect(NULL, &IID_IFontDisp, (void **)&fontdisp);
ok_ole_success(hr, "OleCreateFontIndirect");
V_VT(&vararg) = VT_BOOL;
V_BOOL(&vararg) = VARIANT_FALSE;
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
dispparams.cArgs = 1;
dispparams.rgvarg = &vararg;
hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_IFontDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
ok(hr == DISP_E_UNKNOWNINTERFACE, "IFontDisp_Invoke should have returned DISP_E_UNKNOWNINTERFACE instead of 0x%08x\n", hr);
dispparams.cArgs = 0;
dispparams.rgvarg = NULL;
hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
ok(hr == DISP_E_BADPARAMCOUNT, "IFontDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
ok(hr == DISP_E_PARAMNOTOPTIONAL, "IFontDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
ok(hr == DISP_E_PARAMNOTOPTIONAL, "IFontDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
ok_ole_success(hr, "IFontDisp_Invoke");
hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_METHOD, NULL, &varresult, NULL, NULL);
ok(hr == DISP_E_MEMBERNOTFOUND, "IFontDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
hr = IFontDisp_Invoke(fontdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
ok(hr == DISP_E_MEMBERNOTFOUND, "IFontDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
dispparams.cArgs = 1;
dispparams.rgvarg = &vararg;
hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
ok_ole_success(hr, "IFontDisp_Invoke");
IFontDisp_Release(fontdisp);
}
static void test_IsEqual(void)
{
FONTDESC fd;
LPVOID pvObj = NULL;
LPVOID pvObj2 = NULL;
IFont* ifnt = NULL;
IFont* ifnt2 = NULL;
HRESULT hres;
/* Basic font description */
fd.cbSizeofstruct = sizeof(FONTDESC);
fd.lpstrName = system_font;
S(fd.cySize).Lo = 100;
S(fd.cySize).Hi = 100;
fd.sWeight = 0;
fd.sCharset = 0;
fd.fItalic = 0;
fd.fUnderline = 0;
fd.fStrikethrough = 0;
/* Create font */
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj);
ifnt = pvObj;
/* Test equal fonts */
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
ifnt2 = pvObj2;
hres = IFont_IsEqual(ifnt,ifnt2);
ok(hres == S_OK,
"IFont_IsEqual: (EQUAL) Expected S_OK but got 0x%08x\n",hres);
IFont_Release(ifnt2);
/* Check for bad pointer */
hres = IFont_IsEqual(ifnt,NULL);
ok(hres == E_POINTER,
"IFont_IsEqual: (NULL) Expected 0x80004003 but got 0x%08x\n",hres);
/* Test strName */
fd.lpstrName = arial_font;
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
hres = IFont_IsEqual(ifnt,ifnt2);
ok(hres == S_FALSE,
"IFont_IsEqual: (strName) Expected S_FALSE but got 0x%08x\n",hres);
fd.lpstrName = system_font;
IFont_Release(ifnt2);
/* Test lo font size */
S(fd.cySize).Lo = 10000;
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
ifnt2 = pvObj2;
hres = IFont_IsEqual(ifnt,ifnt2);
ok(hres == S_FALSE,
"IFont_IsEqual: (Lo font size) Expected S_FALSE but got 0x%08x\n",hres);
S(fd.cySize).Lo = 100;
IFont_Release(ifnt2);
/* Test hi font size */
S(fd.cySize).Hi = 10000;
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
ifnt2 = pvObj2;
hres = IFont_IsEqual(ifnt,ifnt2);
ok(hres == S_FALSE,
"IFont_IsEqual: (Hi font size) Expected S_FALSE but got 0x%08x\n",hres);
S(fd.cySize).Hi = 100;
IFont_Release(ifnt2);
/* Test font weight */
fd.sWeight = 100;
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
ifnt2 = pvObj2;
hres = IFont_IsEqual(ifnt,ifnt2);
ok(hres == S_FALSE,
"IFont_IsEqual: (Weight) Expected S_FALSE but got 0x%08x\n",hres);
fd.sWeight = 0;
IFont_Release(ifnt2);
/* Test charset */
fd.sCharset = 1;
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
hres = IFont_IsEqual(ifnt,ifnt2);
ok(hres == S_FALSE,
"IFont_IsEqual: (Charset) Expected S_FALSE but got 0x%08x\n",hres);
fd.sCharset = 0;
IFont_Release(ifnt2);
/* Test italic setting */
fd.fItalic = 1;
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
hres = IFont_IsEqual(ifnt,ifnt2);
ok(hres == S_FALSE,
"IFont_IsEqual: (Italic) Expected S_FALSE but got 0x%08x\n",hres);
fd.fItalic = 0;
IFont_Release(ifnt2);
/* Test underline setting */
fd.fUnderline = 1;
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
hres = IFont_IsEqual(ifnt,ifnt2);
ok(hres == S_FALSE,
"IFont_IsEqual: (Underline) Expected S_FALSE but got 0x%08x\n",hres);
fd.fUnderline = 0;
IFont_Release(ifnt2);
/* Test strikethrough setting */
fd.fStrikethrough = 1;
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
hres = IFont_IsEqual(ifnt,ifnt2);
ok(hres == S_FALSE,
"IFont_IsEqual: (Strikethrough) Expected S_FALSE but got 0x%08x\n",hres);
fd.fStrikethrough = 0;
IFont_Release(ifnt2);
/* Free IFont. */
IFont_Release(ifnt);
}
static void test_ReleaseHfont(void)
{
FONTDESC fd;
LPVOID pvObj1 = NULL;
LPVOID pvObj2 = NULL;
IFont* ifnt1 = NULL;
IFont* ifnt2 = NULL;
HFONT hfnt1 = 0;
HFONT hfnt2 = 0;
HRESULT hres;
/* Basic font description */
fd.cbSizeofstruct = sizeof(FONTDESC);
fd.lpstrName = system_font;
S(fd.cySize).Lo = 100;
S(fd.cySize).Hi = 100;
fd.sWeight = 0;
fd.sCharset = 0;
fd.fItalic = 0;
fd.fUnderline = 0;
fd.fStrikethrough = 0;
/* Create HFONTs and IFONTs */
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj1);
ifnt1 = pvObj1;
IFont_get_hFont(ifnt1,&hfnt1);
fd.lpstrName = arial_font;
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
ifnt2 = pvObj2;
IFont_get_hFont(ifnt2,&hfnt2);
/* Try invalid HFONT */
hres = IFont_ReleaseHfont(ifnt1,NULL);
ok(hres == E_INVALIDARG,
"IFont_ReleaseHfont: (Bad HFONT) Expected E_INVALIDARG but got 0x%08x\n",
hres);
/* Try to add a bad HFONT */
hres = IFont_ReleaseHfont(ifnt1,(HFONT)32);
ok(hres == S_FALSE,
"IFont_ReleaseHfont: (Bad HFONT) Expected S_FALSE but got 0x%08x\n",
hres);
/* Release all refs */
hres = IFont_ReleaseHfont(ifnt1,hfnt1);
ok(hres == S_OK,
"IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
hres);
hres = IFont_ReleaseHfont(ifnt2,hfnt2);
ok(hres == S_OK,
"IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
hres);
/* Check that both lists are empty */
hres = IFont_ReleaseHfont(ifnt1,hfnt1);
ok(hres == S_FALSE,
"IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
hres);
/* The list should be empty */
hres = IFont_ReleaseHfont(ifnt2,hfnt2);
ok(hres == S_FALSE,
"IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
hres);
IFont_Release(ifnt1);
IFont_Release(ifnt2);
}
static void test_AddRefHfont(void)
{
FONTDESC fd;
IFont* ifnt1 = NULL;
IFont* ifnt2 = NULL;
IFont* ifnt3 = NULL;
HFONT hfnt1 = 0;
HFONT hfnt2 = 0;
HFONT hfnt3 = 0;
HRESULT hres;
/* Basic font description */
fd.cbSizeofstruct = sizeof(FONTDESC);
fd.lpstrName = system_font;
S(fd.cySize).Lo = 100;
S(fd.cySize).Hi = 100;
fd.sWeight = 0;
fd.sCharset = 0;
fd.fItalic = 0;
fd.fUnderline = 0;
fd.fStrikethrough = 0;
/* Create HFONTs and IFONTs */
pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt1);
IFont_get_hFont(ifnt1,&hfnt1);
fd.lpstrName = arial_font;
pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
IFont_get_hFont(ifnt2,&hfnt2);
/* Try invalid HFONT */
hres = IFont_AddRefHfont(ifnt1,NULL);
ok(hres == E_INVALIDARG,
"IFont_AddRefHfont: (Bad HFONT) Expected E_INVALIDARG but got 0x%08x\n",
hres);
/* Try to add a bad HFONT */
hres = IFont_AddRefHfont(ifnt1,(HFONT)32);
ok(hres == S_FALSE,
"IFont_AddRefHfont: (Bad HFONT) Expected S_FALSE but got 0x%08x\n",
hres);
/* Add simple IFONT HFONT pair */
hres = IFont_AddRefHfont(ifnt1,hfnt1);
ok(hres == S_OK,
"IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
hres);
/* IFONT and HFONT do not have to be the same (always looks at HFONT) */
hres = IFont_AddRefHfont(ifnt2,hfnt1);
ok(hres == S_OK,
"IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
hres);
/* Release all hfnt1 refs */
hres = IFont_ReleaseHfont(ifnt1,hfnt1);
ok(hres == S_OK,
"IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
hres);
hres = IFont_ReleaseHfont(ifnt1,hfnt1);
ok(hres == S_OK,
"IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
hres);
hres = IFont_ReleaseHfont(ifnt1,hfnt1);
ok(hres == S_OK,
"IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
hres);
/* Check if hfnt1 is empty */
hres = IFont_ReleaseHfont(ifnt1,hfnt1);
ok(hres == S_FALSE,
"IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
hres);
/* Release all hfnt2 refs */
hres = IFont_ReleaseHfont(ifnt2,hfnt2);
ok(hres == S_OK,
"IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
hres);
/* Check if hfnt2 is empty */
hres = IFont_ReleaseHfont(ifnt2,hfnt2);
ok(hres == S_FALSE,
"IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
hres);
/* Show that releasing an IFONT does not always release it from the HFONT cache. */
IFont_Release(ifnt1);
/* Add a reference for destroyed hfnt1 */
hres = IFont_AddRefHfont(ifnt2,hfnt1);
ok(hres == S_OK,
"IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
hres);
/* Decrement reference for destroyed hfnt1 */
hres = IFont_ReleaseHfont(ifnt2,hfnt1);
ok(hres == S_OK,
"IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
hres);
/* Shows that releasing all IFONT's does clear the HFONT cache. */
IFont_Release(ifnt2);
/* Need to make a new IFONT for testing */
fd.fUnderline = 1;
pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt3);
IFont_get_hFont(ifnt3,&hfnt3);
/* Add a reference for destroyed hfnt1 */
hres = IFont_AddRefHfont(ifnt3,hfnt1);
ok(hres == S_FALSE,
"IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
hres);
/* Decrement reference for destroyed hfnt1 */
hres = IFont_ReleaseHfont(ifnt3,hfnt1);
ok(hres == S_FALSE,
"IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
hres);
IFont_Release(ifnt3);
}
START_TEST(olefont)
{
hOleaut32 = GetModuleHandleA("oleaut32.dll");
pOleCreateFontIndirect = (void*)GetProcAddress(hOleaut32, "OleCreateFontIndirect");
if (!pOleCreateFontIndirect)
{
skip("OleCreateFontIndirect not available\n");
return;
}
test_QueryInterface();
test_type_info();
/* Test various size operations and conversions. */
/* Add more as needed. */
test_ifont_sizes(180000, 0, 72, 2540, -18, "default");
test_ifont_sizes(180000, 0, 144, 2540, -36, "ratio1"); /* change ratio */
test_ifont_sizes(180000, 0, 72, 1270, -36, "ratio2"); /* 2nd part of ratio */
/* These depend on details of how IFont rounds sizes internally. */
test_ifont_sizes(0, 0, 72, 2540, 0, "zero size"); /* zero size */
test_ifont_sizes(186000, 0, 72, 2540, -19, "rounding"); /* test rounding */
test_font_events_disp();
test_GetIDsOfNames();
test_Invoke();
test_IsEqual();
test_ReleaseHfont();
test_AddRefHfont();
}

View file

@ -0,0 +1,799 @@
/*
* OLEPICTURE test program
*
* Copyright 2005 Marcus Meissner
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <time.h>
#define COBJMACROS
#include "wine/test.h"
#include <windef.h>
#include <winbase.h>
#include <winuser.h>
#include <wingdi.h>
#include <winnls.h>
#include <winerror.h>
#include <winnt.h>
#include <wtypes.h>
#include <olectl.h>
#include <objidl.h>
#define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
#define ole_expect(expr, expect) { \
HRESULT r = expr; \
ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
}
#define ole_check(expr) ole_expect(expr, S_OK);
static HMODULE hOleaut32;
static HRESULT (WINAPI *pOleLoadPicture)(LPSTREAM,LONG,BOOL,REFIID,LPVOID*);
static HRESULT (WINAPI *pOleCreatePictureIndirect)(PICTDESC*,REFIID,BOOL,LPVOID*);
#define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
/* 1x1 pixel gif */
static const unsigned char gifimage[35] = {
0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
0x01,0x00,0x3b
};
/* 1x1 pixel jpg */
static const unsigned char jpgimage[285] = {
0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
};
/* 1x1 pixel png */
static const unsigned char pngimage[285] = {
0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
};
/* 1x1 pixel bmp */
static const unsigned char bmpimage[66] = {
0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
0x00,0x00
};
/* 2x2 pixel gif */
static const unsigned char gif4pixel[42] = {
0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
};
/* APM with an empty metafile with some padding zeros - looks like under Window the
* metafile data should be at least 20 bytes */
static const unsigned char apmdata[] = {
0xd7,0xcd,0xc6,0x9a, 0x00,0x00,0x00,0x00, 0x00,0x00,0xee,0x02, 0xb1,0x03,0xa0,0x05,
0x00,0x00,0x00,0x00, 0xee,0x53,0x01,0x00, 0x09,0x00,0x00,0x03, 0x13,0x00,0x00,0x00,
0x01,0x00,0x05,0x00, 0x00,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00
};
struct NoStatStreamImpl
{
const IStreamVtbl *lpVtbl;
LONG ref;
HGLOBAL supportHandle;
ULARGE_INTEGER streamSize;
ULARGE_INTEGER currentPosition;
};
typedef struct NoStatStreamImpl NoStatStreamImpl;
static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal);
static void
test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
{
IPicture* pic = NULL;
HRESULT hres;
LPVOID pvObj = NULL;
OLE_HANDLE handle, hPal;
OLE_XSIZE_HIMETRIC width;
OLE_YSIZE_HIMETRIC height;
short type;
DWORD attr;
ULONG res;
pvObj = NULL;
hres = pOleLoadPicture(stream, imgsize, TRUE, &IID_IPicture, &pvObj);
pic = pvObj;
ok(hres == S_OK,"OLP (NULL,..) does not return 0, but 0x%08x\n",hres);
ok(pic != NULL,"OLP (NULL,..) returns NULL, instead of !NULL\n");
if (pic == NULL)
return;
pvObj = NULL;
hres = IPicture_QueryInterface (pic, &IID_IPicture, &pvObj);
ok(hres == S_OK,"IPicture_QI does not return S_OK, but 0x%08x\n", hres);
ok(pvObj != NULL,"IPicture_QI does return NULL, instead of a ptr\n");
IPicture_Release ((IPicture*)pvObj);
handle = 0;
hres = IPicture_get_Handle (pic, &handle);
ok(hres == S_OK,"IPicture_get_Handle does not return S_OK, but 0x%08x\n", hres);
ok(handle != 0, "IPicture_get_Handle returns a NULL handle, but it should be non NULL\n");
width = 0;
hres = IPicture_get_Width (pic, &width);
ok(hres == S_OK,"IPicture_get_Width does not return S_OK, but 0x%08x\n", hres);
ok(width != 0, "IPicture_get_Width returns 0, but it should not be 0.\n");
height = 0;
hres = IPicture_get_Height (pic, &height);
ok(hres == S_OK,"IPicture_get_Height does not return S_OK, but 0x%08x\n", hres);
ok(height != 0, "IPicture_get_Height returns 0, but it should not be 0.\n");
type = 0;
hres = IPicture_get_Type (pic, &type);
ok(hres == S_OK,"IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
ok(type == PICTYPE_BITMAP, "IPicture_get_Type returns %d, but it should be PICTYPE_BITMAP(%d).\n", type, PICTYPE_BITMAP);
attr = 0;
hres = IPicture_get_Attributes (pic, &attr);
ok(hres == S_OK,"IPicture_get_Attributes does not return S_OK, but 0x%08x\n", hres);
ok(attr == 0, "IPicture_get_Attributes returns %d, but it should be 0.\n", attr);
hPal = 0;
hres = IPicture_get_hPal (pic, &hPal);
ok(hres == S_OK,"IPicture_get_hPal does not return S_OK, but 0x%08x\n", hres);
/* a single pixel b/w image has no palette */
ok(hPal == 0, "IPicture_get_hPal returns %d, but it should be 0.\n", hPal);
res = IPicture_Release (pic);
ok (res == 0, "refcount after release is %d, but should be 0?\n", res);
}
static void
test_pic(const unsigned char *imgdata, unsigned int imgsize)
{
LPSTREAM stream;
HGLOBAL hglob;
LPBYTE data;
HRESULT hres;
LARGE_INTEGER seekto;
ULARGE_INTEGER newpos1;
DWORD * header;
unsigned int i,j;
/* Let the fun begin */
hglob = GlobalAlloc (0, imgsize);
data = GlobalLock (hglob);
memcpy(data, imgdata, imgsize);
GlobalUnlock(hglob); data = NULL;
hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
memset(&seekto,0,sizeof(seekto));
hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
test_pic_with_stream(stream, imgsize);
IStream_Release(stream);
/* again with Non Statable and Non Seekable stream */
stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
hglob = 0; /* Non-statable impl always deletes on release */
test_pic_with_stream(stream, 0);
IStream_Release(stream);
for (i = 1; i <= 8; i++) {
/* more fun!!! */
hglob = GlobalAlloc (0, imgsize + i * (2 * sizeof(DWORD)));
data = GlobalLock (hglob);
header = (DWORD *)data;
/* multiple copies of header */
memcpy(data,"lt\0\0",4);
header[1] = imgsize;
for (j = 2; j <= i; j++) {
memcpy(&(header[2 * (j - 1)]), header, 2 * sizeof(DWORD));
}
memcpy(data + i * (2 * sizeof(DWORD)), imgdata, imgsize);
GlobalUnlock(hglob); data = NULL;
hres = CreateStreamOnHGlobal (hglob, FALSE, &stream);
ok (hres == S_OK, "createstreamonhglobal failed? doubt it... hres 0x%08x\n", hres);
memset(&seekto,0,sizeof(seekto));
hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
test_pic_with_stream(stream, imgsize);
IStream_Release(stream);
/* again with Non Statable and Non Seekable stream */
stream = (LPSTREAM)NoStatStreamImpl_Construct(hglob);
hglob = 0; /* Non-statable impl always deletes on release */
test_pic_with_stream(stream, 0);
IStream_Release(stream);
}
}
static void test_empty_image(void) {
LPBYTE data;
LPSTREAM stream;
IPicture* pic = NULL;
HRESULT hres;
LPVOID pvObj = NULL;
HGLOBAL hglob;
OLE_HANDLE handle;
ULARGE_INTEGER newpos1;
LARGE_INTEGER seekto;
short type;
/* Empty image. Happens occasionally in VB programs. */
hglob = GlobalAlloc (0, 8);
data = GlobalLock (hglob);
memcpy(data,"lt\0\0",4);
((DWORD*)data)[1] = 0;
hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
memset(&seekto,0,sizeof(seekto));
hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
pvObj = NULL;
hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
pic = pvObj;
ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
hres = IPicture_get_Type (pic, &type);
ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
hres = IPicture_get_Handle (pic, &handle);
ok (hres == S_OK,"empty picture get handle failed with hres 0x%08x\n", hres);
ok (handle == 0, "empty picture get handle did not return 0, but 0x%08x\n", handle);
IPicture_Release (pic);
}
static void test_empty_image_2(void) {
LPBYTE data;
LPSTREAM stream;
IPicture* pic = NULL;
HRESULT hres;
LPVOID pvObj = NULL;
HGLOBAL hglob;
ULARGE_INTEGER newpos1;
LARGE_INTEGER seekto;
short type;
/* Empty image at random stream position. */
hglob = GlobalAlloc (0, 200);
data = GlobalLock (hglob);
data += 42;
memcpy(data,"lt\0\0",4);
((DWORD*)data)[1] = 0;
hres = CreateStreamOnHGlobal (hglob, TRUE, &stream);
ok (hres == S_OK, "CreatestreamOnHGlobal failed? doubt it... hres 0x%08x\n", hres);
memset(&seekto,0,sizeof(seekto));
seekto.u.LowPart = 42;
hres = IStream_Seek(stream,seekto,SEEK_CUR,&newpos1);
ok (hres == S_OK, "istream seek failed? doubt it... hres 0x%08x\n", hres);
pvObj = NULL;
hres = pOleLoadPicture(stream, 8, TRUE, &IID_IPicture, &pvObj);
pic = pvObj;
ok(hres == S_OK,"empty picture not loaded, hres 0x%08x\n", hres);
ok(pic != NULL,"empty picture not loaded, pic is NULL\n");
hres = IPicture_get_Type (pic, &type);
ok (hres == S_OK,"empty picture get type failed with hres 0x%08x\n", hres);
ok (type == PICTYPE_NONE,"type is %d, but should be PICTYPE_NONE(0)\n", type);
IPicture_Release (pic);
}
static void test_Invoke(void)
{
IPictureDisp *picdisp;
HRESULT hr;
VARIANTARG vararg;
DISPPARAMS dispparams;
VARIANT varresult;
IStream *stream;
HGLOBAL hglob;
void *data;
hglob = GlobalAlloc (0, sizeof(gifimage));
data = GlobalLock(hglob);
memcpy(data, gifimage, sizeof(gifimage));
GlobalUnlock(hglob);
hr = CreateStreamOnHGlobal (hglob, FALSE, &stream);
ok_ole_success(hr, "CreateStreamOnHGlobal");
hr = pOleLoadPicture(stream, sizeof(gifimage), TRUE, &IID_IPictureDisp, (void **)&picdisp);
IStream_Release(stream);
ok_ole_success(hr, "OleLoadPicture");
V_VT(&vararg) = VT_BOOL;
V_BOOL(&vararg) = VARIANT_FALSE;
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
dispparams.cArgs = 1;
dispparams.rgvarg = &vararg;
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IPictureDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
ok(hr == DISP_E_UNKNOWNNAME, "IPictureDisp_Invoke should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n", hr);
dispparams.cArgs = 0;
dispparams.rgvarg = NULL;
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
ok(hr == DISP_E_PARAMNOTOPTIONAL, "IPictureDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
ok_ole_success(hr, "IPictureDisp_Invoke");
ok(V_VT(&varresult) == VT_I4, "V_VT(&varresult) should have been VT_UINT instead of %d\n", V_VT(&varresult));
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
hr = IPictureDisp_Invoke(picdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
ok(hr == DISP_E_MEMBERNOTFOUND, "IPictureDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
dispparams.cArgs = 1;
dispparams.rgvarg = &vararg;
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
dispparams.cArgs = 1;
dispparams.rgvarg = &vararg;
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
IPictureDisp_Release(picdisp);
}
static void test_OleCreatePictureIndirect(void)
{
IPicture *pict;
HRESULT hr;
short type;
OLE_HANDLE handle;
if(!pOleCreatePictureIndirect)
{
skip("Skipping OleCreatePictureIndirect tests\n");
return;
}
hr = pOleCreatePictureIndirect(NULL, &IID_IPicture, TRUE, (void**)&pict);
ok(hr == S_OK, "hr %08x\n", hr);
hr = IPicture_get_Type(pict, &type);
ok(hr == S_OK, "hr %08x\n", hr);
ok(type == PICTYPE_UNINITIALIZED, "type %d\n", type);
hr = IPicture_get_Handle(pict, &handle);
ok(hr == S_OK, "hr %08x\n", hr);
ok(handle == 0, "handle %08x\n", handle);
IPicture_Release(pict);
}
static void test_apm()
{
OLE_HANDLE handle;
LPSTREAM stream;
IPicture *pict;
HGLOBAL hglob;
LPBYTE *data;
LONG cxy;
BOOL keep;
short type;
hglob = GlobalAlloc (0, sizeof(apmdata));
data = GlobalLock(hglob);
memcpy(data, apmdata, sizeof(apmdata));
ole_check(CreateStreamOnHGlobal(hglob, TRUE, &stream));
ole_check(OleLoadPictureEx(stream, sizeof(apmdata), TRUE, &IID_IPicture, 100, 100, 0, (LPVOID *)&pict));
ole_check(IPicture_get_Handle(pict, &handle));
ok(handle != 0, "handle is null\n");
ole_check(IPicture_get_Type(pict, &type));
expect_eq(type, PICTYPE_METAFILE, short, "%d");
ole_check(IPicture_get_Height(pict, &cxy));
expect_eq(cxy, 1667, LONG, "%d");
ole_check(IPicture_get_Width(pict, &cxy));
expect_eq(cxy, 1323, LONG, "%d");
ole_check(IPicture_get_KeepOriginalFormat(pict, &keep));
todo_wine expect_eq(keep, FALSE, LONG, "%d");
ole_expect(IPicture_get_hPal(pict, &handle), E_FAIL);
IPicture_Release(pict);
IStream_Release(stream);
}
START_TEST(olepicture)
{
hOleaut32 = GetModuleHandleA("oleaut32.dll");
pOleLoadPicture = (void*)GetProcAddress(hOleaut32, "OleLoadPicture");
pOleCreatePictureIndirect = (void*)GetProcAddress(hOleaut32, "OleCreatePictureIndirect");
if (!pOleLoadPicture)
{
skip("OleLoadPicture is not available\n");
return;
}
/* Test regular 1x1 pixel images of gif, jpg, bmp type */
test_pic(gifimage, sizeof(gifimage));
test_pic(jpgimage, sizeof(jpgimage));
test_pic(bmpimage, sizeof(bmpimage));
test_pic(gif4pixel, sizeof(gif4pixel));
/* FIXME: No PNG support yet in Wine or in older Windows... */
if (0) test_pic(pngimage, sizeof(pngimage));
test_empty_image();
test_empty_image_2();
test_apm();
test_Invoke();
test_OleCreatePictureIndirect();
}
/* Helper functions only ... */
static void NoStatStreamImpl_Destroy(NoStatStreamImpl* This)
{
GlobalFree(This->supportHandle);
This->supportHandle=0;
HeapFree(GetProcessHeap(), 0, This);
}
static ULONG WINAPI NoStatStreamImpl_AddRef(
IStream* iface)
{
NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
return InterlockedIncrement(&This->ref);
}
static HRESULT WINAPI NoStatStreamImpl_QueryInterface(
IStream* iface,
REFIID riid, /* [in] */
void** ppvObject) /* [iid_is][out] */
{
NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
if (ppvObject==0) return E_INVALIDARG;
*ppvObject = 0;
if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
{
*ppvObject = (IStream*)This;
}
else if (memcmp(&IID_IStream, riid, sizeof(IID_IStream)) == 0)
{
*ppvObject = (IStream*)This;
}
if ((*ppvObject)==0)
return E_NOINTERFACE;
NoStatStreamImpl_AddRef(iface);
return S_OK;
}
static ULONG WINAPI NoStatStreamImpl_Release(
IStream* iface)
{
NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
ULONG newRef = InterlockedDecrement(&This->ref);
if (newRef==0)
NoStatStreamImpl_Destroy(This);
return newRef;
}
static HRESULT WINAPI NoStatStreamImpl_Read(
IStream* iface,
void* pv, /* [length_is][size_is][out] */
ULONG cb, /* [in] */
ULONG* pcbRead) /* [out] */
{
NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
void* supportBuffer;
ULONG bytesReadBuffer;
ULONG bytesToReadFromBuffer;
if (pcbRead==0)
pcbRead = &bytesReadBuffer;
bytesToReadFromBuffer = min( This->streamSize.u.LowPart - This->currentPosition.u.LowPart, cb);
supportBuffer = GlobalLock(This->supportHandle);
memcpy(pv, (char *) supportBuffer+This->currentPosition.u.LowPart, bytesToReadFromBuffer);
This->currentPosition.u.LowPart+=bytesToReadFromBuffer;
*pcbRead = bytesToReadFromBuffer;
GlobalUnlock(This->supportHandle);
if(*pcbRead == cb)
return S_OK;
return S_FALSE;
}
static HRESULT WINAPI NoStatStreamImpl_Write(
IStream* iface,
const void* pv, /* [size_is][in] */
ULONG cb, /* [in] */
ULONG* pcbWritten) /* [out] */
{
NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
void* supportBuffer;
ULARGE_INTEGER newSize;
ULONG bytesWritten = 0;
if (pcbWritten == 0)
pcbWritten = &bytesWritten;
if (cb == 0)
return S_OK;
newSize.u.HighPart = 0;
newSize.u.LowPart = This->currentPosition.u.LowPart + cb;
if (newSize.u.LowPart > This->streamSize.u.LowPart)
IStream_SetSize(iface, newSize);
supportBuffer = GlobalLock(This->supportHandle);
memcpy((char *) supportBuffer+This->currentPosition.u.LowPart, pv, cb);
This->currentPosition.u.LowPart+=cb;
*pcbWritten = cb;
GlobalUnlock(This->supportHandle);
return S_OK;
}
static HRESULT WINAPI NoStatStreamImpl_Seek(
IStream* iface,
LARGE_INTEGER dlibMove, /* [in] */
DWORD dwOrigin, /* [in] */
ULARGE_INTEGER* plibNewPosition) /* [out] */
{
NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
ULARGE_INTEGER newPosition;
switch (dwOrigin)
{
case STREAM_SEEK_SET:
newPosition.u.HighPart = 0;
newPosition.u.LowPart = 0;
break;
case STREAM_SEEK_CUR:
newPosition = This->currentPosition;
break;
case STREAM_SEEK_END:
newPosition = This->streamSize;
break;
default:
return STG_E_INVALIDFUNCTION;
}
if (dlibMove.QuadPart < 0 && newPosition.QuadPart < -dlibMove.QuadPart)
return STG_E_INVALIDFUNCTION;
newPosition.QuadPart += dlibMove.QuadPart;
if (plibNewPosition) *plibNewPosition = newPosition;
This->currentPosition = newPosition;
return S_OK;
}
static HRESULT WINAPI NoStatStreamImpl_SetSize(
IStream* iface,
ULARGE_INTEGER libNewSize) /* [in] */
{
NoStatStreamImpl* const This=(NoStatStreamImpl*)iface;
HGLOBAL supportHandle;
if (libNewSize.u.HighPart != 0)
return STG_E_INVALIDFUNCTION;
if (This->streamSize.u.LowPart == libNewSize.u.LowPart)
return S_OK;
supportHandle = GlobalReAlloc(This->supportHandle, libNewSize.u.LowPart, 0);
if (supportHandle == 0)
return STG_E_MEDIUMFULL;
This->supportHandle = supportHandle;
This->streamSize.u.LowPart = libNewSize.u.LowPart;
return S_OK;
}
static HRESULT WINAPI NoStatStreamImpl_CopyTo(
IStream* iface,
IStream* pstm, /* [unique][in] */
ULARGE_INTEGER cb, /* [in] */
ULARGE_INTEGER* pcbRead, /* [out] */
ULARGE_INTEGER* pcbWritten) /* [out] */
{
HRESULT hr = S_OK;
BYTE tmpBuffer[128];
ULONG bytesRead, bytesWritten, copySize;
ULARGE_INTEGER totalBytesRead;
ULARGE_INTEGER totalBytesWritten;
if ( pstm == 0 )
return STG_E_INVALIDPOINTER;
totalBytesRead.u.LowPart = totalBytesRead.u.HighPart = 0;
totalBytesWritten.u.LowPart = totalBytesWritten.u.HighPart = 0;
while ( cb.u.LowPart > 0 )
{
if ( cb.u.LowPart >= 128 )
copySize = 128;
else
copySize = cb.u.LowPart;
IStream_Read(iface, tmpBuffer, copySize, &bytesRead);
totalBytesRead.u.LowPart += bytesRead;
IStream_Write(pstm, tmpBuffer, bytesRead, &bytesWritten);
totalBytesWritten.u.LowPart += bytesWritten;
if (bytesRead != bytesWritten)
{
hr = STG_E_MEDIUMFULL;
break;
}
if (bytesRead!=copySize)
cb.u.LowPart = 0;
else
cb.u.LowPart -= bytesRead;
}
if (pcbRead)
{
pcbRead->u.LowPart = totalBytesRead.u.LowPart;
pcbRead->u.HighPart = totalBytesRead.u.HighPart;
}
if (pcbWritten)
{
pcbWritten->u.LowPart = totalBytesWritten.u.LowPart;
pcbWritten->u.HighPart = totalBytesWritten.u.HighPart;
}
return hr;
}
static HRESULT WINAPI NoStatStreamImpl_Commit(IStream* iface,DWORD grfCommitFlags)
{
return S_OK;
}
static HRESULT WINAPI NoStatStreamImpl_Revert(IStream* iface) { return S_OK; }
static HRESULT WINAPI NoStatStreamImpl_LockRegion(
IStream* iface,
ULARGE_INTEGER libOffset, /* [in] */
ULARGE_INTEGER cb, /* [in] */
DWORD dwLockType) /* [in] */
{
return S_OK;
}
static HRESULT WINAPI NoStatStreamImpl_UnlockRegion(
IStream* iface,
ULARGE_INTEGER libOffset, /* [in] */
ULARGE_INTEGER cb, /* [in] */
DWORD dwLockType) /* [in] */
{
return S_OK;
}
static HRESULT WINAPI NoStatStreamImpl_Stat(
IStream* iface,
STATSTG* pstatstg, /* [out] */
DWORD grfStatFlag) /* [in] */
{
return E_NOTIMPL;
}
static HRESULT WINAPI NoStatStreamImpl_Clone(
IStream* iface,
IStream** ppstm) /* [out] */
{
return E_NOTIMPL;
}
static const IStreamVtbl NoStatStreamImpl_Vtbl;
/*
Build an object that implements IStream, without IStream_Stat capabilities.
Receives a memory handle with data buffer. If memory handle is non-null,
it is assumed to be unlocked, otherwise an internal memory handle is allocated.
In any case the object takes ownership of memory handle and will free it on
object release.
*/
static NoStatStreamImpl* NoStatStreamImpl_Construct(HGLOBAL hGlobal)
{
NoStatStreamImpl* newStream;
newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(NoStatStreamImpl));
if (newStream!=0)
{
newStream->lpVtbl = &NoStatStreamImpl_Vtbl;
newStream->ref = 1;
newStream->supportHandle = hGlobal;
if (!newStream->supportHandle)
newStream->supportHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD |
GMEM_SHARE, 0);
newStream->currentPosition.u.HighPart = 0;
newStream->currentPosition.u.LowPart = 0;
newStream->streamSize.u.HighPart = 0;
newStream->streamSize.u.LowPart = GlobalSize(newStream->supportHandle);
}
return newStream;
}
static const IStreamVtbl NoStatStreamImpl_Vtbl =
{
NoStatStreamImpl_QueryInterface,
NoStatStreamImpl_AddRef,
NoStatStreamImpl_Release,
NoStatStreamImpl_Read,
NoStatStreamImpl_Write,
NoStatStreamImpl_Seek,
NoStatStreamImpl_SetSize,
NoStatStreamImpl_CopyTo,
NoStatStreamImpl_Commit,
NoStatStreamImpl_Revert,
NoStatStreamImpl_LockRegion,
NoStatStreamImpl_UnlockRegion,
NoStatStreamImpl_Stat,
NoStatStreamImpl_Clone
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
/*
* ITypeLib test IDL - we dump it and compare results in typelib.c
*
* Copyright 2007 Google (Mikolaj Zalewski)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
import "oaidl.idl"; /* needed by widl */
[uuid(8b05fe77-4a6c-4133-b9cd-8f81747af784)]
library Test
{
importlib("stdole2.tlb");
[dual,uuid(b14b6bb5-904e-4ff9-b247-bd361f7aaedd)]
interface IDualIface : IDispatch
{
HRESULT test();
}
[uuid(ec5dfcd6-eeb0-4cd6-b51e-8030e1dac009)]
interface ISimpleIface : IDispatch
{
HRESULT test();
}
}

View file

@ -0,0 +1,31 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_olefont(void);
extern void func_olepicture(void);
extern void func_safearray(void);
extern void func_tmarshal(void);
extern void func_typelib(void);
extern void func_usrmarshal(void);
extern void func_varformat(void);
extern void func_vartest(void);
extern void func_vartype(void);
const struct test winetest_testlist[] =
{
{ "olefont", func_olefont },
{ "olepicture", func_olepicture },
{ "safearray", func_safearray },
{ "tmarshal", func_tmarshal },
{ "typelib", func_typelib },
{ "usrmarshal", func_usrmarshal },
{ "varformat", func_varformat },
{ "vartest", func_vartest },
{ "vartype", func_vartype },
{ 0, 0 }
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,286 @@
/*
* Copyright (C) 2005 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#include "tmarshal_dispids.h"
import "ocidl.idl";
[
uuid(d96d8a3e-78b6-4c8d-8f27-059db959be8a),
version(1.0),
helpstring("Test Typelib")
]
library TestTypelib
{
importlib("stdole2.tlb");
typedef enum tagSTATE
{
STATE_UNWIDGETIFIED = 1,
STATE_WIDGETIFIED
} STATE;
coclass ApplicationObject2;
[
odl,
uuid(12345678-1234-4321-1234-121212121212)
]
interface ISomethingFromDispatch : IDispatch
{
HRESULT anotherfn(void);
}
[
odl,
uuid(a1f8cae3-c947-4c5f-b57d-c87b9b5f3586),
oleautomation,
dual
]
interface IWidget : IDispatch
{
[propput, id(DISPID_TM_NAME)]
HRESULT Name([in] BSTR name);
[propget, id(DISPID_TM_NAME)]
HRESULT Name([out, retval] BSTR *name);
[id(DISPID_TM_DOSOMETHING)]
HRESULT DoSomething([in] double number, [out] BSTR *str1, [in, defaultvalue("")] BSTR str2, [in, optional] VARIANT *opt);
[propget, id(DISPID_TM_STATE)]
HRESULT State([out, retval] STATE *state);
[propput, id(DISPID_TM_STATE)]
HRESULT State([in] STATE state);
[id(DISPID_TM_MAP)]
HRESULT Map([in] BSTR bstrId, [out, retval] BSTR *sValue);
[id(DISPID_TM_SETOLECOLOR)]
HRESULT SetOleColor([in] OLE_COLOR val);
[id(DISPID_TM_GETOLECOLOR)]
HRESULT GetOleColor([out, retval] OLE_COLOR *pVal);
[propget, id(DISPID_TM_CLONE)]
HRESULT Clone([out, retval] IWidget **ppVal);
[propget, id(DISPID_TM_CLONEDISPATCH)]
HRESULT CloneDispatch([out, retval] IDispatch **ppVal);
[propget, id(DISPID_TM_CLONECOCLASS)]
HRESULT CloneCoclass([out, retval] ApplicationObject2 **ppVal);
[propget, id(DISPID_VALUE)]
HRESULT Value([in] VARIANT *value, [out, retval] VARIANT *retval);
[id(DISPID_TM_ARRAY)]
HRESULT Array([in] SAFEARRAY(BSTR) values);
[id(DISPID_TM_VARARRAYPTR)]
HRESULT VariantArrayPtr([in] SAFEARRAY(VARIANT) *values);
[id(DISPID_TM_VARIANT)]
void Variant([in] VARIANT var);
[vararg, id(DISPID_TM_VARARG)]
void VarArg([in] int numexpect, [in] SAFEARRAY(VARIANT) values);
[id(DISPID_TM_ERROR)]
HRESULT Error();
[propget, id(DISPID_TM_CLONEINTERFACE)]
HRESULT CloneInterface([out, retval] ISomethingFromDispatch **ppVal);
}
[
odl,
uuid(a028db05-30f0-4b93-b17a-41c72f831d84),
#if 0 /* FIXME: commented out as causes widl to generate incorrect typelib */
dual,
#endif
oleautomation
]
interface IKindaEnumWidget : IUnknown
{
HRESULT Next(
[out] IWidget **widget);
HRESULT Count(
[out] unsigned long *count);
HRESULT Reset();
HRESULT Clone(
[out] IKindaEnumWidget **ppenum);
}
[
odl,
uuid(a028db06-30f0-4b93-b17a-41c72f831d84),
]
interface INonOleAutomation : IUnknown
{
[id(DISPID_NOA_BSTRRET)]
BSTR BstrRet();
}
[
dllname("comm.drv"),
uuid(d377f60b-8639-4261-8ee7-75c8340d2cc9),
]
module BadModule
{
[
entry("Foo"),
]
HRESULT BadModuleFoo();
};
[
dllname("oleaut32.dll"),
uuid(d377f60c-8639-4261-8ee7-75c8340d2cc9),
]
module BadEntry
{
[
entry("Foo"),
]
HRESULT BadEntryFoo();
};
[
uuid(bb171948-10ec-407a-9a57-2f85f797ff1a),
appobject,
]
coclass ApplicationObject2
{
interface IWidget;
[source] interface IWidget;
};
[
odl,
uuid(375f8a9d-33d0-44f3-b972-61f8407899e0)
]
interface ItestIF1 : IUnknown
{
HRESULT fn1([in] int x);
HRESULT fn2([out,retval] int *x);
}
[
odl,
uuid(094056a3-666f-4956-be12-1859668310b8)
]
interface ItestIF2 : ItestIF1
{
HRESULT fn3([in] int y);
}
[
odl,
uuid(33baba09-2e68-43ab-81fe-d84b403df2e5)
]
dispinterface ItestIF3
{
interface ItestIF2;
}
[
odl,
uuid(a01005c7-7491-42eb-94f3-668e37ce60a6)
]
dispinterface ItestIF4
{
properties:
methods:
[id(0x1c)] HRESULT fn([in] int z);
}
[
odl,
uuid(4ab61e25-c09f-4239-8f7f-7a018ea0199f),
dual
]
interface ItestIF5 : ItestIF2
{
[id(0x1234)] HRESULT fn4([in] int a);
[id(0x1235)] HRESULT fn5([in] int a);
}
[
odl,
uuid(ec236d8e-2cc7-44f2-b394-36c86ff3da74)
]
interface ItestIF6 : IDispatch
{
[id(0x1234)] HRESULT fn4([in] int a);
[id(0x1235)] HRESULT fn5([in] int a);
}
[
odl,
uuid(f711b105-554d-4751-818c-46fcc5d7c0d5),
dual
]
interface ItestIF7 : ItestIF6
{
[id(0x1236)] HRESULT fn6([in] int a);
}
[
odl,
uuid(bdfa260b-ef40-43d3-b071-cddec919f132)
]
interface ItestIF8
{
HRESULT fn1([in] int x);
HRESULT fn2([out,retval] int *x);
}
[
odl,
uuid(51033a23-dc37-4f19-aa34-4d8a670458a0)
]
interface ItestIF9 : ItestIF8
{
HRESULT fn3([in] int y);
}
[
odl,
uuid(2e8f14fe-0bce-42f0-8b7d-3af8393c7967)
]
dispinterface ItestIF10
{
interface ItestIF9;
}
[
odl,
uuid(7d9e9371-482e-4944-9b19-511fc705236f)
]
dispinterface ItestIF11
{
interface ItestIF7;
}
};

View file

@ -0,0 +1,30 @@
/*
* Resource file for tmarshaltest
*
* Copyright 2005 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winnls.h"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#include "wine/wine_common_ver.rc"
1 TYPELIB LOADONCALL DISCARDABLE tmarshal.tlb

View file

@ -0,0 +1,36 @@
/*
* Copyright (C) 2005-2006 Robert Shearman for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#define DISPID_TM_NAME 1
#define DISPID_TM_DOSOMETHING 2
#define DISPID_TM_STATE 3
#define DISPID_TM_MAP 4
#define DISPID_TM_SETOLECOLOR 5
#define DISPID_TM_GETOLECOLOR 6
#define DISPID_TM_CLONE 7
#define DISPID_TM_CLONEDISPATCH 8
#define DISPID_TM_CLONECOCLASS 9
#define DISPID_TM_ARRAY 10
#define DISPID_TM_VARARRAYPTR 11
#define DISPID_TM_VARIANT 12
#define DISPID_TM_VARARG 13
#define DISPID_TM_ERROR 14
#define DISPID_TM_CLONEINTERFACE 15
#define DISPID_NOA_BSTRRET 1

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,401 @@
/*
* VARFORMAT test program
*
* Copyright 1998 Jean-Claude Cote
* Copyright 2006 Google (Benjamin Arai)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <time.h>
#include "windef.h"
#include "winbase.h"
#include "winsock.h"
#include "wine/test.h"
#include "winuser.h"
#include "wingdi.h"
#include "winnls.h"
#include "winerror.h"
#include "winnt.h"
#include "wtypes.h"
#include "oleauto.h"
static HMODULE hOleaut32;
static HRESULT (WINAPI *pVarFormatNumber)(LPVARIANT,int,int,int,int,ULONG,BSTR*);
static HRESULT (WINAPI *pVarFormat)(LPVARIANT,LPOLESTR,int,int,ULONG,BSTR*);
/* Have I8/UI8 data type? */
#define HAVE_OLEAUT32_I8 HAVE_FUNC(VarI8FromI1)
/* Is a given function exported from oleaut32? */
#define HAVE_FUNC(func) ((void*)GetProcAddress(hOleaut32, #func) != NULL)
/* Get a conversion function ptr, return if function not available */
#define CHECKPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func); \
if (!p##func) { trace("function " # func " not available, not testing it\n"); return; }
static inline int strcmpW( const WCHAR *str1, const WCHAR *str2 )
{
while (*str1 && (*str1 == *str2)) { str1++; str2++; }
return *str1 - *str2;
}
#define FMT_NUMBER(vt,val) \
VariantInit(&v); V_VT(&v) = vt; val(&v) = 1; \
hres = pVarFormatNumber(&v,2,0,0,0,0,&str); \
ok(hres == S_OK, "VarFormatNumber (vt %d): returned %8x\n", vt, hres); \
if (hres == S_OK) \
ok(str && strcmpW(str,szResult1) == 0, \
"VarFormatNumber (vt %d): string different\n", vt)
static void test_VarFormatNumber(void)
{
static const WCHAR szSrc1[] = { '1','\0' };
static const WCHAR szResult1[] = { '1','.','0','0','\0' };
static const WCHAR szSrc2[] = { '-','1','\0' };
static const WCHAR szResult2[] = { '(','1','.','0','0',')','\0' };
char buff[8];
HRESULT hres;
VARIANT v;
BSTR str = NULL;
CHECKPTR(VarFormatNumber);
GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buff, sizeof(buff)/sizeof(char));
if (buff[0] != '.' || buff[1])
{
skip("Skipping VarFormatNumber tests as decimal separator is '%s'\n", buff);
return;
}
FMT_NUMBER(VT_I1, V_I1);
FMT_NUMBER(VT_UI1, V_UI1);
FMT_NUMBER(VT_I2, V_I2);
FMT_NUMBER(VT_UI2, V_UI2);
FMT_NUMBER(VT_I4, V_I4);
FMT_NUMBER(VT_UI4, V_UI4);
if (HAVE_OLEAUT32_I8)
{
FMT_NUMBER(VT_I8, V_I8);
FMT_NUMBER(VT_UI8, V_UI8);
}
FMT_NUMBER(VT_R4, V_R4);
FMT_NUMBER(VT_R8, V_R8);
FMT_NUMBER(VT_BOOL, V_BOOL);
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = SysAllocString(szSrc1);
hres = pVarFormatNumber(&v,2,0,0,0,0,&str);
ok(hres == S_OK, "VarFormatNumber (bstr): returned %8x\n", hres);
if (hres == S_OK)
ok(str && strcmpW(str, szResult1) == 0, "VarFormatNumber (bstr): string different\n");
SysFreeString(V_BSTR(&v));
SysFreeString(str);
V_BSTR(&v) = SysAllocString(szSrc2);
hres = pVarFormatNumber(&v,2,0,-1,0,0,&str);
ok(hres == S_OK, "VarFormatNumber (bstr): returned %8x\n", hres);
if (hres == S_OK)
ok(str && strcmpW(str, szResult2) == 0, "VarFormatNumber (-bstr): string different\n");
SysFreeString(V_BSTR(&v));
SysFreeString(str);
}
#define SIGNED_VTBITS (VTBIT_I1|VTBIT_I2|VTBIT_I4|VTBIT_I8|VTBIT_R4|VTBIT_R8)
static const char *szVarFmtFail = "VT %d|0x%04x Format %s: expected 0x%08x, '%s', got 0x%08x, '%s'\n";
#define VARFMT(vt,v,val,fmt,ret,str) do { \
if (out) SysFreeString(out); out = NULL; \
V_VT(&in) = (vt); v(&in) = val; \
if (fmt) MultiByteToWideChar(CP_ACP, 0, fmt, -1, buffW, sizeof(buffW)/sizeof(WCHAR)); \
hres = pVarFormat(&in,fmt ? buffW : NULL,fd,fw,flags,&out); \
if (SUCCEEDED(hres)) WideCharToMultiByte(CP_ACP, 0, out, -1, buff, sizeof(buff),0,0); \
else buff[0] = '\0'; \
ok(hres == ret && (FAILED(ret) || !strcmp(buff, str)), \
szVarFmtFail, \
(vt)&VT_TYPEMASK,(vt)&~VT_TYPEMASK,fmt?fmt:"<null>",ret,str,hres,buff); \
} while(0)
typedef struct tagFMTRES
{
LPCSTR fmt;
LPCSTR one_res;
LPCSTR zero_res;
} FMTRES;
static const FMTRES VarFormat_results[] =
{
{ NULL, "1", "0" },
{ "", "1", "0" },
{ "General Number", "1", "0" },
{ "Percent", "100.00%", "0.00%" },
{ "Standard", "1.00", "0.00" },
{ "Scientific","1.00E+00", "0.00E+00" },
{ "True/False", "True", "False" },
{ "On/Off", "On", "Off" },
{ "Yes/No", "Yes", "No" },
{ "#", "1", "" },
{ "##", "1", "" },
{ "#.#", "1.", "." },
{ "0", "1", "0" },
{ "00", "01", "00" },
{ "0.0", "1.0", "0.0" },
{ "00\\c\\o\\p\\y", "01copy","00copy" },
{ "\"pos\";\"neg\"", "pos", "pos" },
{ "\"pos\";\"neg\";\"zero\"","pos", "zero" }
};
typedef struct tagFMTDATERES
{
DATE val;
LPCSTR fmt;
LPCSTR res;
} FMTDATERES;
static const FMTDATERES VarFormat_date_results[] =
{
{ 0.0, "w", "7" },
{ 0.0, "w", "6" },
{ 0.0, "w", "5" },
{ 0.0, "w", "4" },
{ 0.0, "w", "3" },
{ 0.0, "w", "2" },
{ 0.0, "w", "1" }, /* First 7 entries must remain in this order! */
{ 2.525, "am/pm", "pm" },
{ 2.525, "AM/PM", "PM" },
{ 2.525, "A/P", "P" },
{ 2.525, "a/p", "p" },
{ 2.525, "q", "1" },
{ 2.525, "d", "1" },
{ 2.525, "dd", "01" },
{ 2.525, "ddd", "Mon" },
{ 2.525, "dddd", "Monday" },
{ 2.525, "mmm", "Jan" },
{ 2.525, "mmmm", "January" },
{ 2.525, "y", "1" },
{ 2.525, "yy", "00" },
{ 2.525, "yyy", "001" },
{ 2.525, "yyyy", "1900" },
{ 2.525, "dd mm yyyy hh:mm:ss", "01 01 1900 12:36:00" },
{ 2.525, "dd mm yyyy mm", "01 01 1900 01" },
{ 2.525, "dd mm yyyy :mm", "01 01 1900 :01" },
{ 2.525, "dd mm yyyy hh:mm", "01 01 1900 12:36" },
{ 2.525, "mm mm", "01 01" },
{ 2.525, "mm :mm:ss", "01 :01:00" },
{ 2.525, "mm :ss:mm", "01 :00:01" },
{ 2.525, "hh:mm :ss:mm", "12:36 :00:01" },
{ 2.525, "hh:dd :mm:mm", "12:01 :01:01" },
{ 2.525, "dd:hh :mm:mm", "01:12 :36:01" },
{ 2.525, "hh :mm:mm", "12 :36:01" },
{ 2.525, "dd :mm:mm", "01 :01:01" },
{ 2.525, "dd :mm:nn", "01 :01:36" },
{ 2.725, "hh:nn:ss A/P", "05:24:00 P" }
};
#define VNUMFMT(vt,v) \
for (i = 0; i < sizeof(VarFormat_results)/sizeof(FMTRES); i++) \
{ \
VARFMT(vt,v,1,VarFormat_results[i].fmt,S_OK,VarFormat_results[i].one_res); \
VARFMT(vt,v,0,VarFormat_results[i].fmt,S_OK,VarFormat_results[i].zero_res); \
} \
if ((1 << vt) & SIGNED_VTBITS) \
{ \
VARFMT(vt,v,-1,"\"pos\";\"neg\"",S_OK,"neg"); \
VARFMT(vt,v,-1,"\"pos\";\"neg\";\"zero\"",S_OK,"neg"); \
}
static void test_VarFormat(void)
{
static const WCHAR szTesting[] = { 't','e','s','t','i','n','g','\0' };
size_t i;
WCHAR buffW[256];
char buff[256];
VARIANT in;
VARIANT_BOOL bTrue = VARIANT_TRUE, bFalse = VARIANT_FALSE;
int fd = 0, fw = 0;
ULONG flags = 0;
BSTR bstrin, out = NULL;
HRESULT hres;
CHECKPTR(VarFormat);
if (PRIMARYLANGID(LANGIDFROMLCID(GetUserDefaultLCID())) != LANG_ENGLISH)
{
skip("Skipping VarFormat tests for non english language\n");
return;
}
GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buff, sizeof(buff)/sizeof(char));
if (buff[0] != '.' || buff[1])
{
skip("Skipping VarFormat tests as decimal separator is '%s'\n", buff);
return;
}
GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IDIGITS, buff, sizeof(buff)/sizeof(char));
if (buff[0] != '2' || buff[1])
{
skip("Skipping VarFormat tests as decimal places is '%s'\n", buff);
return;
}
VARFMT(VT_BOOL,V_BOOL,VARIANT_TRUE,"True/False",S_OK,"True");
VARFMT(VT_BOOL,V_BOOL,VARIANT_FALSE,"True/False",S_OK,"False");
VNUMFMT(VT_I1,V_I1);
VNUMFMT(VT_I2,V_I2);
VNUMFMT(VT_I4,V_I4);
if (HAVE_OLEAUT32_I8)
{
VNUMFMT(VT_I8,V_I8);
}
VNUMFMT(VT_INT,V_INT);
VNUMFMT(VT_UI1,V_UI1);
VNUMFMT(VT_UI2,V_UI2);
VNUMFMT(VT_UI4,V_UI4);
if (HAVE_OLEAUT32_I8)
{
VNUMFMT(VT_UI8,V_UI8);
}
VNUMFMT(VT_UINT,V_UINT);
VNUMFMT(VT_R4,V_R4);
VNUMFMT(VT_R8,V_R8);
/* Reference types are dereferenced */
VARFMT(VT_BOOL|VT_BYREF,V_BOOLREF,&bTrue,"True/False",S_OK,"True");
VARFMT(VT_BOOL|VT_BYREF,V_BOOLREF,&bFalse,"True/False",S_OK,"False");
/* Dates */
for (i = 0; i < sizeof(VarFormat_date_results)/sizeof(FMTDATERES); i++)
{
if (i < 7)
fd = i + 1; /* Test first day */
else
fd = 0;
VARFMT(VT_DATE,V_DATE,VarFormat_date_results[i].val,
VarFormat_date_results[i].fmt,S_OK,
VarFormat_date_results[i].res);
}
/* Strings */
bstrin = SysAllocString(szTesting);
VARFMT(VT_BSTR,V_BSTR,bstrin,"",S_OK,"testing");
VARFMT(VT_BSTR,V_BSTR,bstrin,"@",S_OK,"testing");
VARFMT(VT_BSTR,V_BSTR,bstrin,"&",S_OK,"testing");
VARFMT(VT_BSTR,V_BSTR,bstrin,"\\x@\\x@",S_OK,"xtxesting");
VARFMT(VT_BSTR,V_BSTR,bstrin,"\\x&\\x&",S_OK,"xtxesting");
VARFMT(VT_BSTR,V_BSTR,bstrin,"@\\x",S_OK,"txesting");
VARFMT(VT_BSTR,V_BSTR,bstrin,"@@@@@@@@",S_OK," testing");
VARFMT(VT_BSTR,V_BSTR,bstrin,"@\\x@@@@@@@",S_OK," xtesting");
VARFMT(VT_BSTR,V_BSTR,bstrin,"&&&&&&&&",S_OK,"testing");
VARFMT(VT_BSTR,V_BSTR,bstrin,"!&&&&&&&",S_OK,"testing");
VARFMT(VT_BSTR,V_BSTR,bstrin,"&&&&&&&!",S_OK,"testing");
VARFMT(VT_BSTR,V_BSTR,bstrin,">&&",S_OK,"TESTING");
VARFMT(VT_BSTR,V_BSTR,bstrin,"<&&",S_OK,"testing");
VARFMT(VT_BSTR,V_BSTR,bstrin,"<&>&",S_OK,"testing");
SysFreeString(bstrin);
/* Numeric values are converted to strings then output */
VARFMT(VT_I1,V_I1,1,"<&>&",S_OK,"1");
/* Number formats */
VARFMT(VT_I4,V_I4,1,"#00000000",S_OK,"00000001");
VARFMT(VT_I4,V_I4,1,"000###",S_OK,"000001");
VARFMT(VT_I4,V_I4,1,"#00##00#0",S_OK,"00000001");
VARFMT(VT_I4,V_I4,1,"1#####0000",S_OK,"10001");
todo_wine {
VARFMT(VT_I4,V_I4,100000,"#,###,###,###",S_OK,"100,000");
}
VARFMT(VT_R8,V_R8,1.23456789,"0#.0#0#0#0#0",S_OK,"01.234567890");
VARFMT(VT_R8,V_R8,1.2,"0#.0#0#0#0#0",S_OK,"01.200000000");
VARFMT(VT_R8,V_R8,9.87654321,"#0.#0#0#0#0#",S_OK,"9.87654321");
VARFMT(VT_R8,V_R8,9.8,"#0.#0#0#0#0#",S_OK,"9.80000000");
VARFMT(VT_R8,V_R8,0.00000008,"#0.#0#0#0#0#0",S_OK,"0.0000000800");
VARFMT(VT_R8,V_R8,0.00010705,"#0.##########",S_OK,"0.00010705");
VARFMT(VT_I4,V_I4,17,"#0",S_OK,"17");
VARFMT(VT_I4,V_I4,4711,"#0",S_OK,"4711");
VARFMT(VT_I4,V_I4,17,"#00",S_OK,"17");
VARFMT(VT_I4,V_I4,100,"0##",S_OK,"100");
VARFMT(VT_I4,V_I4,17,"#000",S_OK,"017");
VARFMT(VT_I4,V_I4,17,"#0.00",S_OK,"17.00");
VARFMT(VT_I4,V_I4,17,"#0000.00",S_OK,"0017.00");
VARFMT(VT_I4,V_I4,17,"#.00",S_OK,"17.00");
VARFMT(VT_R8,V_R8,1.7,"#.00",S_OK,"1.70");
VARFMT(VT_R8,V_R8,.17,"#.00",S_OK,".17");
VARFMT(VT_I4,V_I4,17,"#3",S_OK,"173");
VARFMT(VT_I4,V_I4,17,"#33",S_OK,"1733");
VARFMT(VT_I4,V_I4,17,"#3.33",S_OK,"173.33");
VARFMT(VT_I4,V_I4,17,"#3333.33",S_OK,"173333.33");
VARFMT(VT_I4,V_I4,17,"#.33",S_OK,"17.33");
VARFMT(VT_R8,V_R8,.17,"#.33",S_OK,".33");
VARFMT(VT_R8,V_R8,1.7,"0.0000E-000",S_OK,"1.7000E000");
VARFMT(VT_R8,V_R8,1.7,"0.0000e-1",S_OK,"1.7000e01");
VARFMT(VT_R8,V_R8,86.936849,"#0.000000000000e-000",S_OK,"86.936849000000e000");
VARFMT(VT_R8,V_R8,1.7,"#0",S_OK,"2");
VARFMT(VT_R8,V_R8,1.7,"#.33",S_OK,"2.33");
VARFMT(VT_R8,V_R8,1.7,"#3",S_OK,"23");
VARFMT(VT_R8,V_R8,1.73245,"0.0000E+000",S_OK,"1.7325E+000");
VARFMT(VT_R8,V_R8,9.9999999,"#0.000000",S_OK,"10.000000");
VARFMT(VT_R8,V_R8,1.7,"0.0000e+0#",S_OK,"1.7000e+0");
VARFMT(VT_R8,V_R8,100.0001e+0,"0.0000E+0",S_OK,"1.0000E+2");
VARFMT(VT_R8,V_R8,1000001,"0.0000e+1",S_OK,"1.0000e+61");
VARFMT(VT_R8,V_R8,100.0001e+25,"0.0000e+0",S_OK,"1.0000e+27");
VARFMT(VT_R8,V_R8,450.0001e+43,"#000.0000e+0",S_OK,"4500.0010e+42");
VARFMT(VT_R8,V_R8,0.0001e-11,"##00.0000e-0",S_OK,"1000.0000e-18");
VARFMT(VT_R8,V_R8,0.0317e-11,"0000.0000e-0",S_OK,"3170.0000e-16");
VARFMT(VT_R8,V_R8,0.0021e-11,"00##.0000e-0",S_OK,"2100.0000e-17");
VARFMT(VT_R8,V_R8,1.0001e-27,"##00.0000e-0",S_OK,"1000.1000e-30");
VARFMT(VT_R8,V_R8,47.11,".0000E+0",S_OK,".4711E+2");
VARFMT(VT_R8,V_R8,3.0401e-13,"#####.####e-0%",S_OK,"30401.e-15%");
/* 'out' is not cleared */
out = (BSTR)0x1;
pVarFormat(&in,NULL,fd,fw,flags,&out); /* Would crash if out is cleared */
out = NULL;
/* VT_NULL */
V_VT(&in) = VT_NULL;
hres = pVarFormat(&in,NULL,fd,fw,0,&out);
ok(hres == S_OK, "VarFormat failed with 0x%08x\n", hres);
ok(out == NULL, "expected NULL formatted string\n");
/* Invalid args */
hres = pVarFormat(&in,NULL,fd,fw,flags,NULL);
ok(hres == E_INVALIDARG, "Null out: expected E_INVALIDARG, got 0x%08x\n", hres);
hres = pVarFormat(NULL,NULL,fd,fw,flags,&out);
ok(hres == E_INVALIDARG, "Null in: expected E_INVALIDARG, got 0x%08x\n", hres);
fd = -1;
VARFMT(VT_BOOL,V_BOOL,VARIANT_TRUE,"",E_INVALIDARG,"");
fd = 8;
VARFMT(VT_BOOL,V_BOOL,VARIANT_TRUE,"",E_INVALIDARG,"");
fd = 0; fw = -1;
VARFMT(VT_BOOL,V_BOOL,VARIANT_TRUE,"",E_INVALIDARG,"");
fw = 4;
VARFMT(VT_BOOL,V_BOOL,VARIANT_TRUE,"",E_INVALIDARG,"");
}
START_TEST(varformat)
{
hOleaut32 = GetModuleHandleA("oleaut32.dll");
test_VarFormatNumber();
test_VarFormat();
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,16 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="riched20_winetest" type="win32cui" installbase="bin" installname="riched20_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="riched20_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>riched20</library>
<library>ole32</library>
<library>user32</library>
<library>gdi32</library>
<library>kernel32</library>
<library>ntdll</library>
<file>editor.c</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,15 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_editor(void);
const struct test winetest_testlist[] =
{
{ "editor", func_editor },
{ 0, 0 }
};

View file

@ -0,0 +1,84 @@
/*
* Unit tests for rsabase functions
*
* Copyright (c) 2004 Michael Jung
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <string.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wincrypt.h"
HCRYPTPROV hProv;
static const char szContainer[] = "Wine Test Container";
static const char szProvider[] = MS_DEF_PROV_A;
static int init_environment(void)
{
hProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;
if (!CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL, 0))
{
if (GetLastError()==NTE_BAD_KEYSET)
{
if(!CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
trace("%08x\n", GetLastError());
return 0;
}
}
else
{
trace("%08x\n", GetLastError());
return 0;
}
}
return 1;
}
static void clean_up_environment(void)
{
CryptAcquireContext(&hProv, szContainer, szProvider, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
}
static void test_gen_random(void)
{
BOOL result;
BYTE rnd1[16], rnd2[16];
memset(rnd1, 0, sizeof(rnd1));
memset(rnd2, 0, sizeof(rnd2));
result = CryptGenRandom(hProv, sizeof(rnd1), rnd1);
ok(result, "%08x\n", GetLastError());
result = CryptGenRandom(hProv, sizeof(rnd2), rnd2);
ok(result, "%08x\n", GetLastError());
ok(memcmp(rnd1, rnd2, sizeof(rnd1)), "CryptGenRandom generates non random data\n");
}
START_TEST(rsabase)
{
if (!init_environment())
return;
test_gen_random();
clean_up_environment();
}

View file

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="rsabase_winetest" type="win32cui" installbase="bin" installname="rsabase_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="rsabase_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>advapi32</library>
<library>kernel32</library>
<library>ntdll</library>
<file>rsabase.c</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,15 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_rsabase(void);
const struct test winetest_testlist[] =
{
{ "rsabase", func_rsabase },
{ 0, 0 }
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="rsaenh_winetest" type="win32cui" installbase="bin" installname="rsaenh_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="rsaenh_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>advapi32</library>
<library>kernel32</library>
<library>ntdll</library>
<file>rsaenh.c</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,15 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_rsaenh(void);
const struct test winetest_testlist[] =
{
{ "rsaenh", func_rsaenh },
{ 0, 0 }
};

View file

@ -23,6 +23,8 @@
#include "winbase.h"
#include "winerror.h"
#include "winuser.h"
#include "ole2.h"
#include "oaidl.h"
/* Function ptrs for ordinal calls */
static HMODULE hShlwapi;
@ -33,6 +35,7 @@ static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD);
static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD);
static BOOL (WINAPI *pSHUnlockShared)(LPVOID);
static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD);
static HRESULT(WINAPIV *pSHPackDispParams)(DISPPARAMS*,VARIANTARG*,UINT,...);
static void test_GetAcceptLanguagesA(void)
{ HRESULT retval;
@ -52,7 +55,7 @@ static void test_GetAcceptLanguagesA(void)
trace("GetAcceptLanguagesA: skipping tests\n");
return;
}
ok( (ERROR_NO_IMPERSONATION_TOKEN == GetLastError()) ||
ok( (ERROR_NO_IMPERSONATION_TOKEN == GetLastError()) ||
(ERROR_CLASS_DOES_NOT_EXIST == GetLastError()) ||
(ERROR_PROC_NOT_FOUND == GetLastError()) ||
(ERROR_CALL_NOT_IMPLEMENTED == GetLastError()) ||
@ -380,7 +383,7 @@ static void test_GetShellSecurityDescriptor(void)
"GetSecurityDescriptorControl failed with error %u\n", GetLastError());
ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
"GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
ok(bHasDacl, "SD has no DACL\n");
@ -404,21 +407,21 @@ static void test_GetShellSecurityDescriptor(void)
ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
"Invalid ACE type %d\n", paaa->Header.AceType);
ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
"Invalid ACE type %d\n", paaa->Header.AceType);
ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
"Invalid ACE type %d\n", paaa->Header.AceType);
ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
"Invalid ACE type %d\n", paaa->Header.AceType);
/* first one of two ACEs generated from inheritable entry - without inheritance */
ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %u\n", GetLastError());
ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
"Invalid ACE type %d\n", paaa->Header.AceType);
ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
"Invalid ACE type %d\n", paaa->Header.AceType);
/* second ACE - with inheritance */
ok(paaa->Header.AceFlags == MY_INHERITANCE,
"Invalid ACE flags %x\n", paaa->Header.AceFlags);
@ -431,6 +434,53 @@ static void test_GetShellSecurityDescriptor(void)
}
}
static void test_SHPackDispParams(void)
{
DISPPARAMS params;
VARIANT vars[10];
HRESULT hres;
if(!pSHPackDispParams)
skip("SHPackSidpParams not available\n");
memset(&params, 0xc0, sizeof(params));
memset(vars, 0xc0, sizeof(vars));
hres = pSHPackDispParams(&params, vars, 1, VT_I4, 0xdeadbeef);
ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
ok(params.cArgs == 1, "params.cArgs = %d\n", params.cArgs);
ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
ok(V_VT(vars) == VT_I4, "V_VT(var) = %d\n", V_VT(vars));
ok(V_DISPATCH(vars) == (void*)0xdeadbeef, "failed\n");
memset(&params, 0xc0, sizeof(params));
hres = pSHPackDispParams(&params, NULL, 0, 0);
ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
ok(params.cArgs == 0, "params.cArgs = %d\n", params.cArgs);
ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
ok(params.rgvarg == NULL, "params.rgvarg = %p\n", params.rgvarg);
memset(vars, 0xc0, sizeof(vars));
memset(&params, 0xc0, sizeof(params));
hres = pSHPackDispParams(&params, vars, 4, VT_BSTR, (void*)0xdeadbeef, VT_EMPTY, 10,
VT_I4, 100, VT_DISPATCH, (void*)0xdeadbeef);
ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres);
ok(params.cArgs == 4, "params.cArgs = %d\n", params.cArgs);
ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs);
ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs);
ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg);
ok(V_VT(vars) == VT_DISPATCH, "V_VT(vars[0]) = %x\n", V_VT(vars));
ok(V_I4(vars) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars));
ok(V_VT(vars+1) == VT_I4, "V_VT(vars[1]) = %d\n", V_VT(vars+1));
ok(V_I4(vars+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars+1));
ok(V_VT(vars+2) == VT_I4, "V_VT(vars[2]) = %d\n", V_VT(vars+2));
ok(V_I4(vars+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars+2));
ok(V_VT(vars+3) == VT_BSTR, "V_VT(vars[3]) = %d\n", V_VT(vars+3));
ok(V_BSTR(vars+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars+3));
}
START_TEST(ordinal)
{
hShlwapi = GetModuleHandleA("shlwapi.dll");
@ -441,10 +491,12 @@ START_TEST(ordinal)
pSHLockShared=(void*)GetProcAddress(hShlwapi,(char*)8);
pSHUnlockShared=(void*)GetProcAddress(hShlwapi,(char*)9);
pSHFreeShared=(void*)GetProcAddress(hShlwapi,(char*)10);
pSHPackDispParams=(void*)GetProcAddress(hShlwapi,(char*)282);
test_GetAcceptLanguagesA();
test_SHSearchMapInt();
test_alloc_shared();
test_fdsa();
test_GetShellSecurityDescriptor();
test_SHPackDispParams();
}

View file

@ -33,199 +33,7 @@ static HRESULT (WINAPI *pPathIsValidCharA)(char,DWORD);
static HRESULT (WINAPI *pPathIsValidCharW)(WCHAR,DWORD);
static LPWSTR (WINAPI *pPathCombineW)(LPWSTR, LPCWSTR, LPCWSTR);
const char* TEST_URL_1 = "http://www.winehq.org/tests?date=10/10/1923";
const char* TEST_URL_2 = "http://localhost:8080/tests%2e.html?date=Mon%2010/10/1923";
const char* TEST_URL_3 = "http://foo:bar@localhost:21/internal.php?query=x&return=y";
typedef struct _TEST_URL_CANONICALIZE {
const char *url;
DWORD flags;
HRESULT expectret;
const char *expecturl;
} TEST_URL_CANONICALIZE;
const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
/*FIXME {"http://www.winehq.org/tests/../tests/../..", 0, S_OK, "http://www.winehq.org/"},*/
{"http://www.winehq.org/tests/../tests", 0, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests\n", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests\r", 0, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests\r", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests/../tests/", 0, S_OK, "http://www.winehq.org/tests/"},
{"http://www.winehq.org/tests/../tests/..", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/../tests/../", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/..", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/../", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
{"http://www.winehq.org/tests/../?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
{"http://www.winehq.org/tests/..#example", 0, S_OK, "http://www.winehq.org/#example"},
{"http://www.winehq.org/tests/../#example", 0, S_OK, "http://www.winehq.org/#example"},
{"http://www.winehq.org/tests\\../#example", 0, S_OK, "http://www.winehq.org/#example"},
{"http://www.winehq.org/tests/..\\#example", 0, S_OK, "http://www.winehq.org/#example"},
{"http://www.winehq.org\\tests/../#example", 0, S_OK, "http://www.winehq.org/#example"},
{"http://www.winehq.org/tests/../#example", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example"},
{"http://www.winehq.org/tests/foo bar", URL_ESCAPE_SPACES_ONLY| URL_DONT_ESCAPE_EXTRA_INFO , S_OK, "http://www.winehq.org/tests/foo%20bar"},
{"http://www.winehq.org/tests/foo%20bar", URL_UNESCAPE , S_OK, "http://www.winehq.org/tests/foo bar"},
{"file:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"},
{"file:///c:/tests\\foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"},
{"file:///c:/tests/foo%20bar", 0, S_OK, "file:///c:/tests/foo%20bar"},
{"file:///c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
{"file://c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
{"file://c:/tests\\../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
{"file://c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
{"file:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\\\tests\\foo bar"},
{"file:///c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo bar"},
{"file:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, S_OK, "file:///c:/tests/foo bar"},
{"http://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/site/about"},
{"file_://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "file_://www.winehq.org/site/about"},
{"c:\\dir\\file", 0, S_OK, "file:///c:/dir/file"},
{"file:///c:\\dir\\file", 0, S_OK, "file:///c:/dir/file"},
{"c:dir\\file", 0, S_OK, "file:///c:dir/file"},
{"c:\\tests\\foo bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
{"c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo%20bar"},
{"A", 0, S_OK, "A"},
{"", 0, S_OK, ""}
};
typedef struct _TEST_URL_ESCAPE {
const char *url;
DWORD flags;
DWORD expectescaped;
HRESULT expectret;
const char *expecturl;
} TEST_URL_ESCAPE;
const TEST_URL_ESCAPE TEST_ESCAPE[] = {
{"http://www.winehq.org/tests0", 0, 0, S_OK, "http://www.winehq.org/tests0"},
{"http://www.winehq.org/tests1\n", 0, 0, S_OK, "http://www.winehq.org/tests1%0A"},
{"http://www.winehq.org/tests2\r", 0, 0, S_OK, "http://www.winehq.org/tests2%0D"},
{"http://www.winehq.org/tests3\r", URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, 0, S_OK, "http://www.winehq.org/tests3\r"},
{"http://www.winehq.org/tests4\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests4\r"},
{"http://www.winehq.org/tests5\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests5\r"},
{"/direct/swhelp/series6/6.2i_latestservicepack.dat\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "/direct/swhelp/series6/6.2i_latestservicepack.dat\r"},
{"file://////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file://///foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file:////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file:///localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
{"file:///foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file://loCalHost/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file://foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file:/localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
{"file:/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file:foo/bar\\baz", 0, 0, S_OK, "file:foo/bar/baz"},
{"file:\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file:\\\\foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file:\\\\\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file:\\\\localhost\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file:///f oo/b?a r\\baz", 0, 0, S_OK, "file:///f%20oo/b?a r\\baz"},
{"file:///foo/b#a r\\baz", 0, 0, S_OK, "file:///foo/b%23a%20r/baz"},
{"file:///f o^&`{}|][\"<>\\%o/b#a r\\baz", 0, 0, S_OK, "file:///f%20o%5E%26%60%7B%7D%7C%5D%5B%22%3C%3E/%o/b%23a%20r/baz"},
{"file:///f o%o/b?a r\\b%az", URL_ESCAPE_PERCENT, 0, S_OK, "file:///f%20o%25o/b?a r\\b%az"},
{"file:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "file:%2Ffoo%2Fbar%5Cbaz"},
{"foo/b%ar\\ba?z\\", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%ar%5Cba%3Fz%5C"},
{"foo/b%ar\\ba?z\\", URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%25ar%5Cba%3Fz%5C"},
{"foo/bar\\ba?z\\", 0, 0, S_OK, "foo/bar%5Cba?z\\"},
{"/foo/bar\\ba?z\\", 0, 0, S_OK, "/foo/bar%5Cba?z\\"},
{"/foo/bar\\ba#z\\", 0, 0, S_OK, "/foo/bar%5Cba#z\\"},
{"/foo/%5C", 0, 0, S_OK, "/foo/%5C"},
{"/foo/%5C", URL_ESCAPE_PERCENT, 0, S_OK, "/foo/%255C"},
{"http://////foo/bar\\baz", 0, 0, S_OK, "http://////foo/bar/baz"},
{"http://///foo/bar\\baz", 0, 0, S_OK, "http://///foo/bar/baz"},
{"http:////foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
{"http:///foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
{"http://localhost/foo/bar\\baz", 0, 0, S_OK, "http://localhost/foo/bar/baz"},
{"http://foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
{"http:/foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
{"http:foo/bar\\ba?z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba?z\\"},
{"http:foo/bar\\ba#z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba#z\\"},
{"http:\\foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
{"http:\\\\foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
{"http:\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
{"http:\\\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
{"http:/fo ?o/b ar\\baz", 0, 0, S_OK, "http:/fo%20?o/b ar\\baz"},
{"http:fo ?o/b ar\\baz", 0, 0, S_OK, "http:fo%20?o/b ar\\baz"},
{"http:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "http:%2Ffoo%2Fbar%5Cbaz"},
{"https://foo/bar\\baz", 0, 0, S_OK, "https://foo/bar/baz"},
{"https:/foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
{"https:\\foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
{"foo:////foo/bar\\baz", 0, 0, S_OK, "foo:////foo/bar%5Cbaz"},
{"foo:///foo/bar\\baz", 0, 0, S_OK, "foo:///foo/bar%5Cbaz"},
{"foo://localhost/foo/bar\\baz", 0, 0, S_OK, "foo://localhost/foo/bar%5Cbaz"},
{"foo://foo/bar\\baz", 0, 0, S_OK, "foo://foo/bar%5Cbaz"},
{"foo:/foo/bar\\baz", 0, 0, S_OK, "foo:/foo/bar%5Cbaz"},
{"foo:foo/bar\\baz", 0, 0, S_OK, "foo:foo%2Fbar%5Cbaz"},
{"foo:\\foo/bar\\baz", 0, 0, S_OK, "foo:%5Cfoo%2Fbar%5Cbaz"},
{"foo:/foo/bar\\ba?\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba?\\z"},
{"foo:/foo/bar\\ba#\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba#\\z"},
{"mailto:/fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:%2Ffo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
{"mailto:fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:fo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
{"mailto:fo/o@b\\%a?\\r.b#\\az", URL_ESCAPE_PERCENT, 0, S_OK, "mailto:fo%2Fo@b%5C%25a%3F%5Cr.b%23%5Caz"},
{"ftp:fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:fo%2Fo@bar.baz%2Ffoo%2Fbar"},
{"ftp:/fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:/fo/o@bar.baz/foo/bar"},
{"ftp://fo/o@bar.baz/fo?o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo?o\\bar"},
{"ftp://fo/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo#o\\bar"},
{"ftp://localhost/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://localhost/o@bar.baz/fo#o\\bar"},
{"ftp:///fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:///fo/o@bar.baz/foo/bar"},
{"ftp:////fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:////fo/o@bar.baz/foo/bar"}
};
typedef struct _TEST_URL_COMBINE {
const char *url1;
const char *url2;
DWORD flags;
HRESULT expectret;
const char *expecturl;
} TEST_URL_COMBINE;
const TEST_URL_COMBINE TEST_COMBINE[] = {
{"http://www.winehq.org/tests", "tests1", 0, S_OK, "http://www.winehq.org/tests1"},
{"http://www.%77inehq.org/tests", "tests1", 0, S_OK, "http://www.%77inehq.org/tests1"},
/*FIXME {"http://www.winehq.org/tests", "../tests2", 0, S_OK, "http://www.winehq.org/tests2"},*/
{"http://www.winehq.org/tests/", "../tests3", 0, S_OK, "http://www.winehq.org/tests3"},
{"http://www.winehq.org/tests/test1", "test2", 0, S_OK, "http://www.winehq.org/tests/test2"},
{"http://www.winehq.org/tests/../tests", "tests4", 0, S_OK, "http://www.winehq.org/tests4"},
{"http://www.winehq.org/tests/../tests/", "tests5", 0, S_OK, "http://www.winehq.org/tests/tests5"},
{"http://www.winehq.org/tests/../tests/", "/tests6/..", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/../tests/..", "tests7/..", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/?query=x&return=y", "tests8", 0, S_OK, "http://www.winehq.org/tests/tests8"},
{"http://www.winehq.org/tests/#example", "tests9", 0, S_OK, "http://www.winehq.org/tests/tests9"},
{"http://www.winehq.org/tests/../tests/", "/tests10/..", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests10/.."},
{"http://www.winehq.org/tests/../", "tests11", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../tests11"},
{"file:///C:\\dir\\file.txt", "test.txt", 0, S_OK, "file:///C:/dir/test.txt"},
{"http://www.winehq.org/test/", "test%20file.txt", 0, S_OK, "http://www.winehq.org/test/test%20file.txt"},
{"http://www.winehq.org/test/", "test%20file.txt", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/test/test%20file.txt"},
{"http://www.winehq.org%2ftest/", "test%20file.txt", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org%2ftest/test%20file.txt"},
{"xxx:@MSITStore:file.chm/file.html", "dir/file", 0, S_OK, "xxx:dir/file"},
{"mk:@MSITStore:file.chm::/file.html", "/dir/file", 0, S_OK, "mk:@MSITStore:file.chm::/dir/file"},
{"mk:@MSITStore:file.chm::/file.html", "mk:@MSITStore:file.chm::/dir/file", 0, S_OK, "mk:@MSITStore:file.chm::/dir/file"},
};
struct {
const char *path;
const char *url;
DWORD ret;
} TEST_URLFROMPATH [] = {
{"foo", "file:foo", S_OK},
{"foo\\bar", "file:foo/bar", S_OK},
{"\\foo\\bar", "file:///foo/bar", S_OK},
{"c:\\foo\\bar", "file:///c:/foo/bar", S_OK},
{"c:foo\\bar", "file:///c:foo/bar", S_OK},
{"c:\\foo/b a%r", "file:///c:/foo/b%20a%25r", S_OK},
{"c:\\foo\\foo bar", "file:///c:/foo/foo%20bar", S_OK},
#if 0
/* The following test fails on native shlwapi as distributed with Win95/98.
* Wine matches the behaviour of later versions.
*/
{"xx:c:\\foo\\bar", "xx:c:\\foo\\bar", S_FALSE}
#endif
};
/* ################ */
struct {
const char *url;
@ -261,16 +69,8 @@ struct {
};
struct {
char url[30];
const char *expect;
} TEST_URL_UNESCAPE[] = {
{"file://foo/bar", "file://foo/bar"},
{"file://fo%20o%5Ca/bar", "file://fo o\\a/bar"}
};
struct {
static struct {
const char *path;
BOOL expect;
} TEST_PATH_IS_URL[] = {
@ -283,38 +83,6 @@ struct {
{"http:partial", TRUE}
};
struct {
const char *url;
BOOL expectOpaque;
BOOL expectFile;
} TEST_URLIS_ATTRIBS[] = {
{ "ftp:", FALSE, FALSE },
{ "http:", FALSE, FALSE },
{ "gopher:", FALSE, FALSE },
{ "mailto:", TRUE, FALSE },
{ "news:", FALSE, FALSE },
{ "nntp:", FALSE, FALSE },
{ "telnet:", FALSE, FALSE },
{ "wais:", FALSE, FALSE },
{ "file:", FALSE, TRUE },
{ "mk:", FALSE, FALSE },
{ "https:", FALSE, FALSE },
{ "shell:", TRUE, FALSE },
{ "https:", FALSE, FALSE },
{ "snews:", FALSE, FALSE },
{ "local:", FALSE, FALSE },
{ "javascript:", TRUE, FALSE },
{ "vbscript:", TRUE, FALSE },
{ "about:", TRUE, FALSE },
{ "res:", FALSE, FALSE },
{ "bogusscheme:", FALSE, FALSE },
{ "file:\\\\e:\\b\\c", FALSE, TRUE },
{ "file://e:/b/c", FALSE, TRUE },
{ "http:partial", FALSE, FALSE },
{ "mailto://www.winehq.org/test.html", TRUE, FALSE },
{ "file:partial", FALSE, TRUE }
};
struct {
const char *path;
const char *result;
@ -332,10 +100,12 @@ struct {
{ "\"", "" }
};
/* ################ */
static LPWSTR GetWideString(const char* szString)
{
LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
return wszString;
@ -355,348 +125,15 @@ static LPSTR strdupA(LPCSTR p)
return ret;
}
static void hash_url(const char* szUrl)
{
LPCSTR szTestUrl = szUrl;
LPWSTR wszTestUrl = GetWideString(szTestUrl);
DWORD cbSize = sizeof(DWORD);
DWORD dwHash1, dwHash2;
ok(UrlHashA(szTestUrl, (LPBYTE)&dwHash1, cbSize) == S_OK, "UrlHashA didn't return S_OK\n");
ok(UrlHashW(wszTestUrl, (LPBYTE)&dwHash2, cbSize) == S_OK, "UrlHashW didn't return S_OK\n");
FreeWideString(wszTestUrl);
ok(dwHash1 == dwHash2, "Hashes didn't compare\n");
}
static void test_UrlHash(void)
{
hash_url(TEST_URL_1);
hash_url(TEST_URL_2);
hash_url(TEST_URL_3);
}
static void test_url_part(const char* szUrl, DWORD dwPart, DWORD dwFlags, const char* szExpected)
{
CHAR szPart[INTERNET_MAX_URL_LENGTH];
WCHAR wszPart[INTERNET_MAX_URL_LENGTH];
LPWSTR wszUrl = GetWideString(szUrl);
LPWSTR wszConvertedPart;
DWORD dwSize;
dwSize = INTERNET_MAX_URL_LENGTH;
ok( UrlGetPartA(szUrl, szPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartA for \"%s\" part 0x%08x didn't return S_OK but \"%s\"\n", szUrl, dwPart, szPart);
dwSize = INTERNET_MAX_URL_LENGTH;
ok( UrlGetPartW(wszUrl, wszPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartW didn't return S_OK\n" );
wszConvertedPart = GetWideString(szPart);
ok(lstrcmpW(wszPart,wszConvertedPart)==0, "Strings didn't match between ascii and unicode UrlGetPart!\n");
FreeWideString(wszUrl);
FreeWideString(wszConvertedPart);
/* Note that v6.0 and later don't return '?' with the query */
ok(strcmp(szPart,szExpected)==0 ||
(*szExpected=='?' && !strcmp(szPart,szExpected+1)),
"Expected %s, but got %s\n", szExpected, szPart);
}
static void test_UrlGetPart(void)
{
CHAR szPart[INTERNET_MAX_URL_LENGTH];
DWORD dwSize;
HRESULT res;
dwSize = sizeof szPart;
szPart[0]='x'; szPart[1]=0;
res = UrlGetPartA("hi", szPart, &dwSize, URL_PART_SCHEME, 0);
todo_wine {
ok (res==S_FALSE, "UrlGetPartA(\"hi\") returned %08X\n", res);
ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart);
}
dwSize = sizeof szPart;
szPart[0]='x'; szPart[1]=0;
res = UrlGetPartA("hi", szPart, &dwSize, URL_PART_QUERY, 0);
todo_wine {
ok (res==S_FALSE, "UrlGetPartA(\"hi\") returned %08X\n", res);
ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart);
}
test_url_part(TEST_URL_3, URL_PART_HOSTNAME, 0, "localhost");
test_url_part(TEST_URL_3, URL_PART_PORT, 0, "21");
test_url_part(TEST_URL_3, URL_PART_USERNAME, 0, "foo");
test_url_part(TEST_URL_3, URL_PART_PASSWORD, 0, "bar");
test_url_part(TEST_URL_3, URL_PART_SCHEME, 0, "http");
test_url_part(TEST_URL_3, URL_PART_QUERY, 0, "?query=x&return=y");
}
static void test_url_escape(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
{
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
DWORD dwEscaped;
WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
WCHAR *urlW, *expected_urlW;
dwEscaped=INTERNET_MAX_URL_LENGTH;
ok(UrlEscapeA(szUrl, szReturnUrl, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeA didn't return 0x%08x from \"%s\"\n", dwExpectReturn, szUrl);
ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", szExpectUrl, szReturnUrl, szUrl);
dwEscaped = INTERNET_MAX_URL_LENGTH;
urlW = GetWideString(szUrl);
expected_urlW = GetWideString(szExpectUrl);
ok(UrlEscapeW(urlW, ret_urlW, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeW didn't return 0x%08x from \"%s\"\n", dwExpectReturn, szUrl);
WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
ok(lstrcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08x\n", szExpectUrl, szReturnUrl, szUrl, dwFlags);
FreeWideString(urlW);
FreeWideString(expected_urlW);
}
static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
{
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
LPWSTR wszUrl = GetWideString(szUrl);
LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
LPWSTR wszConvertedUrl;
DWORD dwSize;
dwSize = INTERNET_MAX_URL_LENGTH;
ok(UrlCanonicalizeA(szUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08x\n", dwExpectReturn);
ok(strcmp(szReturnUrl,szExpectUrl)==0, "UrlCanonicalizeA dwFlags 0x%08x Expected \"%s\", but got \"%s\"\n", dwFlags, szExpectUrl, szReturnUrl);
dwSize = INTERNET_MAX_URL_LENGTH;
ok(UrlCanonicalizeW(wszUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08x\n", dwExpectReturn);
wszConvertedUrl = GetWideString(szReturnUrl);
ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n");
FreeWideString(wszConvertedUrl);
FreeWideString(wszUrl);
FreeWideString(wszExpectUrl);
}
static void test_UrlEscape(void)
{
DWORD size;
HRESULT ret;
unsigned int i;
ret = UrlEscapeA("/woningplan/woonkamer basis.swf", NULL, &size, URL_ESCAPE_SPACES_ONLY);
ok(ret == E_INVALIDARG, "got %x, expected %x\n", ret, E_INVALIDARG);
for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
TEST_ESCAPE[i].expectret, TEST_ESCAPE[i].expecturl);
}
}
static void test_UrlCanonicalize(void)
{
unsigned int i;
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
DWORD dwSize;
HRESULT hr;
for(i=0; i<sizeof(TEST_CANONICALIZE)/sizeof(TEST_CANONICALIZE[0]); i++) {
test_url_canonicalize(TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl);
}
/* move to TEST_CANONICALIZE when fixed */
dwSize = sizeof szReturnUrl;
/*LimeWire online installer calls this*/
hr = UrlCanonicalizeA("/uri-res/N2R?urn:sha1:B3K", szReturnUrl, &dwSize,URL_DONT_ESCAPE_EXTRA_INFO | URL_WININET_COMPATIBILITY /*0x82000000*/);
ok(hr==S_OK,"UrlCanonicalizeA returned 0x%08x instead of S_OK\n", hr);
todo_wine {
ok(strcmp(szReturnUrl,"/uri-res/N2R?urn:sha1:B3K")==0, "UrlCanonicalizeA got \"%s\" instead of \"/uri-res/N2R?urn:sha1:B3K\"\n", szReturnUrl);
}
}
static void test_url_combine(const char *szUrl1, const char *szUrl2, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
{
HRESULT hr;
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
LPWSTR wszUrl1 = GetWideString(szUrl1);
LPWSTR wszUrl2 = GetWideString(szUrl2);
LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
LPWSTR wszConvertedUrl;
DWORD dwSize;
DWORD dwExpectLen = lstrlen(szExpectUrl);
hr = UrlCombineA(szUrl1, szUrl2, NULL, NULL, dwFlags);
ok(hr == E_INVALIDARG, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
dwSize = 0;
hr = UrlCombineA(szUrl1, szUrl2, NULL, &dwSize, dwFlags);
ok(hr == E_POINTER, "Checking length of string, return was 0x%08x, expected 0x%08x\n", hr, E_POINTER);
ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
dwSize--;
hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
ok(hr == E_POINTER, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_POINTER);
ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
ok(hr == dwExpectReturn, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, dwExpectReturn);
ok(dwSize == dwExpectLen, "Got length %d, expected %d\n", dwSize, dwExpectLen);
if(SUCCEEDED(hr)) {
ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
}
dwSize = 0;
hr = UrlCombineW(wszUrl1, wszUrl2, NULL, &dwSize, dwFlags);
ok(hr == E_POINTER, "Checking length of string, return was 0x%08x, expected 0x%08x\n", hr, E_POINTER);
ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
dwSize--;
hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
ok(hr == E_POINTER, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_POINTER);
ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
ok(hr == dwExpectReturn, "UrlCombineW returned 0x%08x, expected 0x%08x\n", hr, dwExpectReturn);
ok(dwSize == dwExpectLen, "Got length %d, expected %d\n", dwSize, dwExpectLen);
if(SUCCEEDED(hr)) {
wszConvertedUrl = GetWideString(szReturnUrl);
ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCombine!\n");
FreeWideString(wszConvertedUrl);
}
FreeWideString(wszUrl1);
FreeWideString(wszUrl2);
FreeWideString(wszExpectUrl);
}
static void test_UrlCombine(void)
{
unsigned int i;
for(i=0; i<sizeof(TEST_COMBINE)/sizeof(TEST_COMBINE[0]); i++) {
test_url_combine(TEST_COMBINE[i].url1, TEST_COMBINE[i].url2, TEST_COMBINE[i].flags,
TEST_COMBINE[i].expectret, TEST_COMBINE[i].expecturl);
}
}
static void test_UrlCreateFromPath(void)
{
size_t i;
char ret_url[INTERNET_MAX_URL_LENGTH];
DWORD len, ret;
WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
WCHAR *pathW, *urlW;
for(i = 0; i < sizeof(TEST_URLFROMPATH) / sizeof(TEST_URLFROMPATH[0]); i++) {
len = INTERNET_MAX_URL_LENGTH;
ret = UrlCreateFromPathA(TEST_URLFROMPATH[i].path, ret_url, &len, 0);
ok(ret == TEST_URLFROMPATH[i].ret, "ret %08x from path %s\n", ret, TEST_URLFROMPATH[i].path);
ok(!lstrcmpi(ret_url, TEST_URLFROMPATH[i].url), "url %s from path %s\n", ret_url, TEST_URLFROMPATH[i].path);
ok(len == strlen(ret_url), "ret len %d from path %s\n", len, TEST_URLFROMPATH[i].path);
len = INTERNET_MAX_URL_LENGTH;
pathW = GetWideString(TEST_URLFROMPATH[i].path);
urlW = GetWideString(TEST_URLFROMPATH[i].url);
ret = UrlCreateFromPathW(pathW, ret_urlW, &len, 0);
WideCharToMultiByte(CP_ACP, 0, ret_urlW, -1, ret_url, sizeof(ret_url),0,0);
ok(ret == TEST_URLFROMPATH[i].ret, "ret %08x from path L\"%s\", expected %08x\n",
ret, TEST_URLFROMPATH[i].path, TEST_URLFROMPATH[i].ret);
ok(!lstrcmpiW(ret_urlW, urlW), "got %s expected %s from path L\"%s\"\n", ret_url, TEST_URLFROMPATH[i].url, TEST_URLFROMPATH[i].path);
ok(len == lstrlenW(ret_urlW), "ret len %d from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
FreeWideString(urlW);
FreeWideString(pathW);
}
}
static void test_UrlIs(void)
{
BOOL ret;
size_t i;
WCHAR wurl[80];
for(i = 0; i < sizeof(TEST_PATH_IS_URL) / sizeof(TEST_PATH_IS_URL[0]); i++) {
MultiByteToWideChar(CP_ACP, 0, TEST_PATH_IS_URL[i].path, -1, wurl, 80);
ret = UrlIsA( TEST_PATH_IS_URL[i].path, URLIS_URL );
ok( ret == TEST_PATH_IS_URL[i].expect,
"returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
TEST_PATH_IS_URL[i].expect );
ret = UrlIsW( wurl, URLIS_URL );
ok( ret == TEST_PATH_IS_URL[i].expect,
"returned %d from path (UrlIsW) %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
TEST_PATH_IS_URL[i].expect );
}
for(i = 0; i < sizeof(TEST_URLIS_ATTRIBS) / sizeof(TEST_URLIS_ATTRIBS[0]); i++) {
MultiByteToWideChar(CP_ACP, 0, TEST_URLIS_ATTRIBS[i].url, -1, wurl, 80);
ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_OPAQUE);
ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
"returned %d for URLIS_OPAQUE, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
TEST_URLIS_ATTRIBS[i].expectOpaque );
ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_FILEURL);
ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
"returned %d for URLIS_FILEURL, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
TEST_URLIS_ATTRIBS[i].expectFile );
ret = UrlIsW( wurl, URLIS_OPAQUE);
ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
"returned %d for URLIS_OPAQUE (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
TEST_URLIS_ATTRIBS[i].expectOpaque );
ret = UrlIsW( wurl, URLIS_FILEURL);
ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
"returned %d for URLIS_FILEURL (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
TEST_URLIS_ATTRIBS[i].expectFile );
}
}
static void test_UrlUnescape(void)
{
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
WCHAR *urlW, *expected_urlW;
DWORD dwEscaped;
size_t i;
static char inplace[] = "file:///C:/Program%20Files";
static WCHAR inplaceW[] = {'f','i','l','e',':','/','/','/','C',':','/',
'P','r','o','g','r','a','m','%','2','0','F','i','l','e','s',0};
for(i=0; i<sizeof(TEST_URL_UNESCAPE)/sizeof(TEST_URL_UNESCAPE[0]); i++) {
dwEscaped=INTERNET_MAX_URL_LENGTH;
ok(UrlUnescapeA(TEST_URL_UNESCAPE[i].url, szReturnUrl, &dwEscaped, 0) == S_OK, "UrlUnescapeA didn't return 0x%08x from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
ok(strcmp(szReturnUrl,TEST_URL_UNESCAPE[i].expect)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url);
dwEscaped = INTERNET_MAX_URL_LENGTH;
urlW = GetWideString(TEST_URL_UNESCAPE[i].url);
expected_urlW = GetWideString(TEST_URL_UNESCAPE[i].expect);
ok(UrlUnescapeW(urlW, ret_urlW, &dwEscaped, 0) == S_OK, "UrlUnescapeW didn't return 0x%08x from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
ok(lstrcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url, 0L);
FreeWideString(urlW);
FreeWideString(expected_urlW);
}
dwEscaped = sizeof(inplace);
ok(UrlUnescapeA(inplace, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeA failed unexpectedly\n");
dwEscaped = sizeof(inplaceW);
ok(UrlUnescapeW(inplaceW, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeW failed unexpectedly\n");
}
/* ################ */
static void test_PathSearchAndQualify(void)
{
WCHAR path1[] = {'c',':','\\','f','o','o',0};
WCHAR expect1[] = {'c',':','\\','f','o','o',0};
WCHAR path2[] = {'c',':','f','o','o',0};
WCHAR c_drive[] = {'c',':',0};
WCHAR foo[] = {'f','o','o',0};
WCHAR c_drive[] = {'c',':',0};
WCHAR foo[] = {'f','o','o',0};
WCHAR path3[] = {'\\','f','o','o',0};
WCHAR winini[] = {'w','i','n','.','i','n','i',0};
WCHAR out[MAX_PATH];
@ -714,7 +151,7 @@ static void test_PathSearchAndQualify(void)
GetFullPathNameW(c_drive, MAX_PATH, cur_dir, NULL);
PathAddBackslashW(cur_dir);
lstrcatW(cur_dir, foo);
ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
/* foo */
ok(PathSearchAndQualifyW(foo, out, MAX_PATH) != 0,
@ -722,7 +159,7 @@ static void test_PathSearchAndQualify(void)
GetFullPathNameW(dot, MAX_PATH, cur_dir, NULL);
PathAddBackslashW(cur_dir);
lstrcatW(cur_dir, foo);
ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
ok(!lstrcmpiW(out, cur_dir), "strings don't match\n");
/* \foo */
ok(PathSearchAndQualifyW(path3, out, MAX_PATH) != 0,
@ -751,7 +188,7 @@ static void test_PathCreateFromUrl(void)
/* Check ret_path = NULL */
len = sizeof(url);
ret = PathCreateFromUrlA(url, NULL, &len, 0);
ret = PathCreateFromUrlA(url, NULL, &len, 0);
ok ( ret == E_INVALIDARG, "got 0x%08x expected E_INVALIDARG\n", ret);
for(i = 0; i < sizeof(TEST_PATHFROMURL) / sizeof(TEST_PATHFROMURL[0]); i++) {
@ -952,7 +389,7 @@ static void test_PathCombineW(void)
WCHAR wbuf[MAX_PATH+1], wstr1[MAX_PATH] = {'C',':','\\',0}, wstr2[MAX_PATH];
static const WCHAR expout[] = {'C',':','\\','A','A',0};
int i;
wszString2 = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
/* NULL test */
@ -1365,7 +802,7 @@ static void test_PathCanonicalizeA(void)
SetLastError(0xdeadbeef);
res = PathCanonicalizeA(dest, NULL);
ok(!res, "Expected failure\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER,
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
todo_wine
{
@ -1384,7 +821,7 @@ static void test_PathCanonicalizeA(void)
SetLastError(0xdeadbeef);
res = PathCanonicalizeA(NULL, "C:\\");
ok(!res, "Expected failure\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER,
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* try empty dest */
@ -1831,19 +1268,12 @@ static void test_PathUnquoteSpaces(void)
}
}
/* ################ */
START_TEST(path)
{
hShlwapi = GetModuleHandleA("shlwapi.dll");
test_UrlHash();
test_UrlGetPart();
test_UrlCanonicalize();
test_UrlEscape();
test_UrlCombine();
test_UrlCreateFromPath();
test_UrlIs();
test_UrlUnescape();
test_PathSearchAndQualify();
test_PathCreateFromUrl();
test_PathIsUrl();

View file

@ -1,9 +1,9 @@
<module name="shlwapi_winetest" type="win32cui" installbase="bin" installname="shlwapi_winetest.exe" allowwarnings="true">
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="shlwapi_winetest" type="win32cui" installbase="bin" installname="shlwapi_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="shlwapi_winetest">.</include>
<define name="__USE_W32API" />
<define name="_WIN32_IE">0x600</define>
<define name="_WIN32_WINNT">0x501</define>
<define name="WINVER">0x501</define>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>shlwapi</library>
<library>advapi32</library>
@ -19,5 +19,6 @@
<file>path.c</file>
<file>shreg.c</file>
<file>string.c</file>
<file>url.c</file>
<file>testlist.c</file>
</module>

View file

@ -102,10 +102,10 @@ static HKEY create_test_entries(void)
trace("sExplen2 = (%d)\n", nExpLen2);
if (nExpectedLen2 != nExpLen2)
trace( "Expanding %s failed (expected %d) - known bug in NT4\n", sTestpath2, nExpectedLen2 );
trace( "Expanding %s failed (expected %d) - known bug in NT4\n", sTestpath2, nExpectedLen2 );
/* Make sure we carry on with correct values */
nExpLen1 = nExpectedLen1;
nExpLen1 = nExpectedLen1;
nExpLen2 = nExpectedLen2;
return hKey;
}
@ -238,7 +238,7 @@ static void test_SHQUeryValueEx(void)
todo_wine
{
ok( (0 == strcmp("", buf)) || (0 == strcmp(sTestpath2, buf)),
"Expected empty or unexpanded string (win98), got (%s)\n", buf);
"Expected empty or unexpanded string (win98), got (%s)\n", buf);
}
ok( dwSize >= nUsedBuffer2, "Buffer size (%u) should be >= (%u)\n", dwSize, nUsedBuffer2);

View file

@ -704,7 +704,7 @@ static void test_StrRStrI(void)
static const WCHAR wszPattern4[] = {'a','b',0};
LPWSTR retW;
LPSTR retA;
check_strrstri(A, szTest, 4, "A", szTest+1);
check_strrstri(A, szTest, 4, "aX", szTest+1);
check_strrstri(A, szTest, 4, "Ay", NULL);

View file

@ -13,6 +13,7 @@ extern void func_ordinal(void);
extern void func_path(void);
extern void func_shreg(void);
extern void func_string(void);
extern void func_url(void);
const struct test winetest_testlist[] =
{
@ -23,5 +24,6 @@ const struct test winetest_testlist[] =
{ "path", func_path },
{ "shreg", func_shreg },
{ "string", func_string },
{ "url", func_url },
{ 0, 0 }
};

View file

@ -0,0 +1,797 @@
/* Unit test suite for Path functions
*
* Copyright 2002 Matthew Mastracci
* Copyright 2007 Detlef Riekenberg
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdio.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "shlwapi.h"
#include "wininet.h"
/* ################ */
static HMODULE hShlwapi;
static HRESULT (WINAPI *pUrlCanonicalizeW)(LPCWSTR, LPWSTR, LPDWORD, DWORD);
static const char* TEST_URL_1 = "http://www.winehq.org/tests?date=10/10/1923";
static const char* TEST_URL_2 = "http://localhost:8080/tests%2e.html?date=Mon%2010/10/1923";
static const char* TEST_URL_3 = "http://foo:bar@localhost:21/internal.php?query=x&return=y";
static const WCHAR winehqW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/',0};
static const CHAR winehqA[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/',0};
/* ################ */
typedef struct _TEST_URL_CANONICALIZE {
const char *url;
DWORD flags;
HRESULT expectret;
const char *expecturl;
} TEST_URL_CANONICALIZE;
static const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = {
/*FIXME {"http://www.winehq.org/tests/../tests/../..", 0, S_OK, "http://www.winehq.org/"},*/
{"http://www.winehq.org/tests/../tests", 0, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests\n", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests\r", 0, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests\r", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests"},
{"http://www.winehq.org/tests/../tests/", 0, S_OK, "http://www.winehq.org/tests/"},
{"http://www.winehq.org/tests/../tests/..", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/../tests/../", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/..", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/../", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/..?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
{"http://www.winehq.org/tests/../?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y"},
{"http://www.winehq.org/tests/..#example", 0, S_OK, "http://www.winehq.org/#example"},
{"http://www.winehq.org/tests/../#example", 0, S_OK, "http://www.winehq.org/#example"},
{"http://www.winehq.org/tests\\../#example", 0, S_OK, "http://www.winehq.org/#example"},
{"http://www.winehq.org/tests/..\\#example", 0, S_OK, "http://www.winehq.org/#example"},
{"http://www.winehq.org\\tests/../#example", 0, S_OK, "http://www.winehq.org/#example"},
{"http://www.winehq.org/tests/../#example", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example"},
{"http://www.winehq.org/tests/foo bar", URL_ESCAPE_SPACES_ONLY| URL_DONT_ESCAPE_EXTRA_INFO , S_OK, "http://www.winehq.org/tests/foo%20bar"},
{"http://www.winehq.org/tests/foo%20bar", URL_UNESCAPE , S_OK, "http://www.winehq.org/tests/foo bar"},
{"file:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"},
{"file:///c:/tests\\foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"},
{"file:///c:/tests/foo%20bar", 0, S_OK, "file:///c:/tests/foo%20bar"},
{"file:///c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
{"file://c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
{"file://c:/tests\\../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
{"file://c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
{"file:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\\\tests\\foo bar"},
{"file:///c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo bar"},
{"file:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, S_OK, "file:///c:/tests/foo bar"},
{"http://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/site/about"},
{"file_://www.winehq.org/site/about", URL_FILE_USE_PATHURL, S_OK, "file_://www.winehq.org/site/about"},
{"c:\\dir\\file", 0, S_OK, "file:///c:/dir/file"},
{"file:///c:\\dir\\file", 0, S_OK, "file:///c:/dir/file"},
{"c:dir\\file", 0, S_OK, "file:///c:dir/file"},
{"c:\\tests\\foo bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar"},
{"c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo%20bar"},
{"A", 0, S_OK, "A"},
{"", 0, S_OK, ""}
};
/* ################ */
typedef struct _TEST_URL_ESCAPE {
const char *url;
DWORD flags;
DWORD expectescaped;
HRESULT expectret;
const char *expecturl;
} TEST_URL_ESCAPE;
static const TEST_URL_ESCAPE TEST_ESCAPE[] = {
{"http://www.winehq.org/tests0", 0, 0, S_OK, "http://www.winehq.org/tests0"},
{"http://www.winehq.org/tests1\n", 0, 0, S_OK, "http://www.winehq.org/tests1%0A"},
{"http://www.winehq.org/tests2\r", 0, 0, S_OK, "http://www.winehq.org/tests2%0D"},
{"http://www.winehq.org/tests3\r", URL_ESCAPE_SPACES_ONLY|URL_ESCAPE_UNSAFE, 0, S_OK, "http://www.winehq.org/tests3\r"},
{"http://www.winehq.org/tests4\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests4\r"},
{"http://www.winehq.org/tests5\r", URL_WININET_COMPATIBILITY|URL_ESCAPE_SPACES_ONLY, 0, S_OK, "http://www.winehq.org/tests5\r"},
{"/direct/swhelp/series6/6.2i_latestservicepack.dat\r", URL_ESCAPE_SPACES_ONLY, 0, S_OK, "/direct/swhelp/series6/6.2i_latestservicepack.dat\r"},
{"file://////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file://///foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file:////foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file:///localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
{"file:///foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file://loCalHost/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file://foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file:/localhost/foo/bar\\baz", 0, 0, S_OK, "file:///localhost/foo/bar/baz"},
{"file:/foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file:foo/bar\\baz", 0, 0, S_OK, "file:foo/bar/baz"},
{"file:\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file:\\\\foo/bar\\baz", 0, 0, S_OK, "file://foo/bar/baz"},
{"file:\\\\\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file:\\\\localhost\\foo/bar\\baz", 0, 0, S_OK, "file:///foo/bar/baz"},
{"file:///f oo/b?a r\\baz", 0, 0, S_OK, "file:///f%20oo/b?a r\\baz"},
{"file:///foo/b#a r\\baz", 0, 0, S_OK, "file:///foo/b%23a%20r/baz"},
{"file:///f o^&`{}|][\"<>\\%o/b#a r\\baz", 0, 0, S_OK, "file:///f%20o%5E%26%60%7B%7D%7C%5D%5B%22%3C%3E/%o/b%23a%20r/baz"},
{"file:///f o%o/b?a r\\b%az", URL_ESCAPE_PERCENT, 0, S_OK, "file:///f%20o%25o/b?a r\\b%az"},
{"file:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "file:%2Ffoo%2Fbar%5Cbaz"},
{"foo/b%ar\\ba?z\\", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%ar%5Cba%3Fz%5C"},
{"foo/b%ar\\ba?z\\", URL_ESCAPE_PERCENT | URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "foo%2Fb%25ar%5Cba%3Fz%5C"},
{"foo/bar\\ba?z\\", 0, 0, S_OK, "foo/bar%5Cba?z\\"},
{"/foo/bar\\ba?z\\", 0, 0, S_OK, "/foo/bar%5Cba?z\\"},
{"/foo/bar\\ba#z\\", 0, 0, S_OK, "/foo/bar%5Cba#z\\"},
{"/foo/%5C", 0, 0, S_OK, "/foo/%5C"},
{"/foo/%5C", URL_ESCAPE_PERCENT, 0, S_OK, "/foo/%255C"},
{"http://////foo/bar\\baz", 0, 0, S_OK, "http://////foo/bar/baz"},
{"http://///foo/bar\\baz", 0, 0, S_OK, "http://///foo/bar/baz"},
{"http:////foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
{"http:///foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
{"http://localhost/foo/bar\\baz", 0, 0, S_OK, "http://localhost/foo/bar/baz"},
{"http://foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
{"http:/foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
{"http:foo/bar\\ba?z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba?z\\"},
{"http:foo/bar\\ba#z\\", 0, 0, S_OK, "http:foo%2Fbar%2Fba#z\\"},
{"http:\\foo/bar\\baz", 0, 0, S_OK, "http:/foo/bar/baz"},
{"http:\\\\foo/bar\\baz", 0, 0, S_OK, "http://foo/bar/baz"},
{"http:\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:///foo/bar/baz"},
{"http:\\\\\\\\foo/bar\\baz", 0, 0, S_OK, "http:////foo/bar/baz"},
{"http:/fo ?o/b ar\\baz", 0, 0, S_OK, "http:/fo%20?o/b ar\\baz"},
{"http:fo ?o/b ar\\baz", 0, 0, S_OK, "http:fo%20?o/b ar\\baz"},
{"http:/foo/bar\\baz", URL_ESCAPE_SEGMENT_ONLY, 0, S_OK, "http:%2Ffoo%2Fbar%5Cbaz"},
{"https://foo/bar\\baz", 0, 0, S_OK, "https://foo/bar/baz"},
{"https:/foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
{"https:\\foo/bar\\baz", 0, 0, S_OK, "https:/foo/bar/baz"},
{"foo:////foo/bar\\baz", 0, 0, S_OK, "foo:////foo/bar%5Cbaz"},
{"foo:///foo/bar\\baz", 0, 0, S_OK, "foo:///foo/bar%5Cbaz"},
{"foo://localhost/foo/bar\\baz", 0, 0, S_OK, "foo://localhost/foo/bar%5Cbaz"},
{"foo://foo/bar\\baz", 0, 0, S_OK, "foo://foo/bar%5Cbaz"},
{"foo:/foo/bar\\baz", 0, 0, S_OK, "foo:/foo/bar%5Cbaz"},
{"foo:foo/bar\\baz", 0, 0, S_OK, "foo:foo%2Fbar%5Cbaz"},
{"foo:\\foo/bar\\baz", 0, 0, S_OK, "foo:%5Cfoo%2Fbar%5Cbaz"},
{"foo:/foo/bar\\ba?\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba?\\z"},
{"foo:/foo/bar\\ba#\\z", 0, 0, S_OK, "foo:/foo/bar%5Cba#\\z"},
{"mailto:/fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:%2Ffo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
{"mailto:fo/o@b\\%a?\\r.b#\\az", 0, 0, S_OK, "mailto:fo%2Fo@b%5C%a%3F%5Cr.b%23%5Caz"},
{"mailto:fo/o@b\\%a?\\r.b#\\az", URL_ESCAPE_PERCENT, 0, S_OK, "mailto:fo%2Fo@b%5C%25a%3F%5Cr.b%23%5Caz"},
{"ftp:fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:fo%2Fo@bar.baz%2Ffoo%2Fbar"},
{"ftp:/fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:/fo/o@bar.baz/foo/bar"},
{"ftp://fo/o@bar.baz/fo?o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo?o\\bar"},
{"ftp://fo/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://fo/o@bar.baz/fo#o\\bar"},
{"ftp://localhost/o@bar.baz/fo#o\\bar", 0, 0, S_OK, "ftp://localhost/o@bar.baz/fo#o\\bar"},
{"ftp:///fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:///fo/o@bar.baz/foo/bar"},
{"ftp:////fo/o@bar.baz/foo/bar", 0, 0, S_OK, "ftp:////fo/o@bar.baz/foo/bar"}
};
/* ################ */
typedef struct _TEST_URL_COMBINE {
const char *url1;
const char *url2;
DWORD flags;
HRESULT expectret;
const char *expecturl;
} TEST_URL_COMBINE;
static const TEST_URL_COMBINE TEST_COMBINE[] = {
{"http://www.winehq.org/tests", "tests1", 0, S_OK, "http://www.winehq.org/tests1"},
{"http://www.%77inehq.org/tests", "tests1", 0, S_OK, "http://www.%77inehq.org/tests1"},
/*FIXME {"http://www.winehq.org/tests", "../tests2", 0, S_OK, "http://www.winehq.org/tests2"},*/
{"http://www.winehq.org/tests/", "../tests3", 0, S_OK, "http://www.winehq.org/tests3"},
{"http://www.winehq.org/tests/test1", "test2", 0, S_OK, "http://www.winehq.org/tests/test2"},
{"http://www.winehq.org/tests/../tests", "tests4", 0, S_OK, "http://www.winehq.org/tests4"},
{"http://www.winehq.org/tests/../tests/", "tests5", 0, S_OK, "http://www.winehq.org/tests/tests5"},
{"http://www.winehq.org/tests/../tests/", "/tests6/..", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/../tests/..", "tests7/..", 0, S_OK, "http://www.winehq.org/"},
{"http://www.winehq.org/tests/?query=x&return=y", "tests8", 0, S_OK, "http://www.winehq.org/tests/tests8"},
{"http://www.winehq.org/tests/#example", "tests9", 0, S_OK, "http://www.winehq.org/tests/tests9"},
{"http://www.winehq.org/tests/../tests/", "/tests10/..", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests10/.."},
{"http://www.winehq.org/tests/../", "tests11", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../tests11"},
{"file:///C:\\dir\\file.txt", "test.txt", 0, S_OK, "file:///C:/dir/test.txt"},
{"http://www.winehq.org/test/", "test%20file.txt", 0, S_OK, "http://www.winehq.org/test/test%20file.txt"},
{"http://www.winehq.org/test/", "test%20file.txt", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org/test/test%20file.txt"},
{"http://www.winehq.org%2ftest/", "test%20file.txt", URL_FILE_USE_PATHURL, S_OK, "http://www.winehq.org%2ftest/test%20file.txt"},
{"xxx:@MSITStore:file.chm/file.html", "dir/file", 0, S_OK, "xxx:dir/file"},
{"mk:@MSITStore:file.chm::/file.html", "/dir/file", 0, S_OK, "mk:@MSITStore:file.chm::/dir/file"},
{"mk:@MSITStore:file.chm::/file.html", "mk:@MSITStore:file.chm::/dir/file", 0, S_OK, "mk:@MSITStore:file.chm::/dir/file"},
{"foo:today", "foo:calendar", 0, S_OK, "foo:calendar"},
{"foo:today", "bar:calendar", 0, S_OK, "bar:calendar"},
{"foo:/today", "foo:calendar", 0, S_OK, "foo:/calendar"},
{"foo:/today/", "foo:calendar", 0, S_OK, "foo:/today/calendar"},
};
/* ################ */
static const struct {
const char *path;
const char *url;
DWORD ret;
} TEST_URLFROMPATH [] = {
{"foo", "file:foo", S_OK},
{"foo\\bar", "file:foo/bar", S_OK},
{"\\foo\\bar", "file:///foo/bar", S_OK},
{"c:\\foo\\bar", "file:///c:/foo/bar", S_OK},
{"c:foo\\bar", "file:///c:foo/bar", S_OK},
{"c:\\foo/b a%r", "file:///c:/foo/b%20a%25r", S_OK},
{"c:\\foo\\foo bar", "file:///c:/foo/foo%20bar", S_OK},
#if 0
/* The following test fails on native shlwapi as distributed with Win95/98.
* Wine matches the behaviour of later versions.
*/
{"xx:c:\\foo\\bar", "xx:c:\\foo\\bar", S_FALSE}
#endif
};
/* ################ */
static struct {
char url[30];
const char *expect;
} TEST_URL_UNESCAPE[] = {
{"file://foo/bar", "file://foo/bar"},
{"file://fo%20o%5Ca/bar", "file://fo o\\a/bar"}
};
/* ################ */
static const struct {
const char *path;
BOOL expect;
} TEST_PATH_IS_URL[] = {
{"http://foo/bar", TRUE},
{"c:\\foo\\bar", FALSE},
{"foo://foo/bar", TRUE},
{"foo\\bar", FALSE},
{"foo.bar", FALSE},
{"bogusscheme:", TRUE},
{"http:partial", TRUE}
};
/* ################ */
static const struct {
const char *url;
BOOL expectOpaque;
BOOL expectFile;
} TEST_URLIS_ATTRIBS[] = {
{ "ftp:", FALSE, FALSE },
{ "http:", FALSE, FALSE },
{ "gopher:", FALSE, FALSE },
{ "mailto:", TRUE, FALSE },
{ "news:", FALSE, FALSE },
{ "nntp:", FALSE, FALSE },
{ "telnet:", FALSE, FALSE },
{ "wais:", FALSE, FALSE },
{ "file:", FALSE, TRUE },
{ "mk:", FALSE, FALSE },
{ "https:", FALSE, FALSE },
{ "shell:", TRUE, FALSE },
{ "https:", FALSE, FALSE },
{ "snews:", FALSE, FALSE },
{ "local:", FALSE, FALSE },
{ "javascript:", TRUE, FALSE },
{ "vbscript:", TRUE, FALSE },
{ "about:", TRUE, FALSE },
{ "res:", FALSE, FALSE },
{ "bogusscheme:", FALSE, FALSE },
{ "file:\\\\e:\\b\\c", FALSE, TRUE },
{ "file://e:/b/c", FALSE, TRUE },
{ "http:partial", FALSE, FALSE },
{ "mailto://www.winehq.org/test.html", TRUE, FALSE },
{ "file:partial", FALSE, TRUE }
};
/* ########################### */
static LPWSTR GetWideString(const char* szString)
{
LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
MultiByteToWideChar(0, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
return wszString;
}
static void FreeWideString(LPWSTR wszString)
{
HeapFree(GetProcessHeap(), 0, wszString);
}
/* ########################### */
static void hash_url(const char* szUrl)
{
LPCSTR szTestUrl = szUrl;
LPWSTR wszTestUrl = GetWideString(szTestUrl);
DWORD cbSize = sizeof(DWORD);
DWORD dwHash1, dwHash2;
ok(UrlHashA(szTestUrl, (LPBYTE)&dwHash1, cbSize) == S_OK, "UrlHashA didn't return S_OK\n");
ok(UrlHashW(wszTestUrl, (LPBYTE)&dwHash2, cbSize) == S_OK, "UrlHashW didn't return S_OK\n");
FreeWideString(wszTestUrl);
ok(dwHash1 == dwHash2, "Hashes didn't compare\n");
}
static void test_UrlHash(void)
{
hash_url(TEST_URL_1);
hash_url(TEST_URL_2);
hash_url(TEST_URL_3);
}
/* ########################### */
static void test_url_part(const char* szUrl, DWORD dwPart, DWORD dwFlags, const char* szExpected)
{
CHAR szPart[INTERNET_MAX_URL_LENGTH];
WCHAR wszPart[INTERNET_MAX_URL_LENGTH];
LPWSTR wszUrl = GetWideString(szUrl);
LPWSTR wszConvertedPart;
DWORD dwSize;
dwSize = INTERNET_MAX_URL_LENGTH;
ok( UrlGetPartA(szUrl, szPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartA for \"%s\" part 0x%08x didn't return S_OK but \"%s\"\n", szUrl, dwPart, szPart);
dwSize = INTERNET_MAX_URL_LENGTH;
ok( UrlGetPartW(wszUrl, wszPart, &dwSize, dwPart, dwFlags) == S_OK, "UrlGetPartW didn't return S_OK\n" );
wszConvertedPart = GetWideString(szPart);
ok(lstrcmpW(wszPart,wszConvertedPart)==0, "Strings didn't match between ascii and unicode UrlGetPart!\n");
FreeWideString(wszUrl);
FreeWideString(wszConvertedPart);
/* Note that v6.0 and later don't return '?' with the query */
ok(strcmp(szPart,szExpected)==0 ||
(*szExpected=='?' && !strcmp(szPart,szExpected+1)),
"Expected %s, but got %s\n", szExpected, szPart);
}
/* ########################### */
static void test_UrlGetPart(void)
{
CHAR szPart[INTERNET_MAX_URL_LENGTH];
DWORD dwSize;
HRESULT res;
dwSize = sizeof szPart;
szPart[0]='x'; szPart[1]=0;
res = UrlGetPartA("hi", szPart, &dwSize, URL_PART_SCHEME, 0);
todo_wine {
ok (res==S_FALSE, "UrlGetPartA(\"hi\") returned %08X\n", res);
ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart);
}
dwSize = sizeof szPart;
szPart[0]='x'; szPart[1]=0;
res = UrlGetPartA("hi", szPart, &dwSize, URL_PART_QUERY, 0);
todo_wine {
ok (res==S_FALSE, "UrlGetPartA(\"hi\") returned %08X\n", res);
ok(szPart[0]==0, "UrlGetPartA(\"hi\") return \"%s\" instead of \"\"\n", szPart);
}
test_url_part(TEST_URL_3, URL_PART_HOSTNAME, 0, "localhost");
test_url_part(TEST_URL_3, URL_PART_PORT, 0, "21");
test_url_part(TEST_URL_3, URL_PART_USERNAME, 0, "foo");
test_url_part(TEST_URL_3, URL_PART_PASSWORD, 0, "bar");
test_url_part(TEST_URL_3, URL_PART_SCHEME, 0, "http");
test_url_part(TEST_URL_3, URL_PART_QUERY, 0, "?query=x&return=y");
}
/* ########################### */
static void test_url_escape(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
{
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
DWORD dwEscaped;
WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
WCHAR *urlW, *expected_urlW;
dwEscaped=INTERNET_MAX_URL_LENGTH;
ok(UrlEscapeA(szUrl, szReturnUrl, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeA didn't return 0x%08x from \"%s\"\n", dwExpectReturn, szUrl);
ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", szExpectUrl, szReturnUrl, szUrl);
dwEscaped = INTERNET_MAX_URL_LENGTH;
urlW = GetWideString(szUrl);
expected_urlW = GetWideString(szExpectUrl);
ok(UrlEscapeW(urlW, ret_urlW, &dwEscaped, dwFlags) == dwExpectReturn, "UrlEscapeW didn't return 0x%08x from \"%s\"\n", dwExpectReturn, szUrl);
WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
ok(lstrcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08x\n", szExpectUrl, szReturnUrl, szUrl, dwFlags);
FreeWideString(urlW);
FreeWideString(expected_urlW);
}
static void test_url_canonicalize(const char *szUrl, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
{
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
LPWSTR wszUrl = GetWideString(szUrl);
LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
LPWSTR wszConvertedUrl;
DWORD dwSize;
dwSize = INTERNET_MAX_URL_LENGTH;
ok(UrlCanonicalizeA(szUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
ok(UrlCanonicalizeA(szUrl, szReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeA didn't return 0x%08x\n", dwExpectReturn);
ok(strcmp(szReturnUrl,szExpectUrl)==0, "UrlCanonicalizeA dwFlags 0x%08x Expected \"%s\", but got \"%s\"\n", dwFlags, szExpectUrl, szReturnUrl);
dwSize = INTERNET_MAX_URL_LENGTH;
ok(UrlCanonicalizeW(wszUrl, NULL, &dwSize, dwFlags) != dwExpectReturn, "Unexpected return for NULL buffer\n");
ok(UrlCanonicalizeW(wszUrl, wszReturnUrl, &dwSize, dwFlags) == dwExpectReturn, "UrlCanonicalizeW didn't return 0x%08x\n", dwExpectReturn);
wszConvertedUrl = GetWideString(szReturnUrl);
ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCanonicalize!\n");
FreeWideString(wszConvertedUrl);
FreeWideString(wszUrl);
FreeWideString(wszExpectUrl);
}
static void test_UrlEscape(void)
{
DWORD size;
HRESULT ret;
unsigned int i;
ret = UrlEscapeA("/woningplan/woonkamer basis.swf", NULL, &size, URL_ESCAPE_SPACES_ONLY);
ok(ret == E_INVALIDARG, "got %x, expected %x\n", ret, E_INVALIDARG);
for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
test_url_escape(TEST_ESCAPE[i].url, TEST_ESCAPE[i].flags,
TEST_ESCAPE[i].expectret, TEST_ESCAPE[i].expecturl);
}
}
/* ########################### */
static void test_UrlCanonicalizeA(void)
{
unsigned int i;
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
DWORD dwSize;
DWORD urllen;
HRESULT hr;
urllen = lstrlenA(winehqA);
/* buffer has no space for the result */
dwSize=urllen-1;
memset(szReturnUrl, '#', urllen+4);
szReturnUrl[urllen+4] = '\0';
SetLastError(0xdeadbeef);
hr = UrlCanonicalizeA(winehqA, szReturnUrl, &dwSize, URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE);
ok( (hr == E_POINTER) && (dwSize == (urllen + 1)),
"got 0x%x with %u and size %u for '%s' and %u (expected 'E_POINTER' and size %u)\n",
hr, GetLastError(), dwSize, szReturnUrl, lstrlenA(szReturnUrl), urllen+1);
/* buffer has no space for the terminating '\0' */
dwSize=urllen;
memset(szReturnUrl, '#', urllen+4);
szReturnUrl[urllen+4] = '\0';
SetLastError(0xdeadbeef);
hr = UrlCanonicalizeA(winehqA, szReturnUrl, &dwSize, URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE);
ok( (hr == E_POINTER) && (dwSize == (urllen + 1)),
"got 0x%x with %u and size %u for '%s' and %u (expected 'E_POINTER' and size %u)\n",
hr, GetLastError(), dwSize, szReturnUrl, lstrlenA(szReturnUrl), urllen+1);
/* buffer has the required size */
dwSize=urllen+1;
memset(szReturnUrl, '#', urllen+4);
szReturnUrl[urllen+4] = '\0';
SetLastError(0xdeadbeef);
hr = UrlCanonicalizeA(winehqA, szReturnUrl, &dwSize, URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE);
ok( (hr == S_OK) && (dwSize == urllen),
"got 0x%x with %u and size %u for '%s' and %u (expected 'S_OK' and size %u)\n",
hr, GetLastError(), dwSize, szReturnUrl, lstrlenA(szReturnUrl), urllen);
/* buffer is larger as the required size */
dwSize=urllen+2;
memset(szReturnUrl, '#', urllen+4);
szReturnUrl[urllen+4] = '\0';
SetLastError(0xdeadbeef);
hr = UrlCanonicalizeA(winehqA, szReturnUrl, &dwSize, URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE);
ok( (hr == S_OK) && (dwSize == urllen),
"got 0x%x with %u and size %u for '%s' and %u (expected 'S_OK' and size %u)\n",
hr, GetLastError(), dwSize, szReturnUrl, lstrlenA(szReturnUrl), urllen);
/* test url-modification */
for(i=0; i<sizeof(TEST_CANONICALIZE)/sizeof(TEST_CANONICALIZE[0]); i++) {
test_url_canonicalize(TEST_CANONICALIZE[i].url, TEST_CANONICALIZE[i].flags,
TEST_CANONICALIZE[i].expectret, TEST_CANONICALIZE[i].expecturl);
}
/* move to TEST_CANONICALIZE when fixed */
dwSize = sizeof szReturnUrl;
/*LimeWire online installer calls this*/
hr = UrlCanonicalizeA("/uri-res/N2R?urn:sha1:B3K", szReturnUrl, &dwSize,URL_DONT_ESCAPE_EXTRA_INFO | URL_WININET_COMPATIBILITY /*0x82000000*/);
ok(hr==S_OK,"UrlCanonicalizeA returned 0x%08x instead of S_OK\n", hr);
todo_wine {
ok(strcmp(szReturnUrl,"/uri-res/N2R?urn:sha1:B3K")==0, "UrlCanonicalizeA got \"%s\" instead of \"/uri-res/N2R?urn:sha1:B3K\"\n", szReturnUrl);
}
}
/* ########################### */
static void test_UrlCanonicalizeW(void)
{
WCHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
DWORD dwSize;
DWORD urllen;
HRESULT hr;
if (!pUrlCanonicalizeW) {
skip("UrlCanonicalizeW\n");
return;
}
urllen = lstrlenW(winehqW);
/* buffer has no space for the result */
dwSize = (urllen-1);
memset(szReturnUrl, '#', (urllen+4) * sizeof(WCHAR));
szReturnUrl[urllen+4] = '\0';
SetLastError(0xdeadbeef);
hr = pUrlCanonicalizeW(winehqW, szReturnUrl, &dwSize, URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE);
ok( (hr == E_POINTER) && (dwSize == (urllen + 1)),
"got 0x%x with %u and size %u for %u (expected 'E_POINTER' and size %u)\n",
hr, GetLastError(), dwSize, lstrlenW(szReturnUrl), urllen+1);
/* buffer has no space for the terminating '\0' */
dwSize = urllen;
memset(szReturnUrl, '#', (urllen+4) * sizeof(WCHAR));
szReturnUrl[urllen+4] = '\0';
SetLastError(0xdeadbeef);
hr = pUrlCanonicalizeW(winehqW, szReturnUrl, &dwSize, URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE);
ok( (hr == E_POINTER) && (dwSize == (urllen + 1)),
"got 0x%x with %u and size %u for %u (expected 'E_POINTER' and size %u)\n",
hr, GetLastError(), dwSize, lstrlenW(szReturnUrl), urllen+1);
/* buffer has the required size */
dwSize = urllen +1;
memset(szReturnUrl, '#', (urllen+4) * sizeof(WCHAR));
szReturnUrl[urllen+4] = '\0';
SetLastError(0xdeadbeef);
hr = pUrlCanonicalizeW(winehqW, szReturnUrl, &dwSize, URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE);
ok( (hr == S_OK) && (dwSize == urllen),
"got 0x%x with %u and size %u for %u (expected 'S_OK' and size %u)\n",
hr, GetLastError(), dwSize, lstrlenW(szReturnUrl), urllen);
/* buffer is larger as the required size */
dwSize = (urllen+2);
memset(szReturnUrl, '#', (urllen+4) * sizeof(WCHAR));
szReturnUrl[urllen+4] = '\0';
SetLastError(0xdeadbeef);
hr = pUrlCanonicalizeW(winehqW, szReturnUrl, &dwSize, URL_WININET_COMPATIBILITY | URL_ESCAPE_UNSAFE);
ok( (hr == S_OK) && (dwSize == urllen),
"got 0x%x with %u and size %u for %u (expected 'S_OK' and size %u)\n",
hr, GetLastError(), dwSize, lstrlenW(szReturnUrl), urllen);
}
/* ########################### */
static void test_url_combine(const char *szUrl1, const char *szUrl2, DWORD dwFlags, HRESULT dwExpectReturn, const char *szExpectUrl)
{
HRESULT hr;
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
LPWSTR wszUrl1 = GetWideString(szUrl1);
LPWSTR wszUrl2 = GetWideString(szUrl2);
LPWSTR wszExpectUrl = GetWideString(szExpectUrl);
LPWSTR wszConvertedUrl;
DWORD dwSize;
DWORD dwExpectLen = lstrlen(szExpectUrl);
hr = UrlCombineA(szUrl1, szUrl2, NULL, NULL, dwFlags);
ok(hr == E_INVALIDARG, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
dwSize = 0;
hr = UrlCombineA(szUrl1, szUrl2, NULL, &dwSize, dwFlags);
ok(hr == E_POINTER, "Checking length of string, return was 0x%08x, expected 0x%08x\n", hr, E_POINTER);
ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
dwSize--;
hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
ok(hr == E_POINTER, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_POINTER);
ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
ok(hr == dwExpectReturn, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, dwExpectReturn);
ok(dwSize == dwExpectLen, "Got length %d, expected %d\n", dwSize, dwExpectLen);
if(SUCCEEDED(hr)) {
ok(strcmp(szReturnUrl,szExpectUrl)==0, "Expected %s, but got %s\n", szExpectUrl, szReturnUrl);
}
dwSize = 0;
hr = UrlCombineW(wszUrl1, wszUrl2, NULL, &dwSize, dwFlags);
ok(hr == E_POINTER, "Checking length of string, return was 0x%08x, expected 0x%08x\n", hr, E_POINTER);
ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
dwSize--;
hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
ok(hr == E_POINTER, "UrlCombineA returned 0x%08x, expected 0x%08x\n", hr, E_POINTER);
ok(dwSize == dwExpectLen+1, "Got length %d, expected %d\n", dwSize, dwExpectLen+1);
hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
ok(hr == dwExpectReturn, "UrlCombineW returned 0x%08x, expected 0x%08x\n", hr, dwExpectReturn);
ok(dwSize == dwExpectLen, "Got length %d, expected %d\n", dwSize, dwExpectLen);
if(SUCCEEDED(hr)) {
wszConvertedUrl = GetWideString(szReturnUrl);
ok(lstrcmpW(wszReturnUrl, wszConvertedUrl)==0, "Strings didn't match between ascii and unicode UrlCombine!\n");
FreeWideString(wszConvertedUrl);
}
FreeWideString(wszUrl1);
FreeWideString(wszUrl2);
FreeWideString(wszExpectUrl);
}
/* ########################### */
static void test_UrlCombine(void)
{
unsigned int i;
for(i=0; i<sizeof(TEST_COMBINE)/sizeof(TEST_COMBINE[0]); i++) {
test_url_combine(TEST_COMBINE[i].url1, TEST_COMBINE[i].url2, TEST_COMBINE[i].flags,
TEST_COMBINE[i].expectret, TEST_COMBINE[i].expecturl);
}
}
/* ########################### */
static void test_UrlCreateFromPath(void)
{
size_t i;
char ret_url[INTERNET_MAX_URL_LENGTH];
DWORD len, ret;
WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
WCHAR *pathW, *urlW;
for(i = 0; i < sizeof(TEST_URLFROMPATH) / sizeof(TEST_URLFROMPATH[0]); i++) {
len = INTERNET_MAX_URL_LENGTH;
ret = UrlCreateFromPathA(TEST_URLFROMPATH[i].path, ret_url, &len, 0);
ok(ret == TEST_URLFROMPATH[i].ret, "ret %08x from path %s\n", ret, TEST_URLFROMPATH[i].path);
ok(!lstrcmpi(ret_url, TEST_URLFROMPATH[i].url), "url %s from path %s\n", ret_url, TEST_URLFROMPATH[i].path);
ok(len == strlen(ret_url), "ret len %d from path %s\n", len, TEST_URLFROMPATH[i].path);
len = INTERNET_MAX_URL_LENGTH;
pathW = GetWideString(TEST_URLFROMPATH[i].path);
urlW = GetWideString(TEST_URLFROMPATH[i].url);
ret = UrlCreateFromPathW(pathW, ret_urlW, &len, 0);
WideCharToMultiByte(CP_ACP, 0, ret_urlW, -1, ret_url, sizeof(ret_url),0,0);
ok(ret == TEST_URLFROMPATH[i].ret, "ret %08x from path L\"%s\", expected %08x\n",
ret, TEST_URLFROMPATH[i].path, TEST_URLFROMPATH[i].ret);
ok(!lstrcmpiW(ret_urlW, urlW), "got %s expected %s from path L\"%s\"\n", ret_url, TEST_URLFROMPATH[i].url, TEST_URLFROMPATH[i].path);
ok(len == lstrlenW(ret_urlW), "ret len %d from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
FreeWideString(urlW);
FreeWideString(pathW);
}
}
/* ########################### */
static void test_UrlIs(void)
{
BOOL ret;
size_t i;
WCHAR wurl[80];
for(i = 0; i < sizeof(TEST_PATH_IS_URL) / sizeof(TEST_PATH_IS_URL[0]); i++) {
MultiByteToWideChar(CP_ACP, 0, TEST_PATH_IS_URL[i].path, -1, wurl, 80);
ret = UrlIsA( TEST_PATH_IS_URL[i].path, URLIS_URL );
ok( ret == TEST_PATH_IS_URL[i].expect,
"returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
TEST_PATH_IS_URL[i].expect );
ret = UrlIsW( wurl, URLIS_URL );
ok( ret == TEST_PATH_IS_URL[i].expect,
"returned %d from path (UrlIsW) %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
TEST_PATH_IS_URL[i].expect );
}
for(i = 0; i < sizeof(TEST_URLIS_ATTRIBS) / sizeof(TEST_URLIS_ATTRIBS[0]); i++) {
MultiByteToWideChar(CP_ACP, 0, TEST_URLIS_ATTRIBS[i].url, -1, wurl, 80);
ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_OPAQUE);
ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
"returned %d for URLIS_OPAQUE, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
TEST_URLIS_ATTRIBS[i].expectOpaque );
ret = UrlIsA( TEST_URLIS_ATTRIBS[i].url, URLIS_FILEURL);
ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
"returned %d for URLIS_FILEURL, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
TEST_URLIS_ATTRIBS[i].expectFile );
ret = UrlIsW( wurl, URLIS_OPAQUE);
ok( ret == TEST_URLIS_ATTRIBS[i].expectOpaque,
"returned %d for URLIS_OPAQUE (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
TEST_URLIS_ATTRIBS[i].expectOpaque );
ret = UrlIsW( wurl, URLIS_FILEURL);
ok( ret == TEST_URLIS_ATTRIBS[i].expectFile,
"returned %d for URLIS_FILEURL (UrlIsW), url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
TEST_URLIS_ATTRIBS[i].expectFile );
}
}
/* ########################### */
static void test_UrlUnescape(void)
{
CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH];
WCHAR *urlW, *expected_urlW;
DWORD dwEscaped;
size_t i;
static char inplace[] = "file:///C:/Program%20Files";
static WCHAR inplaceW[] = {'f','i','l','e',':','/','/','/','C',':','/',
'P','r','o','g','r','a','m','%','2','0','F','i','l','e','s',0};
for(i=0; i<sizeof(TEST_URL_UNESCAPE)/sizeof(TEST_URL_UNESCAPE[0]); i++) {
dwEscaped=INTERNET_MAX_URL_LENGTH;
ok(UrlUnescapeA(TEST_URL_UNESCAPE[i].url, szReturnUrl, &dwEscaped, 0) == S_OK, "UrlUnescapeA didn't return 0x%08x from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
ok(strcmp(szReturnUrl,TEST_URL_UNESCAPE[i].expect)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url);
dwEscaped = INTERNET_MAX_URL_LENGTH;
urlW = GetWideString(TEST_URL_UNESCAPE[i].url);
expected_urlW = GetWideString(TEST_URL_UNESCAPE[i].expect);
ok(UrlUnescapeW(urlW, ret_urlW, &dwEscaped, 0) == S_OK, "UrlUnescapeW didn't return 0x%08x from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url);
WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0);
ok(lstrcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url, 0L);
FreeWideString(urlW);
FreeWideString(expected_urlW);
}
dwEscaped = sizeof(inplace);
ok(UrlUnescapeA(inplace, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeA failed unexpectedly\n");
dwEscaped = sizeof(inplaceW);
ok(UrlUnescapeW(inplaceW, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeW failed unexpectedly\n");
}
/* ########################### */
START_TEST(url)
{
hShlwapi = GetModuleHandleA("shlwapi.dll");
pUrlCanonicalizeW = (void *) GetProcAddress(hShlwapi, "UrlCanonicalizeW");
test_UrlHash();
test_UrlGetPart();
test_UrlCanonicalizeA();
test_UrlCanonicalizeW();
test_UrlEscape();
test_UrlCombine();
test_UrlCreateFromPath();
test_UrlIs();
test_UrlUnescape();
}

View file

@ -0,0 +1,349 @@
/* File generated automatically from tools/winapi/test.dat; do not edit! */
/* This file can be copied, modified and distributed without restriction. */
/*
* Unit tests for data structure packing
*/
#define WINVER 0x0501
#define _WIN32_IE 0x0501
#define _WIN32_WINNT 0x0501
#define WINE_NOWINSOCK
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "urlmon.h"
#include "wine/test.h"
/***********************************************************************
* Compability macros
*/
#define DWORD_PTR UINT_PTR
#define LONG_PTR INT_PTR
#define ULONG_PTR UINT_PTR
/***********************************************************************
* Windows API extension
*/
#if defined(_MSC_VER) && (_MSC_VER >= 1300) && defined(__cplusplus)
# define FIELD_ALIGNMENT(type, field) __alignof(((type*)0)->field)
#elif defined(__GNUC__)
# define FIELD_ALIGNMENT(type, field) __alignof__(((type*)0)->field)
#else
/* FIXME: Not sure if is possible to do without compiler extension */
#endif
#if defined(_MSC_VER) && (_MSC_VER >= 1300) && defined(__cplusplus)
# define _TYPE_ALIGNMENT(type) __alignof(type)
#elif defined(__GNUC__)
# define _TYPE_ALIGNMENT(type) __alignof__(type)
#else
/*
* FIXME: Not sure if is possible to do without compiler extension
* (if type is not just a name that is, if so the normal)
* TYPE_ALIGNMENT can be used)
*/
#endif
#if defined(TYPE_ALIGNMENT) && defined(_MSC_VER) && _MSC_VER >= 800 && !defined(__cplusplus)
#pragma warning(disable:4116)
#endif
#if !defined(TYPE_ALIGNMENT) && defined(_TYPE_ALIGNMENT)
# define TYPE_ALIGNMENT _TYPE_ALIGNMENT
#endif
/***********************************************************************
* Test helper macros
*/
#ifdef FIELD_ALIGNMENT
# define TEST_FIELD_ALIGNMENT(type, field, align) \
ok(FIELD_ALIGNMENT(type, field) == align, \
"FIELD_ALIGNMENT(" #type ", " #field ") == %d (expected " #align ")\n", \
(int)FIELD_ALIGNMENT(type, field))
#else
# define TEST_FIELD_ALIGNMENT(type, field, align) do { } while (0)
#endif
#define TEST_FIELD_OFFSET(type, field, offset) \
ok(FIELD_OFFSET(type, field) == offset, \
"FIELD_OFFSET(" #type ", " #field ") == %ld (expected " #offset ")\n", \
(long int)FIELD_OFFSET(type, field))
#ifdef _TYPE_ALIGNMENT
#define TEST__TYPE_ALIGNMENT(type, align) \
ok(_TYPE_ALIGNMENT(type) == align, "TYPE_ALIGNMENT(" #type ") == %d (expected " #align ")\n", (int)_TYPE_ALIGNMENT(type))
#else
# define TEST__TYPE_ALIGNMENT(type, align) do { } while (0)
#endif
#ifdef TYPE_ALIGNMENT
#define TEST_TYPE_ALIGNMENT(type, align) \
ok(TYPE_ALIGNMENT(type) == align, "TYPE_ALIGNMENT(" #type ") == %d (expected " #align ")\n", (int)TYPE_ALIGNMENT(type))
#else
# define TEST_TYPE_ALIGNMENT(type, align) do { } while (0)
#endif
#define TEST_TYPE_SIZE(type, size) \
ok(sizeof(type) == size, "sizeof(" #type ") == %d (expected " #size ")\n", ((int) sizeof(type)))
/***********************************************************************
* Test macros
*/
#define TEST_FIELD(type, field_type, field_name, field_offset, field_size, field_align) \
TEST_TYPE_SIZE(field_type, field_size); \
TEST_FIELD_ALIGNMENT(type, field_name, field_align); \
TEST_FIELD_OFFSET(type, field_name, field_offset); \
#define TEST_TYPE(type, size, align) \
TEST_TYPE_ALIGNMENT(type, align); \
TEST_TYPE_SIZE(type, size)
#define TEST_TYPE_POINTER(type, size, align) \
TEST__TYPE_ALIGNMENT(*(type)0, align); \
TEST_TYPE_SIZE(*(type)0, size)
#define TEST_TYPE_SIGNED(type) \
ok((type) -1 < 0, "(" #type ") -1 < 0\n");
#define TEST_TYPE_UNSIGNED(type) \
ok((type) -1 > 0, "(" #type ") -1 > 0\n");
static void test_pack_BINDINFO(void)
{
/* BINDINFO (pack 4) */
TEST_FIELD(BINDINFO, ULONG, cbSize, 0, 4, 4);
TEST_FIELD(BINDINFO, LPWSTR, szExtraInfo, 4, 4, 4);
}
static void test_pack_IBindHost(void)
{
/* IBindHost */
}
static void test_pack_IBindHostVtbl(void)
{
/* IBindHostVtbl (pack 4) */
}
static void test_pack_IBindStatusCallback(void)
{
/* IBindStatusCallback */
}
static void test_pack_IBindStatusCallbackVtbl(void)
{
/* IBindStatusCallbackVtbl (pack 4) */
}
static void test_pack_IBinding(void)
{
/* IBinding */
}
static void test_pack_IBindingVtbl(void)
{
/* IBindingVtbl (pack 4) */
}
static void test_pack_IInternetProtocolInfo(void)
{
/* IInternetProtocolInfo */
}
static void test_pack_IInternetProtocolInfoVtbl(void)
{
/* IInternetProtocolInfoVtbl (pack 4) */
}
static void test_pack_IInternetSession(void)
{
/* IInternetSession */
}
static void test_pack_IInternetSessionVtbl(void)
{
/* IInternetSessionVtbl (pack 4) */
}
static void test_pack_IPersistMoniker(void)
{
/* IPersistMoniker */
}
static void test_pack_IPersistMonikerVtbl(void)
{
/* IPersistMonikerVtbl (pack 4) */
}
static void test_pack_IWinInetHttpInfo(void)
{
/* IWinInetHttpInfo */
}
static void test_pack_IWinInetHttpInfoVtbl(void)
{
/* IWinInetHttpInfoVtbl (pack 4) */
}
static void test_pack_IWinInetInfo(void)
{
/* IWinInetInfo */
}
static void test_pack_IWinInetInfoVtbl(void)
{
/* IWinInetInfoVtbl (pack 4) */
}
static void test_pack_LPBINDHOST(void)
{
/* LPBINDHOST */
TEST_TYPE(LPBINDHOST, 4, 4);
}
static void test_pack_LPBINDING(void)
{
/* LPBINDING */
TEST_TYPE(LPBINDING, 4, 4);
}
static void test_pack_LPBINDSTATUSCALLBACK(void)
{
/* LPBINDSTATUSCALLBACK */
TEST_TYPE(LPBINDSTATUSCALLBACK, 4, 4);
}
static void test_pack_LPIINTERNETPROTOCOLINFO(void)
{
/* LPIINTERNETPROTOCOLINFO */
TEST_TYPE(LPIINTERNETPROTOCOLINFO, 4, 4);
}
static void test_pack_LPIINTERNETSESSION(void)
{
/* LPIINTERNETSESSION */
TEST_TYPE(LPIINTERNETSESSION, 4, 4);
}
static void test_pack_LPPERSISTMONIKER(void)
{
/* LPPERSISTMONIKER */
TEST_TYPE(LPPERSISTMONIKER, 4, 4);
}
static void test_pack_LPREMFORMATETC(void)
{
/* LPREMFORMATETC */
TEST_TYPE(LPREMFORMATETC, 4, 4);
}
static void test_pack_LPREMSECURITY_ATTRIBUTES(void)
{
/* LPREMSECURITY_ATTRIBUTES */
TEST_TYPE(LPREMSECURITY_ATTRIBUTES, 4, 4);
}
static void test_pack_LPWININETHTTPINFO(void)
{
/* LPWININETHTTPINFO */
TEST_TYPE(LPWININETHTTPINFO, 4, 4);
}
static void test_pack_LPWININETINFO(void)
{
/* LPWININETINFO */
TEST_TYPE(LPWININETINFO, 4, 4);
}
static void test_pack_PREMSECURITY_ATTRIBUTES(void)
{
/* PREMSECURITY_ATTRIBUTES */
TEST_TYPE(PREMSECURITY_ATTRIBUTES, 4, 4);
}
static void test_pack_REMSECURITY_ATTRIBUTES(void)
{
/* REMSECURITY_ATTRIBUTES (pack 4) */
TEST_TYPE(REMSECURITY_ATTRIBUTES, 12, 4);
TEST_FIELD(REMSECURITY_ATTRIBUTES, DWORD, nLength, 0, 4, 4);
TEST_FIELD(REMSECURITY_ATTRIBUTES, DWORD, lpSecurityDescriptor, 4, 4, 4);
TEST_FIELD(REMSECURITY_ATTRIBUTES, BOOL, bInheritHandle, 8, 4, 4);
}
static void test_pack_RemBINDINFO(void)
{
/* RemBINDINFO (pack 4) */
TEST_TYPE(RemBINDINFO, 72, 4);
TEST_FIELD(RemBINDINFO, ULONG, cbSize, 0, 4, 4);
TEST_FIELD(RemBINDINFO, LPWSTR, szExtraInfo, 4, 4, 4);
TEST_FIELD(RemBINDINFO, DWORD, grfBindInfoF, 8, 4, 4);
TEST_FIELD(RemBINDINFO, DWORD, dwBindVerb, 12, 4, 4);
TEST_FIELD(RemBINDINFO, LPWSTR, szCustomVerb, 16, 4, 4);
TEST_FIELD(RemBINDINFO, DWORD, cbstgmedData, 20, 4, 4);
TEST_FIELD(RemBINDINFO, DWORD, dwOptions, 24, 4, 4);
TEST_FIELD(RemBINDINFO, DWORD, dwOptionsFlags, 28, 4, 4);
TEST_FIELD(RemBINDINFO, DWORD, dwCodePage, 32, 4, 4);
TEST_FIELD(RemBINDINFO, REMSECURITY_ATTRIBUTES, securityAttributes, 36, 12, 4);
TEST_FIELD(RemBINDINFO, IID, iid, 48, 16, 4);
TEST_FIELD(RemBINDINFO, IUnknown *, pUnk, 64, 4, 4);
TEST_FIELD(RemBINDINFO, DWORD, dwReserved, 68, 4, 4);
}
static void test_pack_RemFORMATETC(void)
{
/* RemFORMATETC (pack 4) */
TEST_TYPE(RemFORMATETC, 20, 4);
TEST_FIELD(RemFORMATETC, DWORD, cfFormat, 0, 4, 4);
TEST_FIELD(RemFORMATETC, DWORD, ptd, 4, 4, 4);
TEST_FIELD(RemFORMATETC, DWORD, dwAspect, 8, 4, 4);
TEST_FIELD(RemFORMATETC, LONG, lindex, 12, 4, 4);
TEST_FIELD(RemFORMATETC, DWORD, tymed, 16, 4, 4);
}
static void test_pack(void)
{
test_pack_BINDINFO();
test_pack_IBindHost();
test_pack_IBindHostVtbl();
test_pack_IBindStatusCallback();
test_pack_IBindStatusCallbackVtbl();
test_pack_IBinding();
test_pack_IBindingVtbl();
test_pack_IInternetProtocolInfo();
test_pack_IInternetProtocolInfoVtbl();
test_pack_IInternetSession();
test_pack_IInternetSessionVtbl();
test_pack_IPersistMoniker();
test_pack_IPersistMonikerVtbl();
test_pack_IWinInetHttpInfo();
test_pack_IWinInetHttpInfoVtbl();
test_pack_IWinInetInfo();
test_pack_IWinInetInfoVtbl();
test_pack_LPBINDHOST();
test_pack_LPBINDING();
test_pack_LPBINDSTATUSCALLBACK();
test_pack_LPIINTERNETPROTOCOLINFO();
test_pack_LPIINTERNETSESSION();
test_pack_LPPERSISTMONIKER();
test_pack_LPREMFORMATETC();
test_pack_LPREMSECURITY_ATTRIBUTES();
test_pack_LPWININETHTTPINFO();
test_pack_LPWININETINFO();
test_pack_PREMSECURITY_ATTRIBUTES();
test_pack_REMSECURITY_ATTRIBUTES();
test_pack_RemBINDINFO();
test_pack_RemFORMATETC();
}
START_TEST(generated)
{
test_pack();
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,372 @@
/*
* Copyright 2007 Robert Shearman for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#define CONST_VTABLE
#include <wine/test.h>
#include <stdarg.h>
#include <stddef.h>
#include "windef.h"
#include "winbase.h"
#include "ole2.h"
#include "urlmon.h"
#include "wininet.h"
#define DEFINE_EXPECT(func) \
static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
#define SET_EXPECT(func) \
expect_ ## func = TRUE
#define CHECK_EXPECT(func) \
do { \
ok(expect_ ##func, "unexpected call " #func "\n"); \
expect_ ## func = FALSE; \
called_ ## func = TRUE; \
}while(0)
#define CHECK_EXPECT2(func) \
do { \
ok(expect_ ##func, "unexpected call " #func "\n"); \
called_ ## func = TRUE; \
}while(0)
#define CHECK_CALLED(func) \
do { \
ok(called_ ## func, "expected " #func "\n"); \
expect_ ## func = called_ ## func = FALSE; \
}while(0)
#define CHECK_NOT_CALLED(func) \
do { \
ok(!called_ ## func, "unexpected " #func "\n"); \
expect_ ## func = called_ ## func = FALSE; \
}while(0)
#define CLEAR_CALLED(func) \
expect_ ## func = called_ ## func = FALSE
DEFINE_EXPECT(QueryInterface_IServiceProvider);
DEFINE_EXPECT(OnStartBinding);
DEFINE_EXPECT(OnProgress_FINDINGRESOURCE);
DEFINE_EXPECT(OnProgress_CONNECTING);
DEFINE_EXPECT(OnProgress_SENDINGREQUEST);
DEFINE_EXPECT(OnProgress_MIMETYPEAVAILABLE);
DEFINE_EXPECT(OnProgress_BEGINDOWNLOADDATA);
DEFINE_EXPECT(OnProgress_DOWNLOADINGDATA);
DEFINE_EXPECT(OnProgress_ENDDOWNLOADDATA);
DEFINE_EXPECT(OnStopBinding);
DEFINE_EXPECT(OnDataAvailable);
DEFINE_EXPECT(GetBindInfo);
static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
static WCHAR INDEX_HTML[MAX_PATH];
static const char szHtmlDoc[] = "<HTML></HTML>";
static HRESULT WINAPI statusclb_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
{
if (IsEqualGUID(&IID_IBindStatusCallback, riid) ||
IsEqualGUID(&IID_IUnknown, riid))
{
*ppv = iface;
return S_OK;
}
else if (IsEqualGUID(&IID_IServiceProvider, riid))
{
CHECK_EXPECT(QueryInterface_IServiceProvider);
}
return E_NOINTERFACE;
}
static ULONG WINAPI statusclb_AddRef(IBindStatusCallback *iface)
{
return 2;
}
static ULONG WINAPI statusclb_Release(IBindStatusCallback *iface)
{
return 1;
}
static HRESULT WINAPI statusclb_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
IBinding *pib)
{
HRESULT hres;
IMoniker *mon;
CHECK_EXPECT(OnStartBinding);
ok(pib != NULL, "pib should not be NULL\n");
hres = IBinding_QueryInterface(pib, &IID_IMoniker, (void**)&mon);
ok(hres == E_NOINTERFACE, "IBinding should not have IMoniker interface\n");
if(SUCCEEDED(hres))
IMoniker_Release(mon);
return S_OK;
}
static HRESULT WINAPI statusclb_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI statusclb_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI statusclb_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
{
switch(ulStatusCode) {
case BINDSTATUS_FINDINGRESOURCE:
CHECK_EXPECT(OnProgress_FINDINGRESOURCE);
break;
case BINDSTATUS_CONNECTING:
CHECK_EXPECT(OnProgress_CONNECTING);
break;
case BINDSTATUS_SENDINGREQUEST:
CHECK_EXPECT(OnProgress_SENDINGREQUEST);
break;
case BINDSTATUS_MIMETYPEAVAILABLE:
CHECK_EXPECT(OnProgress_MIMETYPEAVAILABLE);
break;
case BINDSTATUS_BEGINDOWNLOADDATA:
CHECK_EXPECT(OnProgress_BEGINDOWNLOADDATA);
ok(szStatusText != NULL, "szStatusText == NULL\n");
break;
case BINDSTATUS_DOWNLOADINGDATA:
CHECK_EXPECT2(OnProgress_DOWNLOADINGDATA);
break;
case BINDSTATUS_ENDDOWNLOADDATA:
CHECK_EXPECT(OnProgress_ENDDOWNLOADDATA);
ok(szStatusText != NULL, "szStatusText == NULL\n");
break;
case BINDSTATUS_CACHEFILENAMEAVAILABLE:
ok(szStatusText != NULL, "szStatusText == NULL\n");
break;
default:
todo_wine { ok(0, "unexpexted code %d\n", ulStatusCode); }
};
return S_OK;
}
static HRESULT WINAPI statusclb_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
{
CHECK_EXPECT(OnStopBinding);
/* ignore DNS failure */
if (hresult != HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED))
{
ok(SUCCEEDED(hresult), "Download failed: %08x\n", hresult);
ok(szError == NULL, "szError should be NULL\n");
}
return S_OK;
}
static HRESULT WINAPI statusclb_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
{
DWORD cbSize;
CHECK_EXPECT(GetBindInfo);
*grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
cbSize = pbindinfo->cbSize;
memset(pbindinfo, 0, cbSize);
pbindinfo->cbSize = cbSize;
return S_OK;
}
static HRESULT WINAPI statusclb_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
{
HRESULT hres;
DWORD readed;
BYTE buf[512];
CHECK_EXPECT2(OnDataAvailable);
if (0)
{
/* FIXME: Uncomment after removing BindToStorage hack. */
ok(pformatetc != NULL, "pformatetx == NULL\n");
if(pformatetc) {
ok(pformatetc->cfFormat == 0xc02d, "clipformat=%x\n", pformatetc->cfFormat);
ok(pformatetc->ptd == NULL, "ptd = %p\n", pformatetc->ptd);
ok(pformatetc->dwAspect == 1, "dwAspect=%u\n", pformatetc->dwAspect);
ok(pformatetc->lindex == -1, "lindex=%d\n", pformatetc->lindex);
ok(pformatetc->tymed == TYMED_ISTREAM, "tymed=%u\n", pformatetc->tymed);
}
ok(pstgmed != NULL, "stgmeg == NULL\n");
if(pstgmed) {
ok(pstgmed->tymed == TYMED_ISTREAM, "tymed=%u\n", pstgmed->tymed);
ok(U(*pstgmed).pstm != NULL, "pstm == NULL\n");
ok(pstgmed->pUnkForRelease != NULL, "pUnkForRelease == NULL\n");
}
}
if(U(*pstgmed).pstm) {
do hres = IStream_Read(U(*pstgmed).pstm, buf, 512, &readed);
while(hres == S_OK);
ok(hres == S_FALSE || hres == E_PENDING, "IStream_Read returned %08x\n", hres);
}
return S_OK;
}
static HRESULT WINAPI statusclb_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
statusclb_QueryInterface,
statusclb_AddRef,
statusclb_Release,
statusclb_OnStartBinding,
statusclb_GetPriority,
statusclb_OnLowResource,
statusclb_OnProgress,
statusclb_OnStopBinding,
statusclb_GetBindInfo,
statusclb_OnDataAvailable,
statusclb_OnObjectAvailable
};
static IBindStatusCallback BindStatusCallback = { &BindStatusCallbackVtbl };
static void set_file_url(void)
{
int len;
static const WCHAR wszFile[] = {'f','i','l','e',':','/','/'};
memcpy(INDEX_HTML, wszFile, sizeof(wszFile));
len = sizeof(wszFile)/sizeof(WCHAR);
INDEX_HTML[len++] = '/';
len += GetCurrentDirectoryW(sizeof(INDEX_HTML)/sizeof(WCHAR)-len, INDEX_HTML+len);
INDEX_HTML[len++] = '\\';
memcpy(INDEX_HTML+len, wszIndexHtml, sizeof(wszIndexHtml));
}
static void create_file(void)
{
HANDLE file;
DWORD size;
file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
if(file == INVALID_HANDLE_VALUE)
return;
WriteFile(file, szHtmlDoc, sizeof(szHtmlDoc)-1, &size, NULL);
CloseHandle(file);
set_file_url();
}
static void test_URLOpenBlockingStreamW(void)
{
HRESULT hr;
IStream *pStream;
char buffer[256];
hr = URLOpenBlockingStreamW(NULL, NULL, &pStream, 0, &BindStatusCallback);
ok(hr == E_INVALIDARG, "URLOpenBlockingStreamW should have failed with E_INVALIDARG instead of 0x%08x\n", hr);
hr = URLOpenBlockingStreamW(NULL, INDEX_HTML, NULL, 0, &BindStatusCallback);
ok(hr == E_INVALIDARG, "URLOpenBlockingStreamW should have failed with E_INVALIDARG instead of 0x%08x\n", hr);
SET_EXPECT(GetBindInfo);
SET_EXPECT(QueryInterface_IServiceProvider);
SET_EXPECT(OnStartBinding);
SET_EXPECT(OnProgress_SENDINGREQUEST);
SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
SET_EXPECT(OnProgress_BEGINDOWNLOADDATA);
SET_EXPECT(OnProgress_ENDDOWNLOADDATA);
SET_EXPECT(OnStopBinding);
hr = URLOpenBlockingStreamW(NULL, INDEX_HTML, &pStream, 0, &BindStatusCallback);
ok(hr == S_OK, "URLOpenBlockingStreamW failed with error 0x%08x\n", hr);
CHECK_CALLED(GetBindInfo);
todo_wine CHECK_CALLED(QueryInterface_IServiceProvider);
CHECK_CALLED(OnStartBinding);
CHECK_CALLED(OnProgress_SENDINGREQUEST);
CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA);
CHECK_CALLED(OnProgress_ENDDOWNLOADDATA);
CHECK_CALLED(OnStopBinding);
ok(pStream != NULL, "pStream is NULL\n");
hr = IStream_Read(pStream, buffer, sizeof(buffer), NULL);
ok(hr == S_OK, "IStream_Read failed with error 0x%08x\n", hr);
ok(!memcmp(buffer, szHtmlDoc, sizeof(szHtmlDoc)-1), "read data differs from file\n");
IStream_Release(pStream);
}
static void test_URLOpenStreamW(void)
{
HRESULT hr;
hr = URLOpenStreamW(NULL, NULL, 0, &BindStatusCallback);
ok(hr == E_INVALIDARG, "URLOpenStreamW should have failed with E_INVALIDARG instead of 0x%08x\n", hr);
SET_EXPECT(GetBindInfo);
SET_EXPECT(QueryInterface_IServiceProvider);
SET_EXPECT(OnStartBinding);
SET_EXPECT(OnProgress_SENDINGREQUEST);
SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
SET_EXPECT(OnProgress_BEGINDOWNLOADDATA);
SET_EXPECT(OnProgress_ENDDOWNLOADDATA);
SET_EXPECT(OnDataAvailable);
SET_EXPECT(OnStopBinding);
hr = URLOpenStreamW(NULL, INDEX_HTML, 0, &BindStatusCallback);
ok(hr == S_OK, "URLOpenStreamW failed with error 0x%08x\n", hr);
CHECK_CALLED(GetBindInfo);
todo_wine CHECK_CALLED(QueryInterface_IServiceProvider);
CHECK_CALLED(OnStartBinding);
CHECK_CALLED(OnProgress_SENDINGREQUEST);
CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA);
CHECK_CALLED(OnProgress_ENDDOWNLOADDATA);
CHECK_CALLED(OnDataAvailable);
CHECK_CALLED(OnStopBinding);
}
START_TEST(stream)
{
create_file();
test_URLOpenBlockingStreamW();
test_URLOpenStreamW();
DeleteFileW(wszIndexHtml);
}

View file

@ -0,0 +1,23 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_generated(void);
extern void func_misc(void);
extern void func_protocol(void);
extern void func_stream(void);
extern void func_url(void);
const struct test winetest_testlist[] =
{
{ "generated", func_generated },
{ "misc", func_misc },
{ "protocol", func_protocol },
{ "stream", func_stream },
{ "url", func_url },
{ 0, 0 }
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="urlmon_winetest" type="win32cui" installbase="bin" installname="urlmon_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="urlmon_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>urlmon</library>
<library>user32</library>
<library>kernel32</library>
<library>ole32</library>
<library>uuid</library>
<library>ntdll</library>
<file>generated.c</file>
<file>misc.c</file>
<file>protocol.c</file>
<file>stream.c</file>
<file>url.c</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,511 @@
/* Unit test suite for uxtheme API functions
*
* Copyright 2006 Paul Vriens
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#include <stdarg.h>
#include "windows.h"
#include "vfwmsgs.h"
#include "uxtheme.h"
#include "wine/test.h"
static HRESULT (WINAPI * pCloseThemeData)(HTHEME);
static HRESULT (WINAPI * pGetCurrentThemeName)(LPWSTR, int, LPWSTR, int, LPWSTR, int);
static HTHEME (WINAPI * pGetWindowTheme)(HWND);
static BOOL (WINAPI * pIsAppThemed)(VOID);
static BOOL (WINAPI * pIsThemeActive)(VOID);
static BOOL (WINAPI * pIsThemePartDefined)(HTHEME, int, int);
static HTHEME (WINAPI * pOpenThemeData)(HWND, LPCWSTR);
static HRESULT (WINAPI * pSetWindowTheme)(HWND, LPCWSTR, LPCWSTR);
static HMODULE hUxtheme = 0;
#define UXTHEME_GET_PROC(func) \
p ## func = (void*)GetProcAddress(hUxtheme, #func); \
if(!p ## func) { \
trace("GetProcAddress(%s) failed\n", #func); \
FreeLibrary(hUxtheme); \
return FALSE; \
}
static BOOL InitFunctionPtrs(void)
{
hUxtheme = LoadLibraryA("uxtheme.dll");
if(!hUxtheme) {
trace("Could not load uxtheme.dll\n");
return FALSE;
}
if (hUxtheme)
{
UXTHEME_GET_PROC(CloseThemeData)
UXTHEME_GET_PROC(GetCurrentThemeName)
UXTHEME_GET_PROC(GetWindowTheme)
UXTHEME_GET_PROC(IsAppThemed)
UXTHEME_GET_PROC(IsThemeActive)
UXTHEME_GET_PROC(IsThemePartDefined)
UXTHEME_GET_PROC(OpenThemeData)
UXTHEME_GET_PROC(SetWindowTheme)
}
/* The following functions should be available, if not return FALSE. The Vista functions will
* be checked (at some point in time) within the single tests if needed. All used functions for
* now are present on WinXP, W2K3 and Wine.
*/
if (!pCloseThemeData || !pGetCurrentThemeName ||
!pGetWindowTheme || !pIsAppThemed ||
!pIsThemeActive || !pIsThemePartDefined ||
!pOpenThemeData || !pSetWindowTheme)
return FALSE;
return TRUE;
}
static void test_IsThemed(void)
{
BOOL bThemeActive;
BOOL bAppThemed;
BOOL bTPDefined;
SetLastError(0xdeadbeef);
bThemeActive = pIsThemeActive();
trace("Theming is %s\n", (bThemeActive) ? "active" : "inactive");
todo_wine
ok( GetLastError() == ERROR_SUCCESS,
"Expected ERROR_SUCCESS, got 0x%08x\n",
GetLastError());
/* This test is not themed */
SetLastError(0xdeadbeef);
bAppThemed = pIsAppThemed();
if (bThemeActive)
todo_wine
ok( bAppThemed == FALSE, "Expected FALSE as this test executable is not (yet) themed.\n");
else
/* Although Wine currently returns FALSE, the logic behind it is wrong. It is not a todo_wine though in the testing sense */
ok( bAppThemed == FALSE, "Expected FALSE as this test executable is not (yet) themed.\n");
todo_wine
ok( GetLastError() == ERROR_SUCCESS,
"Expected ERROR_SUCCESS, got 0x%08x\n",
GetLastError());
SetLastError(0xdeadbeef);
bTPDefined = pIsThemePartDefined(NULL, 0 , 0);
ok( bTPDefined == FALSE, "Expected FALSE\n");
ok( GetLastError() == E_HANDLE,
"Expected E_HANDLE, got 0x%08x\n",
GetLastError());
}
static void test_GetWindowTheme(void)
{
HTHEME hTheme;
HWND hWnd;
BOOL bDestroyed;
SetLastError(0xdeadbeef);
hTheme = pGetWindowTheme(NULL);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
todo_wine
ok( GetLastError() == E_HANDLE,
"Expected E_HANDLE, got 0x%08x\n",
GetLastError());
/* Only do the bare minumum to get a valid hwnd */
hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
if (!hWnd) return;
SetLastError(0xdeadbeef);
hTheme = pGetWindowTheme(hWnd);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
bDestroyed = DestroyWindow(hWnd);
if (!bDestroyed)
trace("Window %p couldn't be destroyed : 0x%08x\n",
hWnd, GetLastError());
}
static void test_SetWindowTheme(void)
{
HRESULT hRes;
HWND hWnd;
BOOL bDestroyed;
SetLastError(0xdeadbeef);
hRes = pSetWindowTheme(NULL, NULL, NULL);
todo_wine
{
ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
}
/* Only do the bare minumum to get a valid hwnd */
hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
if (!hWnd) return;
SetLastError(0xdeadbeef);
hRes = pSetWindowTheme(hWnd, NULL, NULL);
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
bDestroyed = DestroyWindow(hWnd);
if (!bDestroyed)
trace("Window %p couldn't be destroyed : 0x%08x\n",
hWnd, GetLastError());
}
static void test_OpenThemeData(void)
{
HTHEME hTheme, hTheme2;
HWND hWnd;
BOOL bThemeActive;
HRESULT hRes;
BOOL bDestroyed;
BOOL bTPDefined;
WCHAR szInvalidClassList[] = {'D','E','A','D','B','E','E','F', 0 };
WCHAR szButtonClassList[] = {'B','u','t','t','o','n', 0 };
WCHAR szButtonClassList2[] = {'b','U','t','T','o','N', 0 };
WCHAR szClassList[] = {'B','u','t','t','o','n',';','L','i','s','t','B','o','x', 0 };
bThemeActive = pIsThemeActive();
/* All NULL */
SetLastError(0xdeadbeef);
hTheme = pOpenThemeData(NULL, NULL);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
todo_wine
ok( GetLastError() == E_POINTER,
"Expected GLE() to be E_POINTER, got 0x%08x\n",
GetLastError());
/* A NULL hWnd and an invalid classlist */
SetLastError(0xdeadbeef);
hTheme = pOpenThemeData(NULL, szInvalidClassList);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
todo_wine
ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
"Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
GetLastError());
SetLastError(0xdeadbeef);
hTheme = pOpenThemeData(NULL, szClassList);
if (bThemeActive)
{
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
todo_wine
ok( GetLastError() == ERROR_SUCCESS,
"Expected ERROR_SUCCESS, got 0x%08x\n",
GetLastError());
}
else
{
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
todo_wine
ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
"Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
GetLastError());
}
/* Only do the bare minumum to get a valid hdc */
hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
if (!hWnd) return;
SetLastError(0xdeadbeef);
hTheme = pOpenThemeData(hWnd, NULL);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
todo_wine
ok( GetLastError() == E_POINTER,
"Expected GLE() to be E_POINTER, got 0x%08x\n",
GetLastError());
SetLastError(0xdeadbeef);
hTheme = pOpenThemeData(hWnd, szInvalidClassList);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
todo_wine
ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
"Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
GetLastError());
if (!bThemeActive)
{
SetLastError(0xdeadbeef);
hTheme = pOpenThemeData(hWnd, szButtonClassList);
ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
todo_wine
ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
"Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
GetLastError());
trace("No active theme, skipping rest of OpenThemeData tests\n");
return;
}
/* Only do the next checks if we have an active theme */
SetLastError(0xdeadbeef);
hTheme = pOpenThemeData(hWnd, szButtonClassList);
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
todo_wine
ok( GetLastError() == ERROR_SUCCESS,
"Expected ERROR_SUCCESS, got 0x%08x\n",
GetLastError());
/* Test with bUtToN instead of Button */
SetLastError(0xdeadbeef);
hTheme = pOpenThemeData(hWnd, szButtonClassList2);
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
todo_wine
ok( GetLastError() == ERROR_SUCCESS,
"Expected ERROR_SUCCESS, got 0x%08x\n",
GetLastError());
SetLastError(0xdeadbeef);
hTheme = pOpenThemeData(hWnd, szClassList);
ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
todo_wine
ok( GetLastError() == ERROR_SUCCESS,
"Expected ERROR_SUCCESS, got 0x%08x\n",
GetLastError());
/* GetWindowTheme should return the last handle opened by OpenThemeData */
SetLastError(0xdeadbeef);
hTheme2 = pGetWindowTheme(hWnd);
ok( hTheme == hTheme2, "Expected the same HTHEME handle (%p<->%p)\n",
hTheme, hTheme2);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
SetLastError(0xdeadbeef);
hRes = pCloseThemeData(hTheme);
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
/* Close a second time */
SetLastError(0xdeadbeef);
hRes = pCloseThemeData(hTheme);
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
/* See if closing makes a difference for GetWindowTheme */
SetLastError(0xdeadbeef);
hTheme2 = NULL;
hTheme2 = pGetWindowTheme(hWnd);
ok( hTheme == hTheme2, "Expected the same HTHEME handle (%p<->%p)\n",
hTheme, hTheme2);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
SetLastError(0xdeadbeef);
bTPDefined = pIsThemePartDefined(hTheme, 0 , 0);
todo_wine
{
ok( bTPDefined == FALSE, "Expected FALSE\n");
ok( GetLastError() == ERROR_SUCCESS,
"Expected ERROR_SUCCESS, got 0x%08x\n",
GetLastError());
}
bDestroyed = DestroyWindow(hWnd);
if (!bDestroyed)
trace("Window %p couldn't be destroyed : 0x%08x\n",
hWnd, GetLastError());
}
static void test_GetCurrentThemeName(void)
{
BOOL bThemeActive;
HRESULT hRes;
WCHAR currentTheme[MAX_PATH];
WCHAR currentColor[MAX_PATH];
WCHAR currentSize[MAX_PATH];
bThemeActive = pIsThemeActive();
/* All NULLs */
SetLastError(0xdeadbeef);
hRes = pGetCurrentThemeName(NULL, 0, NULL, 0, NULL, 0);
if (bThemeActive)
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
/* Number of characters given is 0 */
SetLastError(0xdeadbeef);
hRes = pGetCurrentThemeName(currentTheme, 0, NULL, 0, NULL, 0);
if (bThemeActive)
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
/* When the number of characters given is too small (not 0, see above), GetCurrentThemeName returns 0x8007007a.
* The only definition I found was in strsafe.h:
*
* #define STRSAFE_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL) // 0x7A = 122L = ERROR_INSUFFICIENT_BUFFER
*/
SetLastError(0xdeadbeef);
hRes = pGetCurrentThemeName(currentTheme, 2, NULL, 0, NULL, 0);
if (bThemeActive)
todo_wine
ok( LOWORD(hRes) == ERROR_INSUFFICIENT_BUFFER, "Expected 0x8007007A, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
/* The same is true if the number of characters is too small for Color and/or Size */
SetLastError(0xdeadbeef);
hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR),
currentColor, 2,
currentSize, sizeof(currentSize) / sizeof(WCHAR));
if (bThemeActive)
todo_wine
ok( LOWORD(hRes) == ERROR_INSUFFICIENT_BUFFER, "Expected 0x8007007A, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
/* Given number of characters is correct */
SetLastError(0xdeadbeef);
hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR), NULL, 0, NULL, 0);
if (bThemeActive)
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
/* Given number of characters for the theme name is too large */
SetLastError(0xdeadbeef);
hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme), NULL, 0, NULL, 0);
todo_wine
ok( hRes == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
/* The too large case is only for the theme name, not for color name or size name */
SetLastError(0xdeadbeef);
hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR),
currentColor, sizeof(currentTheme),
currentSize, sizeof(currentSize) / sizeof(WCHAR));
if (bThemeActive)
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
SetLastError(0xdeadbeef);
hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR),
currentColor, sizeof(currentTheme) / sizeof(WCHAR),
currentSize, sizeof(currentSize));
if (bThemeActive)
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
/* Correct call */
SetLastError(0xdeadbeef);
hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR),
currentColor, sizeof(currentColor) / sizeof(WCHAR),
currentSize, sizeof(currentSize) / sizeof(WCHAR));
if (bThemeActive)
ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
else
ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
}
static void test_CloseThemeData(void)
{
HRESULT hRes;
SetLastError(0xdeadbeef);
hRes = pCloseThemeData(NULL);
ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
ok( GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got 0x%08x\n",
GetLastError());
}
START_TEST(system)
{
if(!InitFunctionPtrs())
return;
/* No real functional tests will be done (yet). The current tests
* only show input/return behaviour
*/
/* IsThemeActive, IsAppThemed and IsThemePartDefined*/
trace("Starting test_IsThemed()\n");
test_IsThemed();
/* GetWindowTheme */
trace("Starting test_GetWindowTheme()\n");
test_GetWindowTheme();
/* SetWindowTheme */
trace("Starting test_SetWindowTheme()\n");
test_SetWindowTheme();
/* OpenThemeData, a bit more functional now */
trace("Starting test_OpenThemeData()\n");
test_OpenThemeData();
/* GetCurrentThemeName */
trace("Starting test_GetCurrentThemeName()\n");
test_GetCurrentThemeName();
/* CloseThemeData */
trace("Starting test_CloseThemeData()\n");
test_CloseThemeData();
FreeLibrary(hUxtheme);
}

View file

@ -0,0 +1,15 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define STANDALONE
#include "wine/test.h"
extern void func_system(void);
const struct test winetest_testlist[] =
{
{ "system", func_system },
{ 0, 0 }
};

View file

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="uxtheme_winetest" type="win32cui" installbase="bin" installname="uxtheme_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="uxtheme_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>user32</library>
<library>kernel32</library>
<library>ntdll</library>
<file>system.c</file>
<file>testlist.c</file>
</module>

View file

@ -13,19 +13,20 @@
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdio.h>
#include <assert.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winver.h"
#include "wine/test.h"
#define MY_LAST_ERROR -1L
#define MY_LAST_ERROR ((DWORD)-1)
#define EXPECT_BAD_PATH__NOT_FOUND \
ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \
(ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || \
@ -33,7 +34,7 @@
(ERROR_BAD_PATHNAME == GetLastError()), \
"Last error wrong! ERROR_RESOURCE_DATA_NOT_FOUND/ERROR_BAD_PATHNAME (98)/" \
"ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3)" \
"expected, got 0x%08lx\n", GetLastError());
"expected, got %u\n", GetLastError());
#define EXPECT_INVALID__NOT_FOUND \
ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \
(ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || \
@ -41,15 +42,16 @@
(ERROR_INVALID_PARAMETER == GetLastError()), \
"Last error wrong! ERROR_RESOURCE_DATA_NOT_FOUND/ERROR_INVALID_PARAMETER (98)/" \
"ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3)" \
"expected, got 0x%08lx\n", GetLastError());
"expected, got %u\n", GetLastError());
static void test_info_size(void)
{ DWORD hdl, retval;
char mypath[MAX_PATH] = "";
SetLastError(MY_LAST_ERROR);
retval = GetFileVersionInfoSizeA( NULL, NULL);
ok( !retval,
"GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n",
"GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
retval);
EXPECT_INVALID__NOT_FOUND;
@ -57,16 +59,16 @@ static void test_info_size(void)
SetLastError(MY_LAST_ERROR);
retval = GetFileVersionInfoSizeA( NULL, &hdl);
ok( !retval,
"GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n",
"GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
retval);
EXPECT_INVALID__NOT_FOUND;
ok( hdl == 0L,
"Handle wrong! 0L expected, got 0x%08lx\n", hdl);
"Handle wrong! 0L expected, got 0x%08x\n", hdl);
SetLastError(MY_LAST_ERROR);
retval = GetFileVersionInfoSizeA( "", NULL);
ok( !retval,
"GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n",
"GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
retval);
EXPECT_BAD_PATH__NOT_FOUND;
@ -74,43 +76,83 @@ static void test_info_size(void)
SetLastError(MY_LAST_ERROR);
retval = GetFileVersionInfoSizeA( "", &hdl);
ok( !retval,
"GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n",
"GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
retval);
EXPECT_BAD_PATH__NOT_FOUND;
ok( hdl == 0L,
"Handle wrong! 0L expected, got 0x%08lx\n", hdl);
"Handle wrong! 0L expected, got 0x%08x\n", hdl);
SetLastError(MY_LAST_ERROR);
retval = GetFileVersionInfoSizeA( "kernel32.dll", NULL);
ok( retval,
"GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08lx\n",
"GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
retval);
ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
"Last error wrong! NO_ERROR/0x%08lx (NT4) expected, got 0x%08lx\n",
"Last error wrong! NO_ERROR/0x%08x (NT4) expected, got %u\n",
MY_LAST_ERROR, GetLastError());
hdl = 0x55555555;
SetLastError(MY_LAST_ERROR);
retval = GetFileVersionInfoSizeA( "kernel32.dll", &hdl);
ok( retval,
"GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08lx\n",
"GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
retval);
ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
"Last error wrong! NO_ERROR/0x%08lx (NT4) expected, got 0x%08lx\n",
"Last error wrong! NO_ERROR/0x%08x (NT4) expected, got %u\n",
MY_LAST_ERROR, GetLastError());
ok( hdl == 0L,
"Handle wrong! 0L expected, got 0x%08lx\n", hdl);
"Handle wrong! 0L expected, got 0x%08x\n", hdl);
SetLastError(MY_LAST_ERROR);
retval = GetFileVersionInfoSizeA( "notexist.dll", NULL);
ok( !retval,
"GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08lx\n",
"GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
retval);
ok( (ERROR_FILE_NOT_FOUND == GetLastError()) ||
(ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) ||
(MY_LAST_ERROR == GetLastError()),
"Last error wrong! ERROR_FILE_NOT_FOUND/ERROR_RESOURCE_DATA_NOT_FOUND "
"(XP)/0x%08lx (NT4) expected, got 0x%08lx\n", MY_LAST_ERROR, GetLastError());
"(XP)/0x%08x (NT4) expected, got %u\n", MY_LAST_ERROR, GetLastError());
/* test a currently loaded executable */
if(GetModuleFileNameA(NULL, mypath, MAX_PATH)) {
hdl = 0x55555555;
SetLastError(MY_LAST_ERROR);
retval = GetFileVersionInfoSizeA( mypath, &hdl);
ok( retval,
"GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
retval);
ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
"Last error wrong! NO_ERROR/0x%08x (NT4) expected, got %u\n",
MY_LAST_ERROR, GetLastError());
ok( hdl == 0L,
"Handle wrong! 0L expected, got 0x%08x\n", hdl);
}
else
trace("skipping GetModuleFileNameA(NULL,..) failed\n");
/* test a not loaded executable */
if(GetSystemDirectoryA(mypath, MAX_PATH)) {
lstrcatA(mypath, "\\regsvr32.exe");
if(INVALID_FILE_ATTRIBUTES == GetFileAttributesA(mypath))
trace("GetFileAttributesA(%s) failed\n", mypath);
else {
hdl = 0x55555555;
SetLastError(MY_LAST_ERROR);
retval = GetFileVersionInfoSizeA( mypath, &hdl);
ok( retval,
"GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
retval);
ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
"Last error wrong! NO_ERROR/0x%08x (NT4) expected, got %u\n",
MY_LAST_ERROR, GetLastError());
ok( hdl == 0L,
"Handle wrong! 0L expected, got 0x%08x\n", hdl);
}
}
else
trace("skipping GetModuleFileNameA(NULL,..) failed\n");
}
static void VersionDwordLong2String(DWORDLONG Version, LPSTR lpszVerString)
@ -135,19 +177,20 @@ static void test_info(void)
VS_FIXEDFILEINFO *pFixedVersionInfo;
UINT uiLength;
char VersionString[MAX_PATH];
static CHAR backslash[] = "\\";
DWORDLONG dwlVersion;
hdl = 0x55555555;
SetLastError(MY_LAST_ERROR);
retval = GetFileVersionInfoSizeA( "kernel32.dll", &hdl);
ok( retval,
"GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08lx\n",
"GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
retval);
ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
"Last error wrong! NO_ERROR/0x%08lx (NT4) expected, got 0x%08lx\n",
"Last error wrong! NO_ERROR/0x%08x (NT4) expected, got %u\n",
MY_LAST_ERROR, GetLastError());
ok( hdl == 0L,
"Handle wrong! 0L expected, got 0x%08lx\n", hdl);
"Handle wrong! 0L expected, got 0x%08x\n", hdl);
if ( retval == 0 || hdl != 0)
return;
@ -157,21 +200,28 @@ static void test_info(void)
if (pVersionInfo == 0)
return;
if (0)
{
/* this test crashes on WinNT4
*/
boolret = GetFileVersionInfoA( "kernel32.dll", 0, retval, 0);
ok (!boolret, "GetFileVersionInfoA should have failed: GetLastError = 0x%08lx\n", GetLastError());
ok ((GetLastError() == ERROR_INVALID_DATA) || (GetLastError() == ERROR_BAD_PATHNAME),
"Last error wrong! ERROR_INVALID_DATA/ERROR_BAD_PATHNAME (ME) expected, got 0x%08lx\n",
ok (!boolret, "GetFileVersionInfoA should have failed: GetLastError = %u\n", GetLastError());
ok ((GetLastError() == ERROR_INVALID_DATA) || (GetLastError() == ERROR_BAD_PATHNAME) ||
(GetLastError() == NO_ERROR),
"Last error wrong! ERROR_INVALID_DATA/ERROR_BAD_PATHNAME (ME)/"
"NO_ERROR (95) expected, got %u\n",
GetLastError());
}
boolret = GetFileVersionInfoA( "kernel32.dll", 0, retval, pVersionInfo );
ok (boolret, "GetFileVersionInfoA failed: GetLastError = 0x%08lx\n", GetLastError());
ok (boolret, "GetFileVersionInfoA failed: GetLastError = %u\n", GetLastError());
if (!boolret)
return;
goto cleanup;
boolret = VerQueryValueA( pVersionInfo, "\\", (LPVOID *)&pFixedVersionInfo, &uiLength );
ok (boolret, "VerQueryValueA failed: GetLastError = 0x%08lx\n", GetLastError());
boolret = VerQueryValueA( pVersionInfo, backslash, (LPVOID *)&pFixedVersionInfo, &uiLength );
ok (boolret, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
if (!boolret)
return;
goto cleanup;
dwlVersion = (((DWORDLONG)pFixedVersionInfo->dwFileVersionMS) << 32) +
pFixedVersionInfo->dwFileVersionLS;
@ -180,12 +230,306 @@ static void test_info(void)
trace("kernel32.dll version: %s\n", VersionString);
boolret = VerQueryValueA( pVersionInfo, "\\", (LPVOID *)&pFixedVersionInfo, 0);
ok (boolret, "VerQueryValue failed: GetLastError = 0x%08lx\n", GetLastError());
if (0)
{
/* this test crashes on WinNT4
*/
boolret = VerQueryValueA( pVersionInfo, backslash, (LPVOID *)&pFixedVersionInfo, 0);
ok (boolret, "VerQueryValue failed: GetLastError = %u\n", GetLastError());
}
cleanup:
HeapFree( GetProcessHeap(), 0, pVersionInfo);
}
static void test_32bit_win(void)
{
DWORD hdlA, retvalA;
DWORD hdlW, retvalW = 0;
BOOL retA,retW;
PVOID pVersionInfoA = NULL;
PVOID pVersionInfoW = NULL;
char *pBufA;
WCHAR *pBufW;
UINT uiLengthA, uiLengthW;
char mypathA[MAX_PATH];
WCHAR mypathW[MAX_PATH];
char rootA[] = "\\";
WCHAR rootW[] = { '\\', 0 };
char varfileinfoA[] = "\\VarFileInfo\\Translation";
WCHAR varfileinfoW[] = { '\\','V','a','r','F','i','l','e','I','n','f','o',
'\\','T','r','a','n','s','l','a','t','i','o','n', 0 };
char WineVarFileInfoA[] = { 0x09, 0x04, 0xE4, 0x04 };
char FileDescriptionA[] = "\\StringFileInfo\\040904E4\\FileDescription";
WCHAR FileDescriptionW[] = { '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
'\\','0','4','0','9','0','4','E','4',
'\\','F','i','l','e','D','e','s','c','r','i','p','t','i','o','n', 0 };
char WineFileDescriptionA[] = "FileDescription";
WCHAR WineFileDescriptionW[] = { 'F','i','l','e','D','e','s','c','r','i','p','t','i','o','n', 0 };
BOOL is_unicode_enabled = TRUE;
/* A copy from dlls/version/info.c */
typedef struct
{
WORD wLength;
WORD wValueLength;
WORD wType;
WCHAR szKey[1];
#if 0 /* variable length structure */
/* DWORD aligned */
BYTE Value[];
/* DWORD aligned */
VS_VERSION_INFO_STRUCT32 Children[];
#endif
} VS_VERSION_INFO_STRUCT32;
/* If we call GetFileVersionInfoA on a system that supports Unicode, NT/W2K/XP/W2K3 (by default) and Wine,
* the versioninfo will contain Unicode strings.
* Part of the test is to call both the A and W versions, which should have the same Version Information
* for some requests, on systems that support both calls.
*/
/* First get the versioninfo via the W versions */
SetLastError(0xdeadbeef);
GetModuleFileNameW(NULL, mypathW, MAX_PATH);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
trace("GetModuleFileNameW not existing on this platform, skipping comparison between A- and W-calls\n");
is_unicode_enabled = FALSE;
}
if (is_unicode_enabled)
{
retvalW = GetFileVersionInfoSizeW( mypathW, &hdlW);
pVersionInfoW = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, retvalW );
retW = GetFileVersionInfoW( mypathW, 0, retvalW, pVersionInfoW );
}
GetModuleFileNameA(NULL, mypathA, MAX_PATH);
retvalA = GetFileVersionInfoSizeA( mypathA, &hdlA);
pVersionInfoA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, retvalA );
retA = GetFileVersionInfoA( mypathA, 0, retvalA, pVersionInfoA );
if (is_unicode_enabled)
{
ok( retvalA == retvalW, "The size of the struct should be the same for both A/W calls, it is (%d) vs. (%d)\n",
retvalA, retvalW);
ok( !memcmp(pVersionInfoA, pVersionInfoW, retvalA), "Both structs should be the same, they aren't\n");
}
/* The structs on Windows are bigger than just the struct for the basic information. The total struct
* contains also an empty part, which is used for converted strings. The converted strings are a result
* of calling VerQueryValueA on a 32bit resource and calling VerQueryValueW on a 16bit resource.
* The first WORD of the structure (wLength) shows the size of the base struct. The total struct size depends
* on the Windows version:
*
* 16bits resource (numbers are from a sample app):
*
* Windows Version Retrieved with A/W wLength StructSize
* ====================================================================================
* Win98 A 0x01B4 (436) 436
* NT4 A/W 0x01B4 (436) 2048 ???
* W2K/XP/W2K3 A/W 0x01B4 (436) 1536 which is (436 - sizeof(VS_FIXEDFILEINFO)) * 4
*
* 32bits resource (numbers are from this test executable version_crosstest.exe):
* Windows Version Retrieved with A/W wLength StructSize
* =============================================================
* Win98 A 0x01E0 (480) 848 (structure data doesn't seem correct)
* NT4 A/W 0x0350 (848) 1272 (848 * 1.5)
* W2K/XP/W2K3 A/W 0x0350 (848) 1700 which is (848 * 2) + 4
*
* Wine will follow the implementation (eventually) of W2K/XP/W2K3
*/
/* Now some tests for the above (only if we are unicode enabled) */
if (is_unicode_enabled)
{
VS_VERSION_INFO_STRUCT32 *vvis = (VS_VERSION_INFO_STRUCT32 *)pVersionInfoW;
ok ( retvalW == ((vvis->wLength * 2) + 4) || retvalW == (vvis->wLength * 1.5),
"Structure is not of the correct size\n");
}
/* Although the 32bit resource structures contain Unicode strings, VerQueryValueA will always return normal strings,
* VerQueryValueW will always return Unicode ones. (That means everything returned for StringFileInfo requests).
*/
/* Get the VS_FIXEDFILEINFO information, this must be the same for both A- and W-Calls */
retA = VerQueryValueA( pVersionInfoA, rootA, (LPVOID *)&pBufA, &uiLengthA );
ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
ok ( uiLengthA == sizeof(VS_FIXEDFILEINFO), "Size (%d) doesn't match the size of the VS_FIXEDFILEINFO struct\n", uiLengthA);
if (is_unicode_enabled)
{
retW = VerQueryValueW( pVersionInfoW, rootW, (LPVOID *)&pBufW, &uiLengthW );
ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
ok ( uiLengthA == sizeof(VS_FIXEDFILEINFO), "Size (%d) doesn't match the size of the VS_FIXEDFILEINFO struct\n", uiLengthA);
ok( uiLengthA == uiLengthW, "The size of VS_FIXEDFILEINFO should be the same for both A/W calls, it is (%d) vs. (%d)\n",
uiLengthA, uiLengthW);
ok( !memcmp(pBufA, pBufW, uiLengthA), "Both values should be the same, they aren't\n");
}
/* Get some VarFileInfo information, this must be the same for both A- and W-Calls */
retA = VerQueryValueA( pVersionInfoA, varfileinfoA, (LPVOID *)&pBufA, &uiLengthA );
ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
ok( !memcmp(pBufA, WineVarFileInfoA, uiLengthA), "The VarFileInfo should have matched 0904e404 (non case sensitive)\n");
if (is_unicode_enabled)
{
retW = VerQueryValueW( pVersionInfoW, varfileinfoW, (LPVOID *)&pBufW, &uiLengthW );
ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
ok( uiLengthA == uiLengthW, "The size of the VarFileInfo information should be the same for both A/W calls, it is (%d) vs. (%d)\n",
uiLengthA, uiLengthW);
ok( !memcmp(pBufA, pBufW, uiLengthA), "Both values should be the same, they aren't\n");
}
/* Get some StringFileInfo information, this will be ANSI for A-Calls and Unicode for W-Calls */
retA = VerQueryValueA( pVersionInfoA, FileDescriptionA, (LPVOID *)&pBufA, &uiLengthA );
ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
ok( !lstrcmpA(WineFileDescriptionA, pBufA), "expected '%s' got '%s'\n",
WineFileDescriptionA, pBufA);
/* Test a second time */
retA = VerQueryValueA( pVersionInfoA, FileDescriptionA, (LPVOID *)&pBufA, &uiLengthA );
ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
ok( !lstrcmpA(WineFileDescriptionA, pBufA), "expected '%s' got '%s'\n",
WineFileDescriptionA, pBufA);
if (is_unicode_enabled)
{
retW = VerQueryValueW( pVersionInfoW, FileDescriptionW, (LPVOID *)&pBufW, &uiLengthW );
ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
ok( !lstrcmpW(WineFileDescriptionW, pBufW), "FileDescription should have been '%s'\n", WineFileDescriptionA);
}
HeapFree( GetProcessHeap(), 0, pVersionInfoA);
if (is_unicode_enabled)
HeapFree( GetProcessHeap(), 0, pVersionInfoW);
}
static void test_VerQueryValue(void)
{
static const char * const value_name[] = {
"Product", "CompanyName", "FileDescription", "Internal",
"ProductVersion", "InternalName", "File", "LegalCopyright",
"FileVersion", "Legal", "OriginalFilename", "ProductName",
"Company", "Original" };
char *ver, *p;
UINT len, ret, translation, i;
char buf[MAX_PATH];
ret = GetModuleFileName(NULL, buf, sizeof(buf));
assert(ret);
SetLastError(0xdeadbeef);
len = GetFileVersionInfoSize(buf, NULL);
ok(len, "GetFileVersionInfoSize(%s) error %u\n", buf, GetLastError());
ver = HeapAlloc(GetProcessHeap(), 0, len);
assert(ver);
SetLastError(0xdeadbeef);
ret = GetFileVersionInfo(buf, 0, len, ver);
ok(ret, "GetFileVersionInfo error %u\n", GetLastError());
p = (char *)0xdeadbeef;
len = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = VerQueryValue(ver, "\\VarFileInfo\\Translation", (LPVOID*)&p, &len);
ok(ret, "VerQueryValue error %u\n", GetLastError());
ok(len == 4, "VerQueryValue returned %u, expected 4\n", len);
translation = *(UINT *)p;
translation = MAKELONG(HIWORD(translation), LOWORD(translation));
p = (char *)0xdeadbeef;
len = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = VerQueryValue(ver, "String", (LPVOID*)&p, &len);
ok(!ret, "VerQueryValue should fail\n");
ok(GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND,
"VerQueryValue returned %u\n", GetLastError());
ok(p == (char *)0xdeadbeef, "expected 0xdeadbeef got %p\n", p);
ok(len == 0, "expected 0 got %x\n", len);
p = (char *)0xdeadbeef;
len = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = VerQueryValue(ver, "StringFileInfo", (LPVOID*)&p, &len);
ok(ret, "VerQueryValue error %u\n", GetLastError());
todo_wine ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
p = (char *)0xdeadbeef;
len = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = VerQueryValue(ver, "\\StringFileInfo", (LPVOID*)&p, &len);
ok(ret, "VerQueryValue error %u\n", GetLastError());
todo_wine ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
p = (char *)0xdeadbeef;
len = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = VerQueryValue(ver, "\\\\StringFileInfo", (LPVOID*)&p, &len);
ok(ret, "VerQueryValue error %u\n", GetLastError());
todo_wine ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
p = (char *)0xdeadbeef;
len = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = VerQueryValue(ver, "\\StringFileInfo\\\\", (LPVOID*)&p, &len);
ok(ret, "VerQueryValue error %u\n", GetLastError());
todo_wine ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
sprintf(buf, "\\StringFileInfo\\%08x", translation);
p = (char *)0xdeadbeef;
len = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = VerQueryValue(ver, buf, (LPVOID*)&p, &len);
ok(ret, "VerQueryValue error %u\n", GetLastError());
todo_wine ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
for (i = 0; i < sizeof(value_name)/sizeof(value_name[0]); i++)
{
sprintf(buf, "\\StringFileInfo\\%08x\\%s", translation, value_name[i]);
p = (char *)0xdeadbeef;
len = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = VerQueryValue(ver, buf, (LPVOID*)&p, &len);
ok(ret, "VerQueryValue(%s) error %u\n", buf, GetLastError());
ok(len == strlen(value_name[i]) + 1, "VerQueryValue returned %u\n", len);
ok(!strcmp(value_name[i], p), "expected \"%s\", got \"%s\"\n",
value_name[i], p);
/* test partial value names */
len = lstrlen(buf);
buf[len - 2] = 0;
p = (char *)0xdeadbeef;
len = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = VerQueryValue(ver, buf, (LPVOID*)&p, &len);
ok(!ret, "VerQueryValue(%s) succeeded\n", buf);
ok(GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND,
"VerQueryValue returned %u\n", GetLastError());
ok(p == (char *)0xdeadbeef, "expected 0xdeadbeef got %p\n", p);
ok(len == 0, "expected 0 got %x\n", len);
}
HeapFree(GetProcessHeap(), 0, ver);
}
START_TEST(info)
{
test_info_size();
test_info();
test_32bit_win();
test_VerQueryValue();
}

View file

@ -0,0 +1,171 @@
/*
* Copyright (C) 2005 Stefan Leichter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdio.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winver.h"
static void test_find_file(void)
{
DWORD ret;
UINT dwCur, dwOut ;
char appdir[MAX_PATH];
char curdir[MAX_PATH];
char filename[MAX_PATH];
char outBuf[MAX_PATH];
char windir[MAX_PATH];
static CHAR empty[] = "",
regedit[] = "regedit",
regedit_exe[] = "regedit.exe";
memset(appdir, 0, MAX_PATH);
memset(windir, 0, MAX_PATH);
dwCur=MAX_PATH;
dwOut=MAX_PATH;
memset(curdir, 0, MAX_PATH);
memset(outBuf, 0, MAX_PATH);
ret = VerFindFileA(0, regedit, empty, empty, curdir, &dwCur, outBuf, &dwOut);
switch(ret) {
case 0L:
ok(dwCur == 1, "Wrong length of buffer for current location: "
"got %d(%s) expected 1\n", dwCur, curdir);
ok(dwOut == 1, "Wrong length of buffer for the recommended installation location: "
"got %d(%s) expected 1\n", dwOut, outBuf);
break;
case VFF_BUFFTOOSMALL:
ok(dwCur == MAX_PATH, "Wrong length of buffer for current location: "
"got %d(%s) expected MAX_PATH\n", dwCur, curdir);
ok(dwOut == MAX_PATH, "Wrong length of buffer for the recommended installation location: "
"got %d(%s) expected MAX_PATH\n", dwOut, outBuf);
break;
default:
ok(0, "Got unexpected return value %x\n", ret);
}
if(!GetWindowsDirectoryA(windir, MAX_PATH))
trace("GetWindowsDirectoryA failed\n");
else {
sprintf(appdir, "%s\\regedit.exe", windir);
if(INVALID_FILE_ATTRIBUTES == GetFileAttributesA(appdir))
trace("GetFileAttributesA(%s) failed\n", appdir);
else {
dwCur=MAX_PATH;
dwOut=MAX_PATH;
memset(curdir, 0, MAX_PATH);
memset(outBuf, 0, MAX_PATH);
ret = VerFindFileA(0, regedit_exe, empty, empty, curdir, &dwCur, outBuf, &dwOut);
switch(ret) {
case VFF_CURNEDEST:
ok(dwCur == 1 + strlen(windir), "Wrong length of buffer for current location: "
"got %d(%s) expected %d\n", dwCur, curdir, lstrlenA(windir)+1);
ok(dwOut == 1, "Wrong length of buffer for the recommended installation location: "
"got %d(%s) expected 1\n", dwOut, outBuf);
break;
case VFF_BUFFTOOSMALL:
ok(dwCur == MAX_PATH, "Wrong length of buffer for current location: "
"got %d(%s) expected MAX_PATH\n", dwCur, curdir);
ok(dwOut == MAX_PATH, "Wrong length of buffer for the recommended installation location: "
"got %d(%s) expected MAX_PATH\n", dwOut, outBuf);
break;
default:
todo_wine ok(0, "Got unexpected return value %x\n", ret);
}
dwCur=MAX_PATH;
dwOut=MAX_PATH;
memset(curdir, 0, MAX_PATH);
memset(outBuf, 0, MAX_PATH);
ret = VerFindFileA(0, regedit_exe, NULL, NULL, curdir, &dwCur, outBuf, &dwOut);
switch(ret) {
case VFF_CURNEDEST:
ok(dwCur == 1 + strlen(windir), "Wrong length of buffer for current location: "
"got %d(%s) expected %d\n", dwCur, curdir, lstrlenA(windir)+1);
ok(dwOut == 1, "Wrong length of buffer for the recommended installation location: "
"got %d(%s) expected 1\n", dwOut, outBuf);
break;
case VFF_BUFFTOOSMALL:
ok(dwCur == MAX_PATH, "Wrong length of buffer for current location: "
"got %d(%s) expected MAX_PATH\n", dwCur, curdir);
ok(dwOut == MAX_PATH, "Wrong length of buffer for the recommended installation location: "
"got %d(%s) expected MAX_PATH\n", dwOut, outBuf);
break;
default:
todo_wine ok(0, "Got unexpected return value %x\n", ret);
}
}
}
if(!GetModuleFileNameA(NULL, filename, MAX_PATH) ||
!GetSystemDirectoryA(windir, MAX_PATH) ||
!GetTempPathA(MAX_PATH, appdir))
trace("GetModuleFileNameA, GetSystemDirectoryA or GetTempPathA failed\n");
else {
char *p = strrchr(filename, '\\');
if(p) {
*(p++) ='\0';
SetCurrentDirectoryA(filename);
memmove(filename, p, 1 + strlen(p));
}
dwCur=MAX_PATH;
dwOut=MAX_PATH;
memset(outBuf, 0, MAX_PATH);
memset(curdir, 0, MAX_PATH);
ret = VerFindFileA(0, filename, NULL, NULL, curdir, &dwCur, outBuf, &dwOut);
switch(ret) {
case VFF_CURNEDEST:
ok(dwOut == 1, "Wrong length of buffer for the recommended installation location"
"got %d(%s) expected 1\n", dwOut, outBuf);
break;
case VFF_BUFFTOOSMALL:
ok(dwOut == MAX_PATH, "Wrong length of buffer for the recommended installation location"
"got %d(%s) expected MAX_PATH\n", dwOut, outBuf);
break;
default:
todo_wine ok(0, "Got unexpected return value %x\n", ret);
}
dwCur=MAX_PATH;
dwOut=MAX_PATH;
memset(outBuf, 0, MAX_PATH);
memset(curdir, 0, MAX_PATH);
ret = VerFindFileA(VFFF_ISSHAREDFILE, filename, NULL, appdir, curdir, &dwCur, outBuf, &dwOut);
todo_wine ok(VFF_CURNEDEST == ret, "Wrong return value got %x expected VFF_CURNEDEST\n", ret);
ok(dwOut == 1 + strlen(windir), "Wrong length of buffer for current location: "
"got %d(%s) expected %d\n", dwOut, outBuf, lstrlenA(windir)+1);
dwCur=MAX_PATH;
dwOut=MAX_PATH;
memset(outBuf, 0, MAX_PATH);
memset(curdir, 0, MAX_PATH);
ret = VerFindFileA(0, filename, NULL, appdir, curdir, &dwCur, outBuf, &dwOut);
todo_wine ok(VFF_CURNEDEST == ret, "Wrong return value got %x expected VFF_CURNEDEST\n", ret);
ok(dwOut == 1 + strlen(appdir), "Wrong length of buffer for current location: "
"got %d(%s) expected %d\n", dwOut, outBuf, lstrlenA(appdir)+1);
}
}
START_TEST(install)
{
test_find_file();
}

View file

@ -12,6 +12,6 @@ extern void func_install(void);
const struct test winetest_testlist[] =
{
{ "info", func_info },
// { "install", func_install },
{ "install", func_install },
{ 0, 0 }
};

View file

@ -1,9 +1,15 @@
<module name="version_winetest" type="win32cui" installbase="bin" installname="version_winetest.exe" allowwarnings="true">
<include base="version_winetest">.</include>
<define name="__USE_W32API" />
<library>ntdll</library>
<library>version</library>
<library>kernel32</library>
<file>testlist.c</file>
<file>info.c</file>
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="version_winetest" type="win32cui" installbase="bin" installname="version_winetest.exe" allowwarnings="true" entrypoint="0">
<include base="version_winetest">.</include>
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>version</library>
<library>kernel32</library>
<library>ntdll</library>
<file>info.c</file>
<file>install.c</file>
<file>version.rc</file>
<file>testlist.c</file>
</module>

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2005 Mike McCormack
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "windef.h"
#include "winbase.h"
#include "winver.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 63
FILEFLAGS 0
FILEOS VOS_UNKNOWN
FILETYPE VFT_APP
FILESUBTYPE VFT2_UNKNOWN
{
BLOCK "StringFileInfo"
{
BLOCK "040904E4" /* LANG_ENGLISH/SUBLANG_DEFAULT, CP1252 */
{
/* list of strings that partially match in arbitrary order */
VALUE "Product", "Product"
VALUE "CompanyName", "CompanyName"
VALUE "FileDescription", "FileDescription"
VALUE "Internal", "Internal"
VALUE "ProductVersion", "ProductVersion"
VALUE "InternalName", "InternalName"
VALUE "File", "File"
VALUE "LegalCopyright", "LegalCopyright"
VALUE "FileVersion", "FileVersion"
VALUE "Legal", "Legal"
VALUE "OriginalFilename", "OriginalFilename"
VALUE "ProductName", "ProductName"
VALUE "Company", "Company"
VALUE "Original", "Original"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409,1252 /* LANG_ENGLISH/SUBLANG_DEFAULT, CP1252 */
}
}

View file

@ -0,0 +1,740 @@
/*
* Wininet - ftp tests
*
* Copyright 2007 Paul Vriens
* Copyright 2007 Hans Leidekker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
* FIXME:
* Use InternetGetLastResponseInfo when the last error is set to ERROR_INTERNET_EXTENDED_ERROR.
* TODO:
* Add W-function tests.
* Add missing function tests:
* FtpFindFirstFile
* FtpGetCurrentDirectory
* FtpGetFileSize
* FtpSetCurrentDirectory
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "wininet.h"
#include "winsock.h"
#include "wine/test.h"
static void test_getfile_no_open(void)
{
BOOL bRet;
/* Invalid internet handle, the others are valid parameters */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(NULL, "welcome.msg", "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_NOT_INITIALIZED ||
GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INTERNET_NOT_INITIALIZED or ERROR_INVALID_HANDLE (win98), got %d\n", GetLastError());
}
static void test_connect(HINTERNET hInternet)
{
HINTERNET hFtp;
/* Try a few username/password combinations:
* anonymous : NULL
* NULL : IEUser@
* NULL : NULL
*/
SetLastError(0xdeadbeef);
hFtp = InternetConnect(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, "anonymous", NULL, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
if (hFtp) /* some servers accept an empty password */
{
ok ( GetLastError() == ERROR_SUCCESS, "ERROR_SUCCESS, got %d\n", GetLastError());
InternetCloseHandle(hFtp);
}
else
ok ( GetLastError() == ERROR_INTERNET_LOGIN_FAILURE,
"Expected ERROR_INTERNET_LOGIN_FAILURE, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
hFtp = InternetConnect(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, NULL, "IEUser@", INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
ok ( hFtp == NULL, "Expected InternetConnect to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* Using a NULL username and password will be interpreted as anonymous ftp. The username will be 'anonymous' the password
* is created via some simple heuristics (see dlls/wininet/ftp.c).
* On Wine this registry key is not set by default so (NULL, NULL) will result in anonymous ftp with an (most likely) not
* accepted password (the username).
* If the first call fails because we get an ERROR_INTERNET_LOGIN_FAILURE, we try again with a (more) correct password.
*/
SetLastError(0xdeadbeef);
hFtp = InternetConnect(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, NULL, NULL, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
if (!hFtp && (GetLastError() == ERROR_INTERNET_LOGIN_FAILURE))
{
/* We are most likely running on a clean Wine install or a Windows install where the registry key is removed */
SetLastError(0xdeadbeef);
hFtp = InternetConnect(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, "anonymous", "IEUser@", INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
}
ok ( hFtp != NULL, "InternetConnect failed : %d\n", GetLastError());
ok ( GetLastError() == ERROR_SUCCESS,
"ERROR_SUCCESS, got %d\n", GetLastError());
}
static void test_createdir(HINTERNET hFtp, HINTERNET hConnect)
{
BOOL bRet;
/* Invalid internet handle, the other is a valid parameter */
SetLastError(0xdeadbeef);
bRet = FtpCreateDirectoryA(NULL, "new_directory_deadbeef");
ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
ok ( GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
/* No directory-name */
SetLastError(0xdeadbeef);
bRet = FtpCreateDirectoryA(hFtp, NULL);
ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* Parameters are OK, but we shouldn't be allowed to create the directory */
SetLastError(0xdeadbeef);
bRet = FtpCreateDirectoryA(hFtp, "new_directory_deadbeef");
ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
"Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
/* One small test to show that handle type is checked before parameters */
SetLastError(0xdeadbeef);
bRet = FtpCreateDirectoryA(hConnect, NULL);
ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
bRet = FtpCreateDirectoryA(hConnect, "new_directory_deadbeef");
ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
}
static void test_deletefile(HINTERNET hFtp, HINTERNET hConnect)
{
BOOL bRet;
/* Invalid internet handle, the other is a valid parameter */
SetLastError(0xdeadbeef);
bRet = FtpDeleteFileA(NULL, "non_existent_file_deadbeef");
ok ( bRet == FALSE, "Expected FtpDeleteFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
/* No filename */
SetLastError(0xdeadbeef);
bRet = FtpDeleteFileA(hFtp, NULL);
ok ( bRet == FALSE, "Expected FtpDeleteFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* Parameters are OK but remote file should not be there */
SetLastError(0xdeadbeef);
bRet = FtpDeleteFileA(hFtp, "non_existent_file_deadbeef");
ok ( bRet == FALSE, "Expected FtpDeleteFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
"Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
/* One small test to show that handle type is checked before parameters */
SetLastError(0xdeadbeef);
bRet = FtpDeleteFileA(hConnect, NULL);
ok ( bRet == FALSE, "Expected FtpDeleteFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
bRet = FtpDeleteFileA(hConnect, "non_existent_file_deadbeef");
ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
}
static void test_getfile(HINTERNET hFtp, HINTERNET hConnect)
{
BOOL bRet;
HANDLE hFile;
/* The order of checking is:
*
* All parameters except 'session handle' and 'condition flags'
* Session handle
* Session handle type
* Condition flags
*/
/* Test to show the parameter checking order depends on the Windows version */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(NULL, NULL, "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_HANDLE ||
GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_HANDLE (win98) or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* Test to show session handle is checked before 'condition flags' */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(NULL, "welcome.msg", "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, 5, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
/* Make sure we start clean */
DeleteFileA("should_be_non_existing_deadbeef");
DeleteFileA("should_also_be_non_existing_deadbeef");
/* No remote file */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hFtp, NULL, "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
ok (GetFileAttributesA("should_be_non_existing_deadbeef") == INVALID_FILE_ATTRIBUTES,
"Local file should not have been created\n");
DeleteFileA("should_be_non_existing_deadbeef");
/* No local file */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hFtp, "welcome.msg", NULL, FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* Zero attributes */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hFtp, "welcome.msg", "should_be_existing_non_deadbeef", FALSE, 0, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == TRUE, "Expected FtpGetFileA to succeed\n");
ok (GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
ok (GetFileAttributesA("should_be_existing_non_deadbeef") != INVALID_FILE_ATTRIBUTES,
"Local file should have been created\n");
DeleteFileA("should_be_existing_non_deadbeef");
/* Illegal condition flags */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hFtp, "welcome.msg", "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, 0xffffffff, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR || GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INTERNET_EXTENDED_ERROR or ERROR_INVALID_PARAMETER (win98), got %d\n", GetLastError());
ok (GetFileAttributesA("should_be_non_existing_deadbeef") == INVALID_FILE_ATTRIBUTES,
"Local file should not have been created\n");
DeleteFileA("should_be_non_existing_deadbeef");
/* Remote file doesn't exist (and local doesn't exist as well) */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hFtp, "should_be_non_existing_deadbeef", "should_also_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
"Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
/* Currently Wine always creates the local file (even on failure) which is not correct, hence the test */
todo_wine
ok (GetFileAttributesA("should_also_be_non_existing_deadbeef") == INVALID_FILE_ATTRIBUTES,
"Local file should not have been created\n");
DeleteFileA("should_also_be_non_existing_deadbeef");
/* Same call as the previous but now the local file does exists. Windows just removes the file if the call fails
* even if the local existed before!
*/
/* Create a temporary local file */
SetLastError(0xdeadbeef);
hFile = CreateFileA("should_also_be_non_existing_deadbeef", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
ok ( hFile != NULL, "Error creating a local file : %d\n", GetLastError());
CloseHandle(hFile);
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hFtp, "should_be_non_existing_deadbeef", "should_also_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
"Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
/* Currently Wine always creates the local file (even on failure) which is not correct, hence the test */
todo_wine
ok (GetFileAttributesA("should_also_be_non_existing_deadbeef") == INVALID_FILE_ATTRIBUTES,
"Local file should not have been created\n");
DeleteFileA("should_also_be_non_existing_deadbeef");
/* This one should succeed */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hFtp, "welcome.msg", "should_be_existing_non_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == TRUE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
if (GetFileAttributesA("should_be_existing_non_deadbeef") != INVALID_FILE_ATTRIBUTES)
{
/* Should succeed as fFailIfExists is set to FALSE (meaning don't fail if local file exists) */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hFtp, "welcome.msg", "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == TRUE, "Expected FtpGetFileA to succeed\n");
ok ( GetLastError() == ERROR_SUCCESS,
"Expected ERROR_SUCCESS, got %d\n", GetLastError());
/* Should fail as fFailIfExists is set to TRUE */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hFtp, "welcome.msg", "should_be_non_existing_deadbeef", TRUE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_FILE_EXISTS,
"Expected ERROR_FILE_EXISTS, got %d\n", GetLastError());
/* Prove that the existence of the local file is checked first (or at least reported last) */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hFtp, "should_be_non_existing_deadbeef", "should_be_non_existing_deadbeef", TRUE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_FILE_EXISTS,
"Expected ERROR_FILE_EXISTS, got %d\n", GetLastError());
DeleteFileA("should_be_existing_non_deadbeef");
}
/* Test to show the parameter checking order depends on the Windows version */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hConnect, NULL, "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE ||
GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE (win98) or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* Test to show that 'session handle type' is checked before 'condition flags' */
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hConnect, "welcome.msg", "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, 5, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hConnect, "should_be_non_existing_deadbeef", "should_be_non_existing_deadbeef", TRUE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
}
static void test_openfile(HINTERNET hFtp, HINTERNET hConnect)
{
HINTERNET hOpenFile;
/* Invalid internet handle, the rest are valid parameters */
SetLastError(0xdeadbeef);
hOpenFile = FtpOpenFileA(NULL, "welcome.msg", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
ok ( !hOpenFile, "Expected FtpOpenFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
InternetCloseHandle(hOpenFile); /* Just in case */
/* No filename */
SetLastError(0xdeadbeef);
hOpenFile = FtpOpenFileA(hFtp, NULL, GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
ok ( !hOpenFile, "Expected FtpOpenFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
InternetCloseHandle(hOpenFile); /* Just in case */
/* Illegal access flags */
SetLastError(0xdeadbeef);
hOpenFile = FtpOpenFileA(hFtp, "welcome.msg", 0, FTP_TRANSFER_TYPE_ASCII, 0);
ok ( !hOpenFile, "Expected FtpOpenFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
InternetCloseHandle(hOpenFile); /* Just in case */
/* Illegal combination of access flags */
SetLastError(0xdeadbeef);
hOpenFile = FtpOpenFileA(hFtp, "welcome.msg", GENERIC_READ|GENERIC_WRITE, FTP_TRANSFER_TYPE_ASCII, 0);
ok ( !hOpenFile, "Expected FtpOpenFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
InternetCloseHandle(hOpenFile); /* Just in case */
/* Illegal condition flags */
SetLastError(0xdeadbeef);
hOpenFile = FtpOpenFileA(hFtp, "welcome.msg", GENERIC_READ, 0xffffffff, 0);
ok ( !hOpenFile, "Expected FtpOpenFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR || GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INTERNET_EXTENDED_ERROR or ERROR_INVALID_PARAMETER (win98), got %d\n", GetLastError());
InternetCloseHandle(hOpenFile); /* Just in case */
SetLastError(0xdeadbeef);
hOpenFile = FtpOpenFileA(hFtp, "welcome.msg", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
ok ( hOpenFile != NULL, "Expected FtpOpenFileA to succeed\n");
ok ( GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", GetLastError());
if (hOpenFile)
{
BOOL bRet;
HINTERNET hOpenFile2;
HANDLE hFile;
/* We have a handle so all ftp calls should fail (TODO: Put all ftp-calls in here) */
SetLastError(0xdeadbeef);
bRet = FtpCreateDirectoryA(hFtp, "new_directory_deadbeef");
ok ( bRet == FALSE, "Expected FtpCreateDirectoryA to fail\n");
ok ( GetLastError() == ERROR_FTP_TRANSFER_IN_PROGRESS,
"Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
bRet = FtpDeleteFileA(hFtp, "non_existent_file_deadbeef");
ok ( bRet == FALSE, "Expected FtpDeleteFileA to fail\n");
ok ( GetLastError() == ERROR_FTP_TRANSFER_IN_PROGRESS,
"Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
bRet = FtpGetFileA(hFtp, "welcome.msg", "should_be_non_existing_deadbeef", FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpGetFileA to fail\n");
ok ( GetLastError() == ERROR_FTP_TRANSFER_IN_PROGRESS,
"Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", GetLastError());
DeleteFileA("should_be_non_existing_deadbeef"); /* Just in case */
SetLastError(0xdeadbeef);
hOpenFile2 = FtpOpenFileA(hFtp, "welcome.msg", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
ok ( bRet == FALSE, "Expected FtpOpenFileA to fail\n");
ok ( GetLastError() == ERROR_FTP_TRANSFER_IN_PROGRESS,
"Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", GetLastError());
InternetCloseHandle(hOpenFile2); /* Just in case */
/* Create a temporary local file */
SetLastError(0xdeadbeef);
hFile = CreateFileA("now_existing_local", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
ok ( hFile != NULL, "Error creating a local file : %d\n", GetLastError());
CloseHandle(hFile);
SetLastError(0xdeadbeef);
bRet = FtpPutFileA(hFtp, "now_existing_local", "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
ok ( GetLastError() == ERROR_FTP_TRANSFER_IN_PROGRESS,
"Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", GetLastError());
DeleteFileA("now_existing_local");
SetLastError(0xdeadbeef);
bRet = FtpRemoveDirectoryA(hFtp, "should_be_non_existing_deadbeef_dir");
ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
ok ( GetLastError() == ERROR_FTP_TRANSFER_IN_PROGRESS,
"Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
bRet = FtpRenameFileA(hFtp , "should_be_non_existing_deadbeef", "new");
ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
ok ( GetLastError() == ERROR_FTP_TRANSFER_IN_PROGRESS,
"Expected ERROR_FTP_TRANSFER_IN_PROGRESS, got %d\n", GetLastError());
}
InternetCloseHandle(hOpenFile);
/* One small test to show that handle type is checked before parameters */
SetLastError(0xdeadbeef);
hOpenFile = FtpOpenFileA(hConnect, "welcome.msg", GENERIC_READ, 5, 0);
ok ( !hOpenFile, "Expected FtpOpenFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
InternetCloseHandle(hOpenFile); /* Just in case */
SetLastError(0xdeadbeef);
hOpenFile = FtpOpenFileA(hConnect, "welcome.msg", GENERIC_READ, FTP_TRANSFER_TYPE_ASCII, 0);
ok ( hOpenFile == NULL, "Expected FtpOpenFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
InternetCloseHandle(hOpenFile); /* Just in case */
}
static void test_putfile(HINTERNET hFtp, HINTERNET hConnect)
{
BOOL bRet;
HANDLE hFile;
/* The order of checking is:
*
* All parameters except 'session handle' and 'condition flags'
* Session handle
* Session handle type
* Condition flags
*/
/* Test to show the parameter checking order depends on the Windows version */
SetLastError(0xdeadbeef);
bRet = FtpPutFileA(NULL, NULL, "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_HANDLE ||
GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_HANDLE (win98) or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* Test to show session handle is checked before 'condition flags' */
SetLastError(0xdeadbeef);
bRet = FtpPutFileA(NULL, "non_existing_local", "non_existing_remote", 5, 0);
ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
/* Start clean */
DeleteFileA("non_existing_local");
/* No local file given */
SetLastError(0xdeadbeef);
bRet = FtpPutFileA(hFtp, NULL, "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* No remote file given */
SetLastError(0xdeadbeef);
bRet = FtpPutFileA(hFtp, "non_existing_local", NULL, FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* Illegal condition flags */
SetLastError(0xdeadbeef);
bRet = FtpPutFileA(hFtp, "non_existing_local", "non_existing_remote", 5, 0);
ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
ok ( GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_FILE_NOT_FOUND or ERROR_INVALID_PARAMETER (win98), got %d\n", GetLastError());
/* Parameters are OK but local file doesn't exist */
SetLastError(0xdeadbeef);
bRet = FtpPutFileA(hFtp, "non_existing_local", "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
ok ( GetLastError() == ERROR_FILE_NOT_FOUND,
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
/* Create a temporary local file */
SetLastError(0xdeadbeef);
hFile = CreateFileA("now_existing_local", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
ok ( hFile != NULL, "Error creating a local file : %d\n", GetLastError());
CloseHandle(hFile);
/* Local file exists but we shouldn't be allowed to 'put' the file */
SetLastError(0xdeadbeef);
bRet = FtpPutFileA(hFtp, "now_existing_local", "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
"Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
DeleteFileA("now_existing_local");
/* Test to show the parameter checking order depends on the Windows version */
SetLastError(0xdeadbeef);
bRet = FtpPutFileA(hConnect, NULL, "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE ||
GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE (win98) or ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* Test to show that 'session handle type' is checked before 'condition flags' */
SetLastError(0xdeadbeef);
bRet = FtpPutFileA(hConnect, "non_existing_local", "non_existing_remote", 5, 0);
ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
bRet = FtpPutFileA(hConnect, "non_existing_local", "non_existing_remote", FTP_TRANSFER_TYPE_UNKNOWN, 0);
ok ( bRet == FALSE, "Expected FtpPutFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
}
static void test_removedir(HINTERNET hFtp, HINTERNET hConnect)
{
BOOL bRet;
/* Invalid internet handle, the other is a valid parameter */
SetLastError(0xdeadbeef);
bRet = FtpRemoveDirectoryA(NULL, "should_be_non_existing_deadbeef_dir");
ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
ok ( GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
/* No remote directory given */
SetLastError(0xdeadbeef);
bRet = FtpRemoveDirectoryA(hFtp, NULL);
ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* Remote directory doesn't exist */
SetLastError(0xdeadbeef);
bRet = FtpRemoveDirectoryA(hFtp, "should_be_non_existing_deadbeef_dir");
ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
"Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
/* We shouldn't be allowed to remove that directory */
SetLastError(0xdeadbeef);
bRet = FtpRemoveDirectoryA(hFtp, "pub");
ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
"Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
/* One small test to show that handle type is checked before parameters */
SetLastError(0xdeadbeef);
bRet = FtpRemoveDirectoryA(hConnect, NULL);
ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
bRet = FtpRemoveDirectoryA(hConnect, "should_be_non_existing_deadbeef_dir");
ok ( bRet == FALSE, "Expected FtpRemoveDirectoryA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
}
static void test_renamefile(HINTERNET hFtp, HINTERNET hConnect)
{
BOOL bRet;
/* Invalid internet handle, the rest are valid parameters */
SetLastError(0xdeadbeef);
bRet = FtpRenameFileA(NULL , "should_be_non_existing_deadbeef", "new");
ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_HANDLE,
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
/* No 'existing' file */
SetLastError(0xdeadbeef);
bRet = FtpRenameFileA(hFtp , NULL, "new");
ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* No new file */
SetLastError(0xdeadbeef);
bRet = FtpRenameFileA(hFtp , "should_be_non_existing_deadbeef", NULL);
ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
/* Existing file shouldn't be there */
SetLastError(0xdeadbeef);
bRet = FtpRenameFileA(hFtp , "should_be_non_existing_deadbeef", "new");
ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_EXTENDED_ERROR,
"Expected ERROR_INTERNET_EXTENDED_ERROR, got %d\n", GetLastError());
/* One small test to show that handle type is checked before parameters */
SetLastError(0xdeadbeef);
bRet = FtpRenameFileA(hConnect , "should_be_non_existing_deadbeef", NULL);
ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
bRet = FtpRenameFileA(hConnect , "should_be_non_existing_deadbeef", "new");
ok ( bRet == FALSE, "Expected FtpRenameFileA to fail\n");
ok ( GetLastError() == ERROR_INTERNET_INCORRECT_HANDLE_TYPE,
"Expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %d\n", GetLastError());
}
static void test_command(HINTERNET hFtp, HINTERNET hConnect)
{
BOOL ret;
DWORD error;
unsigned int i;
static const struct
{
BOOL ret;
DWORD error;
const char *cmd;
}
command_test[] =
{
{ FALSE, ERROR_INVALID_PARAMETER, NULL },
{ FALSE, ERROR_INVALID_PARAMETER, "" },
{ FALSE, ERROR_INTERNET_EXTENDED_ERROR, "HELO" },
{ FALSE, ERROR_INTERNET_EXTENDED_ERROR, "SIZE " },
{ FALSE, ERROR_INTERNET_EXTENDED_ERROR, " SIZE" },
{ FALSE, ERROR_INTERNET_EXTENDED_ERROR, "SIZE " },
{ FALSE, ERROR_INTERNET_EXTENDED_ERROR, "SIZE /welcome.msg /welcome.msg" },
{ FALSE, ERROR_INTERNET_EXTENDED_ERROR, "SIZE /welcome.msg" },
{ FALSE, ERROR_INTERNET_EXTENDED_ERROR, "SIZE /welcome.msg " },
{ TRUE, ERROR_SUCCESS, "SIZE\t/welcome.msg" },
{ TRUE, ERROR_SUCCESS, "SIZE /welcome.msg" },
{ FALSE, ERROR_INTERNET_EXTENDED_ERROR, "PWD /welcome.msg" },
{ TRUE, ERROR_SUCCESS, "PWD" },
{ TRUE, ERROR_SUCCESS, "PWD\r\n" }
};
for (i = 0; i < sizeof(command_test) / sizeof(command_test[0]); i++)
{
SetLastError(0xdeadbeef);
ret = FtpCommandA(hFtp, FALSE, FTP_TRANSFER_TYPE_ASCII, command_test[i].cmd, 0, NULL);
error = GetLastError();
ok(ret == command_test[i].ret, "%d: expected FtpCommandA to %s\n", i, command_test[i].ret ? "succeed" : "fail");
ok(error == command_test[i].error, "%d: expected error %u, got %u\n", i, command_test[i].error, error);
}
}
START_TEST(ftp)
{
HANDLE hInternet, hFtp, hHttp;
SetLastError(0xdeadbeef);
hInternet = InternetOpen("winetest", 0, NULL, NULL, 0);
ok(hInternet != NULL, "InternetOpen failed: %u\n", GetLastError());
hFtp = InternetConnect(hInternet, "ftp.winehq.org", INTERNET_DEFAULT_FTP_PORT, "anonymous", NULL, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
if (!hFtp)
{
InternetCloseHandle(hInternet);
skip("No ftp connection could be made to ftp.winehq.org\n");
return;
}
hHttp = InternetConnect(hInternet, "www.winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (!hHttp)
{
InternetCloseHandle(hFtp);
InternetCloseHandle(hInternet);
skip("No http connection could be made to www.winehq.org\n");
return;
}
/* The first call should always be a proper InternetOpen, if not
* several calls will return ERROR_INTERNET_NOT_INITIALIZED when
* all parameters are correct but no session handle is given. Whereas
* the same call will return ERROR_INVALID_HANDLE if an InternetOpen
* is done before.
* The following test will show that behaviour, where the tests inside
* the other sub-tests will show the other situation.
*/
test_getfile_no_open();
test_connect(hInternet);
test_createdir(hFtp, hHttp);
test_deletefile(hFtp, hHttp);
test_getfile(hFtp, hHttp);
test_openfile(hFtp, hHttp);
test_putfile(hFtp, hHttp);
test_removedir(hFtp, hHttp);
test_renamefile(hFtp, hHttp);
test_command(hFtp, hHttp);
InternetCloseHandle(hHttp);
InternetCloseHandle(hFtp);
InternetCloseHandle(hInternet);
}

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more