In particular, February dates contain an e-acute in French, the representation of which depends on the code page being used, which in SHFormatDateTimeA() is CP_ACP.
Also there are only three months that triggered this bug in French: February, August and December. So also make sure to test this issue year round.
From: Francois Gouget fgouget@codeweavers.com
In particular, February dates contain an e-acute in French, the representation of which depends on the code page being used, which in SHFormatDateTimeA() is CP_ACP.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54149 --- dlls/shlwapi/tests/ordinal.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/dlls/shlwapi/tests/ordinal.c b/dlls/shlwapi/tests/ordinal.c index 603a2ac2a76..e2a6ee52a7d 100644 --- a/dlls/shlwapi/tests/ordinal.c +++ b/dlls/shlwapi/tests/ordinal.c @@ -1731,14 +1731,14 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
@@ -1746,21 +1746,21 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME | FDTF_SHORTTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
@@ -1768,7 +1768,7 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTDATE; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
@@ -1776,12 +1776,12 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS | LOCALE_USE_CP_ACP, &st, NULL, buff3, sizeof(buff3)); ok(ret == lstrlenA(buff3)+1, "got %d\n", ret); ok(lstrcmpA(buff3, buff + lstrlenA(buff) - lstrlenA(buff3)) == 0, "expected (%s), got (%s) for time part\n", buff3, buff + lstrlenA(buff) - lstrlenA(buff3)); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); buff[lstrlenA(buff2)] = '\0'; ok(lstrcmpA(buff2, buff) == 0, "expected (%s) got (%s) for date part\n", @@ -1790,12 +1790,12 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_LONGTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, &st, NULL, buff3, sizeof(buff3)); ok(ret == lstrlenA(buff3)+1, "got %d\n", ret); ok(lstrcmpA(buff3, buff + lstrlenA(buff) - lstrlenA(buff3)) == 0, "expected (%s), got (%s) for time part\n", buff3, buff + lstrlenA(buff) - lstrlenA(buff3)); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); buff[lstrlenA(buff2)] = '\0'; ok(lstrcmpA(buff2, buff) == 0, "expected (%s) got (%s) for date part\n", @@ -1804,10 +1804,10 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_SHORTTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); strcat(buff2, " "); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS | LOCALE_USE_CP_ACP, &st, NULL, buff3, sizeof(buff3)); ok(ret == lstrlenA(buff3)+1, "got %d\n", ret); strcat(buff2, buff3); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff); @@ -1815,10 +1815,10 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); strcat(buff2, " "); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, &st, NULL, buff3, sizeof(buff3)); ok(ret == lstrlenA(buff3)+1, "got %d\n", ret); strcat(buff2, buff3); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
From: Francois Gouget fgouget@codeweavers.com
Test the current date to ensure broad coverage, and specifically test a February date because, in the French locale, it shows that SHFormatDateTimeA() uses the CP_ACP code page, not the locale's default one.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54149 --- dlls/shlwapi/tests/ordinal.c | 46 +++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 19 deletions(-)
diff --git a/dlls/shlwapi/tests/ordinal.c b/dlls/shlwapi/tests/ordinal.c index e2a6ee52a7d..7cb997c304c 100644 --- a/dlls/shlwapi/tests/ordinal.c +++ b/dlls/shlwapi/tests/ordinal.c @@ -1666,16 +1666,14 @@ static void test_SHSetWindowBits(void) UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL)); }
-static void test_SHFormatDateTimeA(void) +static void test_SHFormatDateTimeA(const SYSTEMTIME *st) { FILETIME UNALIGNED filetime; CHAR buff[100], buff2[100], buff3[100]; - SYSTEMTIME st; DWORD flags; INT ret;
- GetLocalTime(&st); - SystemTimeToFileTime(&st, &filetime); + SystemTimeToFileTime(st, &filetime); /* SHFormatDateTime expects input as utc */ LocalFileTimeToFileTime(&filetime, &filetime);
@@ -1731,14 +1729,14 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS | LOCALE_USE_CP_ACP, st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
@@ -1746,21 +1744,21 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME | FDTF_SHORTTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE | LOCALE_USE_CP_ACP, st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE | LOCALE_USE_CP_ACP, st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
@@ -1768,7 +1766,7 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTDATE; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE | LOCALE_USE_CP_ACP, st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
@@ -1776,12 +1774,12 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS | LOCALE_USE_CP_ACP, &st, NULL, buff3, sizeof(buff3)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS | LOCALE_USE_CP_ACP, st, NULL, buff3, sizeof(buff3)); ok(ret == lstrlenA(buff3)+1, "got %d\n", ret); ok(lstrcmpA(buff3, buff + lstrlenA(buff) - lstrlenA(buff3)) == 0, "expected (%s), got (%s) for time part\n", buff3, buff + lstrlenA(buff) - lstrlenA(buff3)); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE | LOCALE_USE_CP_ACP, st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); buff[lstrlenA(buff2)] = '\0'; ok(lstrcmpA(buff2, buff) == 0, "expected (%s) got (%s) for date part\n", @@ -1790,12 +1788,12 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_LONGTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, &st, NULL, buff3, sizeof(buff3)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, st, NULL, buff3, sizeof(buff3)); ok(ret == lstrlenA(buff3)+1, "got %d\n", ret); ok(lstrcmpA(buff3, buff + lstrlenA(buff) - lstrlenA(buff3)) == 0, "expected (%s), got (%s) for time part\n", buff3, buff + lstrlenA(buff) - lstrlenA(buff3)); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE | LOCALE_USE_CP_ACP, st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); buff[lstrlenA(buff2)] = '\0'; ok(lstrcmpA(buff2, buff) == 0, "expected (%s) got (%s) for date part\n", @@ -1804,10 +1802,10 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_SHORTTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE | LOCALE_USE_CP_ACP, st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); strcat(buff2, " "); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS | LOCALE_USE_CP_ACP, &st, NULL, buff3, sizeof(buff3)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS | LOCALE_USE_CP_ACP, st, NULL, buff3, sizeof(buff3)); ok(ret == lstrlenA(buff3)+1, "got %d\n", ret); strcat(buff2, buff3); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff); @@ -1815,10 +1813,10 @@ static void test_SHFormatDateTimeA(void) flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGTIME; ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); ok(ret == lstrlenA(buff)+1, "got %d\n", ret); - ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE | LOCALE_USE_CP_ACP, &st, NULL, buff2, sizeof(buff2)); + ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE | LOCALE_USE_CP_ACP, st, NULL, buff2, sizeof(buff2)); ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); strcat(buff2, " "); - ret = GetTimeFormatA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, &st, NULL, buff3, sizeof(buff3)); + ret = GetTimeFormatA(LOCALE_USER_DEFAULT, LOCALE_USE_CP_ACP, st, NULL, buff3, sizeof(buff3)); ok(ret == lstrlenA(buff3)+1, "got %d\n", ret); strcat(buff2, buff3); ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff); @@ -3109,6 +3107,8 @@ static void test_DllGetVersion(void)
START_TEST(ordinal) { + SYSTEMTIME st; + static const SYSTEMTIME february = {2023, 2, 2, 14, 12, 0, 0, 0}; char **argv; int argc;
@@ -3136,7 +3136,15 @@ START_TEST(ordinal) test_IConnectionPoint(); test_SHPropertyBag_ReadLONG(); test_SHSetWindowBits(); - test_SHFormatDateTimeA(); + + GetLocalTime(&st); + test_SHFormatDateTimeA(&st); + /* Test how the locale and code page interact for date formatting by + * repeating the tests with a February date which in French contains an + * e-acute that can only be represented in some code pages. + */ + test_SHFormatDateTimeA(&february); + test_SHFormatDateTimeW(); test_SHGetObjectCompatFlags(); test_IUnknown_QueryServiceExec();