summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/unix/CPP/myWindows/test_emul.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/7zip/unix/CPP/myWindows/test_emul.cpp')
-rw-r--r--src/libs/7zip/unix/CPP/myWindows/test_emul.cpp745
1 files changed, 745 insertions, 0 deletions
diff --git a/src/libs/7zip/unix/CPP/myWindows/test_emul.cpp b/src/libs/7zip/unix/CPP/myWindows/test_emul.cpp
new file mode 100644
index 000000000..1c8d3261d
--- /dev/null
+++ b/src/libs/7zip/unix/CPP/myWindows/test_emul.cpp
@@ -0,0 +1,745 @@
+#undef BIG_ENDIAN
+#undef LITTLE_ENDIAN
+
+#include "StdAfx.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#ifdef __APPLE_CC__
+#define UInt32 macUIn32
+#include <CoreFoundation/CoreFoundation.h>
+#undef UInt32
+#endif
+
+#ifdef ENV_HAVE_WCHAR__H
+#include <wchar.h>
+#endif
+#ifdef ENV_HAVE_LOCALE
+#include <locale.h>
+#endif
+
+#include <windows.h>
+
+#define NEED_NAME_WINDOWS_TO_UNIX
+// #include "myPrivate.h"
+
+#include "Common/StringConvert.h"
+#include "Common/StdOutStream.h"
+
+#undef NDEBUG
+#include <assert.h>
+
+#include "Common/StringConvert.cpp"
+#include "Common/StdOutStream.cpp"
+#include "Common/IntToString.cpp"
+
+#include "Windows/Synchronization.cpp"
+#include "Windows/FileFind.cpp"
+#include "Windows/Time.cpp"
+#include "../C/Threads.c"
+#include "../../C/Ppmd.h"
+
+using namespace NWindows;
+
+#if defined(ENV_HAVE_WCHAR__H) && defined(ENV_HAVE_MBSTOWCS) && defined(ENV_HAVE_WCSTOMBS)
+void test_mbs(void) {
+ wchar_t wstr1[256] = {
+ L'e',
+ 0xE8, // latin small letter e with grave
+ 0xE9, // latin small letter e with acute
+ L'a',
+ 0xE0, // latin small letter a with grave
+ 0x20AC, // euro sign
+ L'b',
+ 0 };
+ wchar_t wstr2[256];
+ char astr[256];
+
+ global_use_utf16_conversion = 1;
+
+ size_t len1 = wcslen(wstr1);
+
+ printf("wstr1 - %d - '%ls'\n",(int)len1,wstr1);
+
+ size_t len0 = wcstombs(astr,wstr1,sizeof(astr));
+ printf("astr - %d - '%s'\n",(int)len0,astr);
+
+ size_t len2 = mbstowcs(wstr2,astr,sizeof(wstr2)/sizeof(*wstr2));
+ printf("wstr - %d - '%ls'\n",(int)len2,wstr2);
+
+ if (wcscmp(wstr1,wstr2) != 0) {
+ printf("ERROR during conversions wcs -> mbs -> wcs\n");
+ exit(EXIT_FAILURE);
+ }
+
+ char *ptr = astr;
+ size_t len = 0;
+ while (*ptr) {
+ ptr = CharNextA(ptr);
+ len += 1;
+ }
+ if ((len != len1) && (len != 12)) { // 12 = when locale is UTF8 instead of ISO8859-15
+ printf("ERROR CharNextA : len=%d, len1=%d\n",(int)len,(int)len1);
+ exit(EXIT_FAILURE);
+ }
+
+ UString ustr(wstr1);
+ assert(ustr.Length() == (int)len1);
+
+ AString ansistr(astr);
+ assert(ansistr.Length() == (int)len0);
+
+ ansistr = UnicodeStringToMultiByte(ustr);
+ assert(ansistr.Length() == (int)len0);
+
+ assert(strcmp(ansistr,astr) == 0);
+ assert(wcscmp(ustr,wstr1) == 0);
+
+ UString ustr2 = MultiByteToUnicodeString(astr);
+ assert(ustr2.Length() == (int)len1);
+ assert(wcscmp(ustr2,wstr1) == 0);
+}
+#endif
+
+static void test_astring(int num) {
+ AString strResult;
+
+ strResult = "first part : ";
+ char number[256];
+ sprintf(number,"%d",num);
+ strResult += AString(number);
+
+ strResult += " : last part";
+
+ printf("strResult -%s-\n",(const char *)strResult);
+
+}
+
+
+extern void my_windows_split_path(const AString &p_path, AString &dir , AString &base);
+
+static struct {
+ const char *path;
+ const char *dir;
+ const char *base;
+}
+tabSplit[]=
+ {
+ { "",".","." },
+ { "/","/","/" },
+ { ".",".","." },
+ { "//","/","/" },
+ { "///","/","/" },
+ { "dir",".","dir" },
+ { "/dir","/","dir" },
+ { "/dir/","/","dir" },
+ { "/dir/base","/dir","base" },
+ { "/dir//base","/dir","base" },
+ { "/dir///base","/dir","base" },
+ { "//dir/base","//dir","base" },
+ { "///dir/base","///dir","base" },
+ { "/dir/base/","/dir","base" },
+ { 0,0,0 }
+ };
+
+static void test_split_astring() {
+ int ind = 0;
+ while (tabSplit[ind].path) {
+ AString path(tabSplit[ind].path);
+ AString dir;
+ AString base;
+
+ my_windows_split_path(path,dir,base);
+
+ if ((dir != tabSplit[ind].dir) || (base != tabSplit[ind].base)) {
+ printf("ERROR : '%s' '%s' '%s'\n",(const char *)path,(const char *)dir,(const char *)base);
+ }
+ ind++;
+ }
+ printf("test_split_astring : done\n");
+}
+
+ // Number of 100 nanosecond units from 1/1/1601 to 1/1/1970
+#define EPOCH_BIAS 116444736000000000LL
+static LARGE_INTEGER UnixTimeToUL(time_t tps_unx)
+{
+ LARGE_INTEGER ul;
+ ul.QuadPart = tps_unx * 10000000LL + EPOCH_BIAS;
+ return ul;
+}
+
+static LARGE_INTEGER FileTimeToUL(FILETIME fileTime)
+{
+ LARGE_INTEGER lFileTime;
+ lFileTime.QuadPart = fileTime.dwHighDateTime;
+ lFileTime.QuadPart = (lFileTime.QuadPart << 32) | fileTime.dwLowDateTime;
+ return lFileTime;
+}
+
+static void display(const char *txt,SYSTEMTIME systime)
+{
+ FILETIME fileTime;
+ BOOL ret = SystemTimeToFileTime(&systime,&fileTime);
+ assert(ret == TRUE);
+ LARGE_INTEGER ulFileTime = FileTimeToUL(fileTime);
+
+ const char * day="";
+ switch (systime.wDayOfWeek)
+ {
+ case 0:day = "Sunday";break;
+ case 1:day = "Monday";break;
+ case 2:day = "Tuesday";break;
+ case 3:day = "Wednesday";break;
+ case 4:day = "Thursday";break;
+ case 5:day = "Friday";break;
+ case 6:day = "Saturday";break;
+ }
+ g_StdOut<< txt << day << " "
+ << (int)systime.wYear << "/" << (int)systime.wMonth << "/" << (int)systime.wDay << " "
+ << (int)systime.wHour << ":" << (int)systime.wMinute << ":" << (int)systime.wSecond << ":"
+ << (int)systime.wMilliseconds
+ << " (" << (UInt64)ulFileTime.QuadPart << ")\n";
+}
+
+static void test_time()
+{
+ time_t tps_unx = time(0);
+
+ printf("Test Time (1):\n");
+ printf("===========\n");
+ SYSTEMTIME systimeGM;
+ GetSystemTime(&systimeGM);
+
+ LARGE_INTEGER ul = UnixTimeToUL(tps_unx);
+ g_StdOut<<" unix time = " << (UInt64)tps_unx << " (" << (UInt64)ul.QuadPart << ")\n";
+
+ g_StdOut<<" gmtime : " << asctime(gmtime(&tps_unx))<<"\n";
+ g_StdOut<<" localtime : " << asctime(localtime(&tps_unx))<<"\n";
+
+ display(" GetSystemTime : ", systimeGM);
+}
+
+static void test_time2()
+{
+ UInt32 dosTime = 0x30d0094C;
+ FILETIME utcFileTime;
+ FILETIME localFileTime;
+ FILETIME localFileTime2;
+ UInt32 dosTime2 = 0;
+
+ printf("Test Time (2):\n");
+ printf("===========\n");
+ NTime::DosTimeToFileTime(dosTime, localFileTime);
+ NTime::FileTimeToDosTime(localFileTime, dosTime2);
+ assert(dosTime == dosTime2);
+
+ printf("Test Time (3):\n");
+ printf("===========\n");
+ /* DosTime To utcFileTime */
+
+ if (NTime::DosTimeToFileTime(dosTime, localFileTime)) /* DosDateTimeToFileTime */
+ {
+ if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ }
+
+ printf(" - 0x%x => 0x%x 0x%x => 0x%x 0x%x\n",(unsigned)dosTime,
+ (unsigned)localFileTime.dwHighDateTime,(unsigned)localFileTime.dwLowDateTime,
+ (unsigned)utcFileTime.dwHighDateTime,(unsigned)utcFileTime.dwLowDateTime);
+
+
+ /* utcFileTime to DosTime */
+
+ FileTimeToLocalFileTime(&utcFileTime, &localFileTime2);
+ NTime::FileTimeToDosTime(localFileTime2, dosTime2); /* FileTimeToDosDateTime */
+
+ printf(" - 0x%x <= 0x%x 0x%x <= 0x%x 0x%x\n",(unsigned)dosTime2,
+ (unsigned)localFileTime2.dwHighDateTime,(unsigned)localFileTime2.dwLowDateTime,
+ (unsigned)utcFileTime.dwHighDateTime,(unsigned)utcFileTime.dwLowDateTime);
+
+ assert(dosTime == dosTime2);
+ assert(localFileTime.dwHighDateTime == localFileTime2.dwHighDateTime);
+ assert(localFileTime.dwLowDateTime == localFileTime2.dwLowDateTime);
+}
+
+static void test_semaphore()
+{
+ g_StdOut << "\nTEST SEMAPHORE :\n";
+
+ NWindows::NSynchronization::CSynchro sync;
+ NWindows::NSynchronization::CSemaphoreWFMO sema;
+ bool bres;
+ DWORD waitResult;
+ int i;
+
+ sync.Create();
+ sema.Create(&sync,2,10);
+
+ g_StdOut << " - Release(1)\n";
+ for(i = 0 ;i < 8;i++)
+ {
+ // g_StdOut << " - Release(1) : "<< i << "\n";
+ bres = sema.Release(1);
+ assert(bres == S_OK);
+ }
+ // g_StdOut << " - Release(1) : done\n";
+ bres = sema.Release(1);
+ assert(bres == S_FALSE);
+
+ g_StdOut << " - WaitForMultipleObjects(INFINITE)\n";
+ HANDLE events[1] = { sema };
+ for(i=0;i<10;i++)
+ {
+ waitResult = ::WaitForMultipleObjects(1, events, FALSE, INFINITE);
+ assert(waitResult == WAIT_OBJECT_0);
+ }
+
+ g_StdOut << " Done\n";
+}
+
+
+/****************************************************************************************/
+
+
+static int threads_count = 0;
+
+static THREAD_FUNC_RET_TYPE thread_fct(void * /* param */ ) {
+ threads_count++;
+ return 0;
+}
+
+#define MAX_THREADS 100000
+
+int test_thread(void) {
+ ::CThread thread;
+
+ Thread_Construct(&thread);
+
+ threads_count = 0;
+
+ printf("test_thread : %d threads\n",MAX_THREADS);
+
+ for(int i=0;i<MAX_THREADS;i++) {
+ Thread_Create(&thread, thread_fct, 0);
+
+ Thread_Wait(&thread);
+
+ Thread_Close(&thread);
+ }
+
+ assert(threads_count == MAX_THREADS);
+
+ return 0;
+}
+
+
+void dumpStr(const char *title,const char *txt)
+{
+ size_t i,len = strlen(txt);
+
+ printf("%s - %d :",title,(int)len);
+
+ for(i = 0 ; i<len;i++) {
+ printf(" 0x%02x",(unsigned)(txt[i] & 255));
+ }
+
+ printf("\n");
+}
+
+
+void dumpWStr(const char *title,const wchar_t *txt)
+{
+ size_t i,len = wcslen(txt);
+
+ printf("%s - %d :",title,(int)len);
+
+ for(i = 0 ; i<len;i++) {
+ printf(" 0x%02x",(unsigned)(txt[i]));
+ }
+
+ printf("\n");
+}
+
+#ifdef __APPLE_CC__
+
+void testMaxOSX_stringConvert()
+{
+/*
+ 0xE8, // latin small letter e with grave
+ 0xE9, // latin small letter e with acute
+ L'a',
+ 0xE0, // latin small letter a with grave
+ 0x20AC, // euro sign
+*/
+ struct
+ {
+ char astr [256];
+ wchar_t ustr [256];
+ }
+ tab [] =
+ {
+ {
+ // 'a' , 'e with acute' , 'e with grave' , 'a with grave' , 'u with grave' , 'b' , '.' , 't' , 'x' , 't'
+ { 0x61, 0x65, 0xcc, 0x81 , 0x65, 0xcc, 0x80, 0x61, 0xcc, 0x80, 0x75, 0xcc, 0x80, 0x62, 0x2e, 0x74, 0x78, 0x74, 0 },
+ { 0x61, 0xe9, 0xe8, 0xe0, 0xf9, 0x62, 0x2e, 0x74, 0x78, 0x74, 0 }
+ },
+ {
+ // 'a' , 'euro sign' , 'b' , '.' , 't' , 'x' , 't' , '\n'
+ { 0x61, 0xe2, 0x82, 0xac, 0x62, 0x2e, 0x74, 0x78, 0x74, 0x0a, 0 },
+ { 0x61, 0x20AC, 0x62, 0x2e, 0x74, 0x78, 0x74, 0x0a, 0 }
+ },
+ {
+ { 0 },
+ { 0 }
+ }
+ };
+
+ int i;
+
+ printf("testMaxOSX_stringConvert : \n");
+
+ i = 0;
+ while (tab[i].astr[0])
+ {
+ printf(" %s\n",tab[i].astr);
+
+ UString ustr = GetUnicodeString(tab[i].astr);
+
+ // dumpWStr("1",&ustr[0]);
+
+ assert(MyStringCompare(&ustr[0],tab[i].ustr) == 0);
+ assert(ustr.Length() == wcslen(tab[i].ustr) );
+
+
+ AString astr = GetAnsiString(ustr);
+ assert(MyStringCompare(&astr[0],tab[i].astr) == 0);
+ assert(astr.Length() == strlen(tab[i].astr) );
+
+ i++;
+ }
+}
+
+void testMacOSX()
+{
+// char texte1[]= { 0xc3 , 0xa9 , 0xc3, 0xa0, 0};
+
+ wchar_t wpath1[4096] = {
+ 0xE9, // latin small letter e with acute
+ 0xE0,
+ 0xc7,
+ 0x25cc,
+ 0x327,
+ 0xe4,
+ 0xe2,
+ 0xc2,
+ 0xc3,
+ 0x2e,
+ 0x74,
+ 0x78,
+ 0x74,
+/*
+ L'e',
+ 0xE8, // latin small letter e with grave
+ 0xE9, // latin small letter e with acute
+ L'a',
+ 0xE0, // latin small letter a with grave
+ 0x20AC, // euro sign
+ L'b',
+*/
+ 0 };
+
+ char utf8[4096];
+ wchar_t wpath2[4096];
+
+
+
+ // dumpStr("UTF8 standart",texte1);
+
+ dumpWStr("UCS32 standard",wpath1);
+
+// Translate into FS pathname
+ {
+ const wchar_t * wcs = wpath1;
+
+ UniChar unipath[4096];
+
+ long n = wcslen(wcs);
+
+ for(long i = 0 ; i<= n ;i++) {
+ unipath[i] = wcs[i];
+ }
+
+ CFStringRef cfpath = CFStringCreateWithCharacters(NULL,unipath,n);
+
+ CFMutableStringRef cfpath2 = CFStringCreateMutableCopy(NULL,0,cfpath);
+ CFRelease(cfpath);
+ CFStringNormalize(cfpath2,kCFStringNormalizationFormD);
+
+ CFStringGetCString(cfpath2,(char *)utf8,4096,kCFStringEncodingUTF8);
+
+ CFRelease(cfpath2);
+ }
+
+ dumpStr("UTF8 MacOSX",utf8);
+
+// Translate from FS pathname
+ {
+ const char * path = utf8;
+
+ long n = strlen(path);
+
+ CFStringRef cfpath = CFStringCreateWithCString(NULL,path,kCFStringEncodingUTF8);
+
+ if (cfpath)
+ {
+
+ CFMutableStringRef cfpath2 = CFStringCreateMutableCopy(NULL,0,cfpath);
+ CFRelease(cfpath);
+ CFStringNormalize(cfpath2,kCFStringNormalizationFormC);
+
+ n = CFStringGetLength(cfpath2);
+ for(long i = 0 ; i<= n ;i++) {
+ wpath2[i] = CFStringGetCharacterAtIndex(cfpath2,i);
+ }
+ wpath2[n] = 0;
+
+ CFRelease(cfpath2);
+ }
+ else
+ {
+ wpath2[0] = 0;
+ }
+ }
+
+ dumpWStr("UCS32 standard (2)",wpath2);
+
+/*
+ {
+ CFStringRef cfpath;
+
+ cfpath = CFStringCreateWithCString(kCFAllocatorDefault, texte1, kCFStringEncodingUTF8);
+
+ // TODO str = null ?
+
+ CFMutableStringRef cfpath2 = CFStringCreateMutableCopy(NULL,0,cfpaht);
+ CFRealease(cfpath);
+
+
+
+
+ }
+*/
+
+
+}
+#endif // __APPLE_CC__
+
+
+static const TCHAR *kMainDll = TEXT("7z.dll");
+
+static CSysString ConvertUInt32ToString(UInt32 value)
+{
+ TCHAR buffer[32];
+ ConvertUInt32ToString(value, buffer);
+ return buffer;
+}
+
+
+void test_csystring(void)
+{
+ {
+ const CSysString baseFolder = TEXT("bin/");
+ const CSysString b2 = baseFolder + kMainDll;
+
+ assert(MyStringCompare(&b2[0],TEXT("bin/7z.dll")) == 0);
+ }
+
+ {
+ LPCTSTR dirPath=TEXT("/tmp/");
+ LPCTSTR prefix=TEXT("foo");
+ CSysString resultPath;
+
+ UINT number = 12345;
+ UInt32 count = 6789;
+
+/*
+ TCHAR * buf = resultPath.GetBuffer(MAX_PATH);
+ ::swprintf(buf,MAX_PATH,L"%ls%ls#%d@%d.tmp",dirPath,prefix,(unsigned)number,count);
+ buf[MAX_PATH-1]=0;
+ resultPath.ReleaseBuffer();
+*/
+ resultPath = dirPath;
+ resultPath += prefix;
+ resultPath += TEXT('#');
+ resultPath += ConvertUInt32ToString(number);
+ resultPath += TEXT('@');
+ resultPath += ConvertUInt32ToString(count);
+ resultPath += TEXT(".tmp");
+
+ // printf("##%ls##\n",&resultPath[0]);
+
+ assert(MyStringCompare(&resultPath[0],TEXT("/tmp/foo#12345@6789.tmp")) == 0);
+ }
+
+}
+
+static void test_AString()
+{
+ AString a;
+
+ a = "abc";
+ assert(MyStringCompare(&a[0],"abc") == 0);
+ assert(a.Length() == 3);
+
+ a = GetAnsiString(L"abc");
+ assert(MyStringCompare(&a[0],"abc") == 0);
+ assert(a.Length() == 3);
+}
+
+
+const TCHAR kAnyStringWildcard = '*';
+
+static void test_UString2(const UString &phyPrefix)
+{
+ UString tmp = phyPrefix + wchar_t(kAnyStringWildcard);
+ printf("Enum(%ls-%ls-%lc)\n",&tmp[0],&phyPrefix[0],wchar_t(kAnyStringWildcard));
+}
+
+
+
+static void test_UString()
+{
+ UString us = L"7za433_tar";
+
+ test_UString2(L"7za433_tar");
+
+ UString u1(us);
+ test_UString2(u1);
+ u1 = L"";
+ test_UString2(u1);
+ u1 = us;
+ test_UString2(u1);
+
+ UString u2 = us;
+ test_UString2(u2);
+ u2 = L"";
+ test_UString2(u2);
+ u2 = u1;
+ test_UString2(u2);
+
+ u1 = L"abc";
+ assert(MyStringCompare(&u1[0],L"abc") == 0);
+ assert(u1.Length() == 3);
+
+ u1 = GetUnicodeString("abc");
+ assert(MyStringCompare(&u1[0],L"abc") == 0);
+ assert(u1.Length() == 3);
+}
+
+/****************************************************************************************/
+int main() {
+
+ // return test_thread();
+
+
+#ifdef ENV_HAVE_LOCALE
+ setlocale(LC_ALL,"");
+#endif
+
+#if defined(BIG_ENDIAN)
+ printf("BIG_ENDIAN : %d\n",(int)BIG_ENDIAN);
+#endif
+#if defined(LITTLE_ENDIAN)
+ printf("LITTLE_ENDIAN : %d\n",(int)LITTLE_ENDIAN);
+#endif
+
+ printf("sizeof(Byte) : %d\n",(int)sizeof(Byte));
+ printf("sizeof(UInt16) : %d\n",(int)sizeof(UInt16));
+ printf("sizeof(UInt32) : %d\n",(int)sizeof(UInt32));
+ printf("sizeof(UINT32) : %d\n",(int)sizeof(UINT32));
+ printf("sizeof(UInt64) : %d\n",(int)sizeof(UInt64));
+ printf("sizeof(UINT64) : %d\n",(int)sizeof(UINT64));
+ printf("sizeof(void *) : %d\n",(int)sizeof(void *));
+ printf("sizeof(size_t) : %d\n",(int)sizeof(size_t));
+ printf("sizeof(ptrdiff_t) : %d\n",(int)sizeof(ptrdiff_t));
+ printf("sizeof(off_t) : %d\n",(int)sizeof(off_t));
+ printf("sizeof(wchar_t) : %d\n",(int)sizeof(wchar_t));
+#ifdef __APPLE_CC__
+ printf("sizeof(UniChar) : %d\n",(int)sizeof(UniChar));
+#endif
+ printf("sizeof(CPpmd_See) : %d\n",(int)sizeof(CPpmd_See));
+ printf("sizeof(CPpmd_State) : %d\n",(int)sizeof(CPpmd_State));
+
+ // size tests
+ assert(sizeof(Byte)==1);
+ assert(sizeof(UInt16)==2);
+ assert(sizeof(UInt32)==4);
+ assert(sizeof(UINT32)==4);
+ assert(sizeof(UInt64)==8);
+ assert(sizeof(UINT64)==8);
+
+ // alignement tests
+ assert(sizeof(CPpmd_See)==4);
+ assert(sizeof(CPpmd_State)==6);
+
+ union {
+ Byte b[2];
+ UInt16 s;
+ } u;
+ u.s = 0x1234;
+
+ if ((u.b[0] == 0x12) && (u.b[1] == 0x34)) {
+ printf("CPU : big endian\n");
+ } else if ((u.b[0] == 0x34) && (u.b[1] == 0x12)) {
+ printf("CPU : little endian\n");
+ } else {
+ printf("CPU : unknown endianess\n");
+ }
+
+#if defined(ENV_HAVE_WCHAR__H) && defined(ENV_HAVE_MBSTOWCS) && defined(ENV_HAVE_WCSTOMBS)
+ test_mbs();
+#endif
+
+ test_astring(12345);
+ test_split_astring();
+
+ test_csystring();
+ test_AString();
+ test_UString();
+
+ test_time();
+
+ test_time2();
+
+ test_semaphore();
+
+#ifdef __APPLE_CC__
+ testMacOSX();
+ testMaxOSX_stringConvert();
+#endif
+
+
+{
+ LANGID langID;
+ WORD primLang;
+ WORD subLang;
+
+ langID = GetUserDefaultLangID();
+ printf("langID=0x%x\n",langID);
+
+ primLang = (WORD)(PRIMARYLANGID(langID));
+ subLang = (WORD)(SUBLANGID(langID));
+
+ printf("primLang=%d subLang=%d\n",(unsigned)primLang,(unsigned)subLang);
+}
+
+ printf("\n### All Done ###\n\n");
+
+ return 0;
+}
+