diff --git a/rostests/winetests/setupapi/install.c b/rostests/winetests/setupapi/install.c index 5361238fb3b..668b2c2565b 100644 --- a/rostests/winetests/setupapi/install.c +++ b/rostests/winetests/setupapi/install.c @@ -35,6 +35,7 @@ #include "wine/test.h" static const char inffile[] = "test.inf"; +static const WCHAR inffileW[] = {'t','e','s','t','.','i','n','f',0}; static char CURR_DIR[MAX_PATH]; /* Notes on InstallHinfSectionA/W: @@ -52,6 +53,7 @@ static char CURR_DIR[MAX_PATH]; static void (WINAPI *pInstallHinfSectionA)(HWND, HINSTANCE, LPCSTR, INT); static void (WINAPI *pInstallHinfSectionW)(HWND, HINSTANCE, LPCWSTR, INT); +static BOOL (WINAPI *pSetupGetInfFileListW)(PCWSTR, DWORD, PWSTR, DWORD, PDWORD); /* * Helpers @@ -466,6 +468,177 @@ cleanup: DeleteFile(inffile); } +static void test_inffilelist(void) +{ + static const char inffile2[] = "test2.inf"; + static const WCHAR inffile2W[] = {'t','e','s','t','2','.','i','n','f',0}; + static const char invalid_inf[] = "invalid.inf"; + static const WCHAR invalid_infW[] = {'i','n','v','a','l','i','d','.','i','n','f',0}; + static const char *inf = + "[Version]\n" + "Signature=\"$Chicago$\""; + static const char *inf2 = + "[Version]\n" + "Signature=\"$CHICAGO$\""; + static const char *infNT = + "[Version]\n" + "Signature=\"$WINDOWS NT$\""; + + WCHAR *p, *ptr; + char dirA[MAX_PATH]; + WCHAR dir[MAX_PATH] = { 0 }; + WCHAR buffer[MAX_PATH] = { 0 }; + DWORD expected, outsize; + BOOL ret; + + if(!pSetupGetInfFileListW) + { + win_skip("SetupGetInfFileListW not present\n"); + return; + } + + /* NULL means %windir%\\inf + * get the value as reference + */ + expected = 0; + SetLastError(0xdeadbeef); + ret = pSetupGetInfFileListW(NULL, INF_STYLE_WIN4, NULL, 0, &expected); + if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + win_skip("SetupGetInfFileListW not implemented\n"); + return; + } + ok(ret, "expected SetupGetInfFileListW to succeed! Error: %d\n", GetLastError()); + ok(expected > 0, "expected required buffersize to be at least 1\n"); + + /* check if an empty string doesn't behaves like NULL */ + outsize = 0; + SetLastError(0xdeadbeef); + ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize); + ok(!ret, "expected SetupGetInfFileListW to fail!\n"); + + /* create a private directory, the temp directory may contain some + * inf files left over from old installations + */ + if (!GetTempFileNameA(CURR_DIR, "inftest", 1, dirA)) + { + win_skip("GetTempFileNameA failed with error %d\n", GetLastError()); + return; + } + if (!CreateDirectoryA(dirA, NULL )) + { + win_skip("CreateDirectoryA(%s) failed with error %d\n", dirA, GetLastError()); + return; + } + if (!SetCurrentDirectoryA(dirA)) + { + win_skip("SetCurrentDirectoryA failed with error %d\n", GetLastError()); + RemoveDirectoryA(dirA); + return; + } + + MultiByteToWideChar(CP_ACP, 0, dirA, -1, dir, MAX_PATH); + /* check a not existing directory + */ + ptr = dir + lstrlenW(dir); + MultiByteToWideChar(CP_ACP, 0, "\\not_existent", -1, ptr, MAX_PATH - lstrlenW(dir)); + outsize = 0xffffffff; + SetLastError(0xdeadbeef); + ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize); + ok(ret, "expected SetupGetInfFileListW to succeed!\n"); + ok(outsize == 1, "expected required buffersize to be 1, got %d\n", outsize); + ok(ERROR_PATH_NOT_FOUND == GetLastError(), + "expected error ERROR_PATH_NOT_FOUND, got %d\n", GetLastError()); + + create_inf_file(inffile, inf); + create_inf_file(inffile2, inf); + create_inf_file(invalid_inf, "This content does not match the inf file format"); + + /* pass a filename instead of a directory + */ + *ptr = '\\'; + MultiByteToWideChar(CP_ACP, 0, invalid_inf, -1, ptr+1, MAX_PATH - lstrlenW(dir)); + outsize = 0xffffffff; + SetLastError(0xdeadbeef); + ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize); + ok(!ret, "expected SetupGetInfFileListW to fail!\n"); + ok(ERROR_DIRECTORY == GetLastError(), + "expected error ERROR_DIRECTORY, got %d\n", GetLastError()); + + /* make the filename look like directory + */ + dir[1 + lstrlenW(dir)] = 0; + dir[lstrlenW(dir)] = '\\'; + SetLastError(0xdeadbeef); + ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize); + ok(!ret, "expected SetupGetInfFileListW to fail!\n"); + ok(ERROR_DIRECTORY == GetLastError(), + "expected error ERROR_DIRECTORY, got %d\n", GetLastError()); + + /* now check the buffer content of a vaild call + */ + *ptr = 0; + expected = 3 + strlen(inffile) + strlen(inffile2); + ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize); + ok(ret, "expected SetupGetInfFileListW to succeed!\n"); + ok(expected == outsize, "expected required buffersize to be %d, got %d\n", + expected, outsize); + for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1) + ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW), + "unexpected filename %s\n",wine_dbgstr_w(p)); + + /* upper case value + */ + create_inf_file(inffile2, inf2); + ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize); + ok(ret, "expected SetupGetInfFileListW to succeed!\n"); + ok(expected == outsize, "expected required buffersize to be %d, got %d\n", + expected, outsize); + for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1) + ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW), + "unexpected filename %s\n",wine_dbgstr_w(p)); + + /* signature Windows NT is also inf style win4 + */ + create_inf_file(inffile2, infNT); + expected = 3 + strlen(inffile) + strlen(inffile2); + ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize); + ok(ret, "expected SetupGetInfFileListW to succeed!\n"); + ok(expected == outsize, "expected required buffersize to be %d, got %d\n", + expected, outsize); + for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1) + ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW), + "unexpected filename %s\n",wine_dbgstr_w(p)); + + /* old style + */ + expected = 2 + strlen(invalid_inf); + ret = pSetupGetInfFileListW(dir, INF_STYLE_OLDNT, buffer, MAX_PATH, &outsize); + ok(ret, "expected SetupGetInfFileListW to succeed!\n"); + ok(expected == outsize, "expected required buffersize to be %d, got %d\n", + expected, outsize); + for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1) + ok(!lstrcmpW(p,invalid_infW), "unexpected filename %s\n",wine_dbgstr_w(p)); + + /* mixed style + */ + expected = 4 + strlen(inffile) + strlen(inffile2) + strlen(invalid_inf); + ret = pSetupGetInfFileListW(dir, INF_STYLE_OLDNT | INF_STYLE_WIN4, buffer, + MAX_PATH, &outsize); + ok(ret, "expected SetupGetInfFileListW to succeed!\n"); + ok(expected == outsize, "expected required buffersize to be %d, got %d\n", + expected, outsize); + for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1) + ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW) || !lstrcmpW(p,invalid_infW), + "unexpected filename %s\n",wine_dbgstr_w(p)); + + DeleteFile(inffile); + DeleteFile(inffile2); + DeleteFile(invalid_inf); + SetCurrentDirectoryA(CURR_DIR); + RemoveDirectoryA(dirA); +} + START_TEST(install) { HMODULE hsetupapi = GetModuleHandle("setupapi.dll"); @@ -483,6 +656,8 @@ START_TEST(install) pInstallHinfSectionA = (void *)GetProcAddress(hsetupapi, "InstallHinfSectionA"); pInstallHinfSectionW = (void *)GetProcAddress(hsetupapi, "InstallHinfSectionW"); + pSetupGetInfFileListW = (void *)GetProcAddress(hsetupapi, "SetupGetInfFileListW"); + if (pInstallHinfSectionA) { /* Check if pInstallHinfSectionA sets last error or is a stub (as on WinXP) */ @@ -519,5 +694,7 @@ START_TEST(install) test_profile_items(); } + test_inffilelist(); + SetCurrentDirectory(prev_path); } diff --git a/rostests/winetests/setupapi/misc.c b/rostests/winetests/setupapi/misc.c index e110e221e8b..a3abde46746 100644 --- a/rostests/winetests/setupapi/misc.c +++ b/rostests/winetests/setupapi/misc.c @@ -46,6 +46,7 @@ static CHAR CURR_DIR[MAX_PATH]; static BOOL (WINAPI *pSetupGetFileCompressionInfoExA)(PCSTR, PSTR, DWORD, PDWORD, PDWORD, PDWORD, PUINT); static BOOL (WINAPI *pSetupCopyOEMInfA)(PCSTR, PCSTR, DWORD, DWORD, PSTR, DWORD, PDWORD, PSTR *); static BOOL (WINAPI *pSetupQueryInfOriginalFileInformationA)(PSP_INF_INFORMATION, UINT, PSP_ALTPLATFORM_INFO, PSP_ORIGINAL_FILE_INFO_A); +static BOOL (WINAPI *pSetupUninstallOEMInfA)(PCSTR, DWORD, PVOID); static void create_inf_file(LPCSTR filename) { @@ -196,21 +197,23 @@ static void test_SetupCopyOEMInf(void) /* try a relative SourceInfFileName */ SetLastError(0xdeadbeef); res = pSetupCopyOEMInfA(tmpfile, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL); - ok(res == FALSE, "Expected FALSE, got %d\n", res); - if (GetLastError() == ERROR_WRONG_INF_TYPE) + ok(res == FALSE || + broken(res == TRUE), /* Win98 */ + "Expected FALSE, got %d\n", res); + if (GetLastError() == ERROR_WRONG_INF_TYPE || GetLastError() == ERROR_UNSUPPORTED_TYPE /* Win7 */) { /* FIXME: * Vista needs a [Manufacturer] entry in the inf file. Doing this will give some * popups during the installation though as it also needs a catalog file (signed?). */ - win_skip("Needs a different inf file on Vista/W2K8\n"); + win_skip("Needs a different inf file on Vista+\n"); DeleteFile(tmpfile); return; } ok(GetLastError() == ERROR_FILE_NOT_FOUND || - GetLastError() == ERROR_FILE_EXISTS, /* Win98 */ - "Expected ERROR_FILE_NOT_FOUND or ERROR_FILE_EXISTS, got %d\n", GetLastError()); + broken(GetLastError() == ERROR_SUCCESS), /* Win98 */ + "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); ok(file_exists(tmpfile), "Expected tmpfile to exist\n"); /* try SP_COPY_REPLACEONLY, dest does not exist */ @@ -306,6 +309,24 @@ static void test_SetupCopyOEMInf(void) ok(res == TRUE, "Expected TRUE, got %d\n", res); ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError()); ok(!file_exists(path), "Expected source inf to not exist\n"); + + if (pSetupUninstallOEMInfA) + { + char *destfile = strrchr(dest, '\\') + 1; + + SetLastError(0xdeadbeef); + ok(pSetupUninstallOEMInfA(destfile, 0, NULL), "Failed to uninstall '%s' : %d\n", destfile, GetLastError()); + } + else + { + /* Win9x/WinMe */ + SetLastError(0xdeadbeef); + ok(DeleteFileA(dest), "Failed to delete file '%s' : %d\n", dest, GetLastError()); + + /* On WinMe we also need to remove the .pnf file */ + *(strrchr(dest, '.') + 1) = 'p'; + DeleteFileA(dest); + } } static void create_source_file(LPSTR filename, const BYTE *data, DWORD size) @@ -581,6 +602,32 @@ static void test_SetupDecompressOrCopyFile(void) DeleteFileA(source); } +static void test_SetupUninstallOEMInf(void) +{ + BOOL ret; + + SetLastError(0xdeadbeef); + ret = pSetupUninstallOEMInfA(NULL, 0, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pSetupUninstallOEMInfA("", 0, NULL); + todo_wine + { + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); + } + + SetLastError(0xdeadbeef); + ret = pSetupUninstallOEMInfA("nonexistent.inf", 0, NULL); + todo_wine + { + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); + } +} + START_TEST(misc) { HMODULE hsetupapi = GetModuleHandle("setupapi.dll"); @@ -588,6 +635,7 @@ START_TEST(misc) pSetupGetFileCompressionInfoExA = (void*)GetProcAddress(hsetupapi, "SetupGetFileCompressionInfoExA"); pSetupCopyOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupCopyOEMInfA"); pSetupQueryInfOriginalFileInformationA = (void*)GetProcAddress(hsetupapi, "SetupQueryInfOriginalFileInformationA"); + pSetupUninstallOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupUninstallOEMInfA"); GetCurrentDirectoryA(MAX_PATH, CURR_DIR); @@ -604,4 +652,9 @@ START_TEST(misc) win_skip("SetupGetFileCompressionInfoExA is not available\n"); test_SetupDecompressOrCopyFile(); + + if (pSetupUninstallOEMInfA) + test_SetupUninstallOEMInf(); + else + win_skip("SetupUninstallOEMInfA is not available\n"); } diff --git a/rostests/winetests/setupapi/parser.c b/rostests/winetests/setupapi/parser.c index 91a84252804..072ac9794cc 100644 --- a/rostests/winetests/setupapi/parser.c +++ b/rostests/winetests/setupapi/parser.c @@ -32,14 +32,18 @@ /* function pointers */ static HMODULE hSetupAPI; -static LPCWSTR (WINAPI *pSetupGetField)(PINFCONTEXT,DWORD); +static LPCSTR (WINAPI *pSetupGetFieldA)(PINFCONTEXT,DWORD); +static LPCWSTR (WINAPI *pSetupGetFieldW)(PINFCONTEXT,DWORD); static BOOL (WINAPI *pSetupEnumInfSectionsA)( HINF hinf, UINT index, PSTR buffer, DWORD size, UINT *need ); static void init_function_pointers(void) { hSetupAPI = GetModuleHandleA("setupapi.dll"); - pSetupGetField = (void *)GetProcAddress(hSetupAPI, "pSetupGetField"); + /* Nice, pSetupGetField is either A or W depending on the Windows version! The actual test + * takes care of this difference */ + pSetupGetFieldA = (void *)GetProcAddress(hSetupAPI, "pSetupGetField"); + pSetupGetFieldW = (void *)GetProcAddress(hSetupAPI, "pSetupGetField"); pSetupEnumInfSectionsA = (void *)GetProcAddress(hSetupAPI, "SetupEnumInfSectionsA" ); } @@ -497,7 +501,14 @@ static const char *contents = "[Version]\n" "[Strings]\n" "RTMQFE_NAME = \"RTMQFE\"\n"; -static const WCHAR getfield_res[][20] = +static const CHAR getfield_resA[][20] = +{ + "RTMQFE", + "%RTMGFE_NAME%", + "SP1RTM", +}; + +static const WCHAR getfield_resW[][20] = { {'R','T','M','Q','F','E',0}, {'%','R','T','M','G','F','E','_','N','A','M','E','%',0}, @@ -509,10 +520,20 @@ static void test_pSetupGetField(void) UINT err; BOOL ret; HINF hinf; - LPCWSTR field; + LPCSTR fieldA; + LPCWSTR fieldW; INFCONTEXT context; int i; int len; + BOOL unicode = TRUE; + + SetLastError(0xdeadbeef); + lstrcmpW(NULL, NULL); + if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + win_skip("Using A-functions instead of W\n"); + unicode = FALSE; + } hinf = test_file_contents( contents, &err ); ok( hinf != NULL, "Expected valid INF file\n" ); @@ -524,23 +545,47 @@ static void test_pSetupGetField(void) for ( i = 0; i < 3; i++ ) { - field = pSetupGetField( &context, i ); - ok( field != NULL, "Failed to get field %i\n", i ); - ok( !lstrcmpW( getfield_res[i], field ), "Wrong string returned\n" ); + if (unicode) + { + fieldW = pSetupGetFieldW( &context, i ); + ok( fieldW != NULL, "Failed to get field %i\n", i ); + ok( !lstrcmpW( getfield_resW[i], fieldW ), "Wrong string returned\n" ); + } + else + { + fieldA = pSetupGetFieldA( &context, i ); + ok( fieldA != NULL, "Failed to get field %i\n", i ); + ok( !lstrcmpA( getfield_resA[i], fieldA ), "Wrong string returned\n" ); + } } - field = pSetupGetField( &context, 3 ); - ok( field != NULL, "Failed to get field 3\n" ); - len = lstrlenW( field ); - ok( len == 511 /* NT4, W2K, XP and W2K3 */ || - len == 4096 /* Vista */ || - len == 256 /* Win9x and WinME */, - "Unexpected length, got %d\n", len ); + if (unicode) + { + fieldW = pSetupGetFieldW( &context, 3 ); + ok( fieldW != NULL, "Failed to get field 3\n" ); + len = lstrlenW( fieldW ); + ok( len == 511 || /* NT4, W2K, XP and W2K3 */ + len == 4096, /* Vista */ + "Unexpected length, got %d\n", len ); - field = pSetupGetField( &context, 4 ); - ok( field == NULL, "Expected NULL, got %p\n", field ); - ok( GetLastError() == ERROR_INVALID_PARAMETER, - "Expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() ); + fieldW = pSetupGetFieldW( &context, 4 ); + ok( fieldW == NULL, "Expected NULL, got %p\n", fieldW ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() ); + } + else + { + fieldA = pSetupGetFieldA( &context, 3 ); + ok( fieldA != NULL, "Failed to get field 3\n" ); + len = lstrlenA( fieldA ); + ok( len == 511, /* Win9x, WinME */ + "Unexpected length, got %d\n", len ); + + fieldA = pSetupGetFieldA( &context, 4 ); + ok( fieldA == NULL, "Expected NULL, got %p\n", fieldA ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() ); + } SetupCloseInfFile( hinf ); } @@ -557,14 +602,14 @@ static void test_SetupGetIntField(void) } keys[] = { /* key fields index expected int errorcode */ - { "Key=", "48", 1, 48, ERROR_SUCCESS }, - { "Key=", "48", 0, -1, ERROR_INVALID_DATA }, - { "123=", "48", 0, 123, ERROR_SUCCESS }, - { "Key=", "0x4", 1, 4, ERROR_SUCCESS }, - { "Key=", "Field1", 1, -1, ERROR_INVALID_DATA }, - { "Key=", "Field1,34", 2, 34, ERROR_SUCCESS }, - { "Key=", "Field1,,Field3", 2, 0, ERROR_SUCCESS }, - { "Key=", "Field1,", 2, 0, ERROR_SUCCESS } + { "Key", "48", 1, 48, ERROR_SUCCESS }, + { "Key", "48", 0, -1, ERROR_INVALID_DATA }, + { "123", "48", 0, 123, ERROR_SUCCESS }, + { "Key", "0x4", 1, 4, ERROR_SUCCESS }, + { "Key", "Field1", 1, -1, ERROR_INVALID_DATA }, + { "Key", "Field1,34", 2, 34, ERROR_SUCCESS }, + { "Key", "Field1,,Field3", 2, 0, ERROR_SUCCESS }, + { "Key", "Field1,", 2, 0, ERROR_SUCCESS } }; unsigned int i; @@ -579,11 +624,12 @@ static void test_SetupGetIntField(void) strcpy( buffer, STD_HEADER "[TestSection]\n" ); strcat( buffer, keys[i].key ); + strcat( buffer, "=" ); strcat( buffer, keys[i].fields ); hinf = test_file_contents( buffer, &err); ok( hinf != NULL, "Expected valid INF file\n" ); - SetupFindFirstLineA( hinf, "TestSection", "Key", &context ); + SetupFindFirstLineA( hinf, "TestSection", keys[i].key, &context ); SetLastError( 0xdeadbeef ); intfield = -1; retb = SetupGetIntField( &context, keys[i].index, &intfield ); diff --git a/rostests/winetests/setupapi/query.c b/rostests/winetests/setupapi/query.c index 0b7883c6289..6e956a2a096 100644 --- a/rostests/winetests/setupapi/query.c +++ b/rostests/winetests/setupapi/query.c @@ -167,14 +167,15 @@ static void test_SetupGetInfInformation(void) broken(GetLastError() == ERROR_FILE_NOT_FOUND) || /* win98 */ broken(GetLastError() == ERROR_PATH_NOT_FOUND) || /* NT4 */ broken(GetLastError() == ERROR_INVALID_NAME) || /* win2k */ - broken(GetLastError() == ERROR_GENERAL_SYNTAX), /* another win2k */ + broken(GetLastError() == ERROR_GENERAL_SYNTAX), /* another win2k / winMe */ "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); ok(size == 0xdeadbeef, "Expected size to remain unchanged\n"); /* try an invalid inf filename */ - /* do not use NULL as absolute inf filename on win9x (crash) */ + /* do not use NULL as absolute inf filename on win9x/winMe (crash) */ if ((GetLastError() != ERROR_BAD_PATHNAME) && /* win95 */ - (GetLastError() != ERROR_FILE_NOT_FOUND)) /* win98 */ + (GetLastError() != ERROR_FILE_NOT_FOUND) && /* win98 */ + (GetLastError() != ERROR_GENERAL_SYNTAX)) /* winMe */ { size = 0xdeadbeef; SetLastError(0xbeefcafe); diff --git a/rostests/winetests/setupapi/stringtable.c b/rostests/winetests/setupapi/stringtable.c index cecfc237188..fbe1037da8a 100644 --- a/rostests/winetests/setupapi/stringtable.c +++ b/rostests/winetests/setupapi/stringtable.c @@ -301,6 +301,7 @@ static void test_StringTableLookUpStringEx(void) ok(!memcmp(buffer, &data, 4), "unexpected data\n"); pStringTableDestroy(table); + pStringTableDestroy(table2); } static void test_StringTableStringFromId(void)