OSDN Git Service

invoke yamy{64,32} and yamyd32 from same directory of yamy.exe instead of current...
[yamy/yamy.git] / s / installer.cpp
1 ///////////////////////////////////////////////////////////////////////////////\r
2 // setup.cpp\r
3 \r
4 \r
5 #include "../misc.h"\r
6 #include "../registry.h"\r
7 #include "../stringtool.h"\r
8 #include "../windowstool.h"\r
9 #include "installer.h"\r
10 \r
11 #include <shlobj.h>\r
12 #include <sys/types.h>\r
13 #include <sys/stat.h>\r
14 \r
15 \r
16 namespace Installer\r
17 {\r
18 using namespace std;\r
19 \r
20 \r
21 /////////////////////////////////////////////////////////////////////////////\r
22 // Utility Functions\r
23 \r
24 /** createLink\r
25         uses the shell's IShellLink and IPersistFile interfaces to\r
26         create and store a shortcut to the specified object.\r
27     @return\r
28         the result of calling the member functions of the interfaces.\r
29     @param i_pathObj\r
30         address of a buffer containing the path of the object.\r
31     @param i_pathLink\r
32                 address of a buffer containing the path where the\r
33         shell link is to be stored.\r
34     @param i_desc\r
35         address of a buffer containing the description of the\r
36         shell link.\r
37 */\r
38 HRESULT createLink(LPCTSTR i_pathObj, LPCTSTR i_pathLink, LPCTSTR i_desc,\r
39                                    LPCTSTR i_workingDirectory)\r
40 {\r
41         // Get a pointer to the IShellLink interface.\r
42         IShellLink* psl;\r
43         HRESULT hres =\r
44                 CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,\r
45                                                  IID_IShellLink, (void **)&psl);\r
46         if (SUCCEEDED(hres)) {\r
47                 // Set the path to the shortcut target and add the description.\r
48                 psl->SetPath(i_pathObj);\r
49                 psl->SetDescription(i_desc);\r
50                 if (i_workingDirectory)\r
51                         psl->SetWorkingDirectory(i_workingDirectory);\r
52 \r
53                 // Query IShellLink for the IPersistFile interface for saving the\r
54                 // shortcut in persistent storage.\r
55                 IPersistFile* ppf;\r
56                 hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);\r
57 \r
58                 if (SUCCEEDED(hres)) {\r
59 #ifdef UNICODE\r
60                         // Save the link by calling IPersistFile::Save.\r
61                         hres = ppf->Save(i_pathLink, TRUE);\r
62 #else\r
63                         wchar_t wsz[MAX_PATH];\r
64                         // Ensure that the string is ANSI.\r
65                         MultiByteToWideChar(CP_ACP, 0, i_pathLink, -1, wsz, MAX_PATH);\r
66                         // Save the link by calling IPersistFile::Save.\r
67                         hres = ppf->Save(wsz, TRUE);\r
68 #endif\r
69                         ppf->Release();\r
70                 }\r
71                 psl->Release();\r
72         }\r
73         return hres;\r
74 }\r
75 \r
76 \r
77 // create file extension information\r
78 void createFileExtension(const tstringi &i_ext, const tstring &i_contentType,\r
79                                                  const tstringi &i_fileType,\r
80                                                  const tstring &i_fileTypeName,\r
81                                                  const tstringi &i_iconPath,\r
82                                                  const tstring &i_command)\r
83 {\r
84         tstring dummy;\r
85 \r
86         Registry regExt(HKEY_CLASSES_ROOT, i_ext);\r
87         if (!         regExt.read (_T(""), &dummy))\r
88                 CHECK_TRUE( regExt.write(_T(""), i_fileType) );\r
89         if (!         regExt.read (_T("Content Type"), &dummy))\r
90                 CHECK_TRUE( regExt.write(_T("Content Type"), i_contentType) );\r
91 \r
92         Registry      regFileType(HKEY_CLASSES_ROOT, i_fileType);\r
93         if (!         regFileType.read (_T(""), &dummy))\r
94                 CHECK_TRUE( regFileType.write(_T(""), i_fileTypeName) );\r
95 \r
96         Registry      regFileTypeIcon(HKEY_CLASSES_ROOT,\r
97                                                                   i_fileType + _T("\\DefaultIcon"));\r
98         if (!         regFileTypeIcon.read (_T(""), &dummy))\r
99                 CHECK_TRUE( regFileTypeIcon.write(_T(""), i_iconPath) );\r
100 \r
101         Registry      regFileTypeComand(HKEY_CLASSES_ROOT,\r
102                                                                         i_fileType + _T("\\shell\\open\\command"));\r
103         if (!         regFileTypeComand.read (_T(""), &dummy))\r
104                 CHECK_TRUE( regFileTypeComand.write(_T(""), i_command) );\r
105 }\r
106 \r
107 \r
108 // remove file extension information\r
109 void removeFileExtension(const tstringi &i_ext, const tstringi &i_fileType)\r
110 {\r
111         Registry::remove(HKEY_CLASSES_ROOT, i_ext);\r
112         Registry::remove(HKEY_CLASSES_ROOT,\r
113                                          i_fileType + _T("\\shell\\open\\command"));\r
114         Registry::remove(HKEY_CLASSES_ROOT, i_fileType + _T("\\shell\\open"));\r
115         Registry::remove(HKEY_CLASSES_ROOT, i_fileType + _T("\\shell"));\r
116         Registry::remove(HKEY_CLASSES_ROOT, i_fileType);\r
117 }\r
118 \r
119 \r
120 // create uninstallation information\r
121 void createUninstallInformation(const tstringi &i_name,\r
122                                                                 const tstring &i_displayName,\r
123                                                                 const tstring &i_commandLine)\r
124 {\r
125         Registry reg(\r
126                 HKEY_LOCAL_MACHINE,\r
127                 _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\")\r
128                 + i_name);\r
129 \r
130         CHECK_TRUE( reg.write(_T("DisplayName"), i_displayName) );\r
131         CHECK_TRUE( reg.write(_T("UninstallString"), i_commandLine) );\r
132 }\r
133 \r
134 \r
135 // remove uninstallation information\r
136 void removeUninstallInformation(const tstringi &i_name)\r
137 {\r
138         Registry::\r
139         remove(HKEY_LOCAL_MACHINE,\r
140                    _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\")\r
141                    + i_name);\r
142 }\r
143 \r
144 \r
145 // normalize path\r
146 tstringi normalizePath(tstringi i_path)\r
147 {\r
148         tregex regSlash(_T("^(.*)/(.*)$"));\r
149         tsmatch what;\r
150         while (boost::regex_search(i_path, what, regSlash))\r
151                 i_path = what.str(1) + _T("\\") + what.str(2);\r
152 \r
153         tregex regTailBackSlash(_T("^(.*)\\\\$"));\r
154         while (boost::regex_search(i_path, what, regTailBackSlash))\r
155                 i_path = what.str(1);\r
156 \r
157         return i_path;\r
158 }\r
159 \r
160 \r
161 // create deep directory\r
162 bool createDirectories(const _TCHAR *i_folder)\r
163 {\r
164         const _TCHAR *s = _tcschr(i_folder, _T('\\')); // TODO: '/'\r
165         if (s && s - i_folder == 2 && i_folder[1] == _T(':'))\r
166                 s = _tcschr(s + 1, _T('\\'));\r
167 \r
168         struct _stat sbuf;\r
169         while (s) {\r
170                 tstringi f(i_folder, 0, s - i_folder);\r
171                 if (_tstat(f.c_str(), &sbuf) < 0)\r
172                         if (!CreateDirectory(f.c_str(), NULL))\r
173                                 return false;\r
174                 s = _tcschr(s + 1, _T('\\'));\r
175         }\r
176         if (_tstat(i_folder, &sbuf) < 0)\r
177                 if (!CreateDirectory(i_folder, NULL))\r
178                         return false;\r
179         return true;\r
180 }\r
181 \r
182 \r
183 // get driver directory\r
184 tstringi getDriverDirectory()\r
185 {\r
186         _TCHAR buf[GANA_MAX_PATH];\r
187         CHECK_TRUE( GetSystemDirectory(buf, NUMBER_OF(buf)) );\r
188         return tstringi(buf) + _T("\\drivers");\r
189 }\r
190 \r
191 \r
192 // get current directory\r
193 tstringi getModuleDirectory()\r
194 {\r
195         _TCHAR buf[GANA_MAX_PATH];\r
196         CHECK_TRUE( GetModuleFileName(g_hInst, buf, NUMBER_OF(buf)) );\r
197         tregex reg(_T("^(.*)\\\\[^\\\\]*$"));\r
198         tsmatch what;\r
199         tstringi path(buf);\r
200         if (boost::regex_search(path, what, reg))\r
201                 return what.str(1);\r
202         else\r
203                 return path;\r
204 }\r
205 \r
206 \r
207 // get start menu name\r
208 tstringi getStartMenuName(const tstringi &i_shortcutName)\r
209 {\r
210 #if 0\r
211         char programDir[GANA_MAX_PATH];\r
212         if (SUCCEEDED(SHGetSpecialFolderPath(NULL, programDir,\r
213                                                                                  CSIDL_COMMON_PROGRAMS, FALSE)))\r
214                 return tstringi(programDir) + "\\" + shortcutName + ".lnk";\r
215 #else\r
216         tstringi programDir;\r
217         if (Registry::read(HKEY_LOCAL_MACHINE,\r
218                                            _T("Software\\Microsoft\\Windows\\CurrentVersion\\")\r
219                                            _T("Explorer\\Shell Folders"), _T("Common Programs"),\r
220                                            &programDir))\r
221                 return programDir + _T("\\") + i_shortcutName + _T(".lnk");\r
222 #endif\r
223         return _T("");\r
224 }\r
225 \r
226 \r
227 // get start up name\r
228 tstringi getStartUpName(const tstringi &i_shortcutName)\r
229 {\r
230         tstringi startupDir;\r
231         if (Registry::read(HKEY_CURRENT_USER,\r
232                                            _T("Software\\Microsoft\\Windows\\CurrentVersion\\")\r
233                                            _T("Explorer\\Shell Folders"), _T("Startup"),\r
234                                            &startupDir))\r
235                 return startupDir + _T("\\") + i_shortcutName + _T(".lnk");\r
236         return _T("");\r
237 }\r
238 \r
239 \r
240 #if defined(_WINNT)\r
241 \r
242 #  define MAYUD_FILTER_KEY _T("System\\CurrentControlSet\\Control\\Class\\{4D36E96B-E325-11CE-BFC1-08002BE10318}")\r
243 \r
244 // create driver service\r
245 DWORD createDriverService(const tstringi &i_serviceName,\r
246                                                   const tstring &i_serviceDescription,\r
247                                                   const tstringi &i_driverPath,\r
248                                                   const _TCHAR *i_preloadedGroups,\r
249                                                   bool forUsb)\r
250 {\r
251         SC_HANDLE hscm =\r
252                 OpenSCManager(NULL, NULL,\r
253                                           SC_MANAGER_CREATE_SERVICE | SC_MANAGER_CONNECT);\r
254         if (!hscm)\r
255                 return false;\r
256 \r
257         SC_HANDLE hs =\r
258                 CreateService(hscm, i_serviceName.c_str(), i_serviceDescription.c_str(),\r
259                                           SERVICE_START | SERVICE_STOP, SERVICE_KERNEL_DRIVER,\r
260                                           forUsb == true ? SERVICE_DEMAND_START : SERVICE_AUTO_START,\r
261                                           SERVICE_ERROR_IGNORE,\r
262                                           i_driverPath.c_str(), NULL, NULL,\r
263                                           i_preloadedGroups, NULL, NULL);\r
264         DWORD err = GetLastError();\r
265         if (hs == NULL) {\r
266                 switch (err) {\r
267                 case ERROR_SERVICE_EXISTS: {\r
268 #if 0\r
269                         hs = OpenService(hscm, i_serviceName.c_str(), SERVICE_CHANGE_CONFIG);\r
270                         if (hs == NULL) {\r
271                                 CloseServiceHandle(hscm);\r
272                                 return GetLastError();\r
273                         }\r
274                         if (!ChangeServiceConfig(\r
275                                                 hscm, SERVICE_KERNEL_DRIVER,\r
276                                                 forUsb == true ? SERVICE_DEMAND_START : SERVICE_AUTO_START,\r
277                                                 SERVICE_ERROR_IGNORE,\r
278                                                 i_driverPath.c_str(), NULL, NULL,\r
279                                                 i_preloadedGroups, NULL, NULL,\r
280                                                 i_serviceDescription.c_str())) {\r
281                                 CloseServiceHandle(hs);\r
282                                 CloseServiceHandle(hscm);\r
283                                 return GetLastError();          // ERROR_IO_PENDING!\r
284                                 // this code always reaches here. why?\r
285                         }\r
286 #else\r
287                         Registry reg(HKEY_LOCAL_MACHINE,\r
288                                                  _T("SYSTEM\\CurrentControlSet\\Services\\mayud"));\r
289                         reg.write(_T("Start"),\r
290                                           forUsb ? SERVICE_DEMAND_START : SERVICE_AUTO_START);\r
291 #endif\r
292                         break;\r
293                 }\r
294                 default: {\r
295                         CloseServiceHandle(hscm);\r
296                         return err;\r
297                 }\r
298                 }\r
299         }\r
300         CloseServiceHandle(hs);\r
301         CloseServiceHandle(hscm);\r
302 \r
303         if (forUsb == true) {\r
304                 Registry reg(HKEY_LOCAL_MACHINE, MAYUD_FILTER_KEY);\r
305                 typedef std::list<tstring> Filters;\r
306                 Filters filters;\r
307                 if (!reg.read(_T("UpperFilters"), &filters))\r
308                         return false;\r
309                 for (Filters::iterator i = filters.begin(); i != filters.end(); ) {\r
310                         Filters::iterator next = i;\r
311                         ++ next;\r
312                         if (*i == _T("mayud")) {\r
313                                 filters.erase(i);\r
314                         }\r
315                         i = next;\r
316                 }\r
317                 filters.push_back(_T("mayud"));\r
318                 if (!reg.write(_T("UpperFilters"), filters))\r
319                         return false;\r
320         }\r
321 \r
322         return ERROR_SUCCESS;\r
323 }\r
324 #endif // _WINNT\r
325 \r
326 \r
327 #if defined(_WINNT)\r
328 // remove driver service\r
329 DWORD removeDriverService(const tstringi &i_serviceName)\r
330 {\r
331         DWORD err = ERROR_SUCCESS;\r
332 \r
333         Registry reg(HKEY_LOCAL_MACHINE, MAYUD_FILTER_KEY);\r
334         std::list<tstring> filters;\r
335         if (reg.read(_T("UpperFilters"), &filters)) {\r
336                 filters.remove(_T("mayud"));\r
337                 reg.write(_T("UpperFilters"), filters);\r
338         }\r
339 \r
340         SC_HANDLE hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);\r
341         SC_HANDLE hs =\r
342                 OpenService(hscm, i_serviceName.c_str(),\r
343                                         SERVICE_START | SERVICE_STOP | DELETE);\r
344         if (!hs) {\r
345                 err = GetLastError();\r
346                 goto error;\r
347         }\r
348 \r
349         SERVICE_STATUS ss;\r
350         ControlService(hs, SERVICE_CONTROL_STOP, &ss);\r
351 \r
352         if (!DeleteService(hs)) {\r
353                 err = GetLastError();\r
354                 goto error;\r
355         }\r
356 error:\r
357         CloseServiceHandle(hs);\r
358         CloseServiceHandle(hscm);\r
359         return err;\r
360 }\r
361 #endif // _WINNT\r
362 \r
363 \r
364 // check operating system\r
365 bool checkOs(SetupFile::OS os)\r
366 {\r
367         OSVERSIONINFO ver;\r
368         ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
369         GetVersionEx(&ver);\r
370 \r
371         switch (os) {\r
372         default:\r
373         case SetupFile::ALL:\r
374                 return true;\r
375         case SetupFile::W9x:\r
376                 return (ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&\r
377                                 4 <= ver.dwMajorVersion);\r
378         case SetupFile::NT :\r
379                 return (ver.dwPlatformId == VER_PLATFORM_WIN32_NT &&\r
380                                 4 <= ver.dwMajorVersion);\r
381         case SetupFile::NT4:\r
382                 return (ver.dwPlatformId == VER_PLATFORM_WIN32_NT &&\r
383                                 ver.dwMajorVersion == 4);\r
384         case SetupFile::W2k:                    // W2k, XP, ...\r
385                 return (ver.dwPlatformId == VER_PLATFORM_WIN32_NT &&\r
386                                 5 <= ver.dwMajorVersion);\r
387         }\r
388 }\r
389 \r
390 \r
391 // install files\r
392 bool installFiles(const SetupFile::Data *i_setupFiles,\r
393                                   size_t i_setupFilesSize, u_int32 i_flags,\r
394                                   const tstringi &i_srcDir, const tstringi &i_destDir)\r
395 {\r
396         tstringi to, from;\r
397         tstringi destDriverDir = getDriverDirectory();\r
398 \r
399         for (size_t i = 0; i < i_setupFilesSize; ++ i) {\r
400                 const SetupFile::Data &s = i_setupFiles[i];\r
401                 const tstringi &fromDir = i_srcDir;\r
402                 const tstringi &toDir =\r
403                         (s.m_destination == SetupFile::ToDriver) ? destDriverDir : i_destDir;\r
404 \r
405                 if (!s.m_from)\r
406                         continue;                               // remove only\r
407 \r
408                 if (fromDir == toDir)\r
409                         continue;                               // same directory\r
410 \r
411                 if (!checkOs(s.m_os))                   // check operating system\r
412                         continue;\r
413 \r
414                 if ((s.m_flags & i_flags) != i_flags)   // check flags\r
415                         continue;\r
416 \r
417                 // type\r
418                 switch (s.m_kind) {\r
419                 case SetupFile::Dll: {\r
420                         // rename driver\r
421                         tstringi from_ = toDir + _T("\\") + s.m_to;\r
422                         tstringi to_ = toDir + _T("\\deleted.") + s.m_to;\r
423                         DeleteFile(to_.c_str());\r
424                         MoveFile(from_.c_str(), to_.c_str());\r
425                         DeleteFile(to_.c_str());\r
426                 }\r
427                 // fall through\r
428                 default:\r
429                 case SetupFile::File: {\r
430                         from += fromDir + _T('\\') + s.m_from + _T('\0');\r
431                         to   += toDir   + _T('\\') + s.m_to   + _T('\0');\r
432                         break;\r
433                 }\r
434                 case SetupFile::Dir: {\r
435                         createDirectories((toDir + _T('\\') + s.m_to).c_str());\r
436                         break;\r
437                 }\r
438                 }\r
439         }\r
440 #if 0\r
441         {\r
442                 tstringi to_(to), from_(from);\r
443                 for (size_t i = 0; i < to_.size(); ++ i)\r
444                         if (!to_[i])\r
445                                 to_[i] = ' ';\r
446                 for (size_t i = 0; i < from_.size(); ++ i)\r
447                         if (!from_[i])\r
448                                 from_[i] = ' ';\r
449                 MessageBox(NULL, to_.c_str(), from_.c_str(), MB_OK);\r
450         }\r
451 #endif\r
452 \r
453         SHFILEOPSTRUCT fo;\r
454         ::ZeroMemory(&fo, sizeof(fo));\r
455         fo.wFunc = FO_COPY;\r
456         fo.fFlags = FOF_MULTIDESTFILES;\r
457         fo.pFrom = from.c_str();\r
458         fo.pTo   = to.c_str();\r
459         if (SHFileOperation(&fo) || fo.fAnyOperationsAborted)\r
460                 return false;\r
461         return true;\r
462 }\r
463 \r
464 \r
465 // remove files from src\r
466 bool removeSrcFiles(const SetupFile::Data *i_setupFiles,\r
467                                         size_t i_setupFilesSize, u_int32 i_flags,\r
468                                         const tstringi &i_srcDir)\r
469 {\r
470         tstringi destDriverDir = getDriverDirectory();\r
471 \r
472         for (size_t i = 0; i < i_setupFilesSize; ++ i) {\r
473                 const SetupFile::Data &s = i_setupFiles[i_setupFilesSize - i - 1];\r
474                 const tstringi &fromDir = i_srcDir;\r
475 \r
476                 if (!s.m_from)\r
477                         continue;       // remove only\r
478 \r
479                 if (!checkOs(s.m_os))   // check operating system\r
480                         continue;\r
481 \r
482                 if ((s.m_flags & i_flags) != i_flags)   // check flags\r
483                         continue;\r
484 \r
485                 // type\r
486                 switch (s.m_kind) {\r
487                 default:\r
488                 case SetupFile::Dll:\r
489                 case SetupFile::File:\r
490                         DeleteFile((fromDir + _T('\\') + s.m_from).c_str());\r
491                         break;\r
492                 case SetupFile::Dir:\r
493                         RemoveDirectory((fromDir + _T('\\') + s.m_from).c_str());\r
494                         break;\r
495                 }\r
496         }\r
497         RemoveDirectory(i_srcDir.c_str());\r
498         return true;\r
499 }\r
500 \r
501 \r
502 // remove files\r
503 void removeFiles(const SetupFile::Data *i_setupFiles,\r
504                                  size_t i_setupFilesSize, u_int32 i_flags,\r
505                                  const tstringi &i_destDir)\r
506 {\r
507         tstringi destDriverDir = getDriverDirectory();\r
508 \r
509         for (size_t i = 0; i < i_setupFilesSize; ++ i) {\r
510                 const SetupFile::Data &s = i_setupFiles[i_setupFilesSize - i - 1];\r
511                 const tstringi &toDir =\r
512                         (s.m_destination == SetupFile::ToDriver) ? destDriverDir : i_destDir;\r
513 \r
514                 if (!checkOs(s.m_os))   // check operating system\r
515                         continue;\r
516 \r
517                 if ((s.m_flags & i_flags) != i_flags)   // check flags\r
518                         continue;\r
519 \r
520                 // type\r
521                 switch (s.m_kind) {\r
522                 case SetupFile::Dll:\r
523                         DeleteFile((toDir + _T("\\deleted.") + s.m_to).c_str());\r
524                         // fall through\r
525                 default:\r
526                 case SetupFile::File:\r
527                         DeleteFile((toDir + _T('\\') + s.m_to).c_str());\r
528                         break;\r
529                 case SetupFile::Dir:\r
530                         RemoveDirectory((toDir + _T('\\') + s.m_to).c_str());\r
531                         break;\r
532                 }\r
533         }\r
534         RemoveDirectory(i_destDir.c_str());\r
535 }\r
536 \r
537 \r
538 // uninstall step1\r
539 int uninstallStep1(const _TCHAR *i_uninstallOption)\r
540 {\r
541         // copy this EXEcutable image into the user's temp directory\r
542         _TCHAR setup_exe[GANA_MAX_PATH], tmp_setup_exe[GANA_MAX_PATH];\r
543         GetModuleFileName(NULL, setup_exe, NUMBER_OF(setup_exe));\r
544         GetTempPath(NUMBER_OF(tmp_setup_exe), tmp_setup_exe);\r
545         GetTempFileName(tmp_setup_exe, _T("del"), 0, tmp_setup_exe);\r
546         CopyFile(setup_exe, tmp_setup_exe, FALSE);\r
547 \r
548         // open the clone EXE using FILE_FLAG_DELETE_ON_CLOSE\r
549         HANDLE hfile = CreateFile(tmp_setup_exe, 0, FILE_SHARE_READ, NULL,\r
550                                                           OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);\r
551 \r
552         // spawn the clone EXE passing it our EXE's process handle\r
553         // and the full path name to the original EXE file.\r
554         _TCHAR commandLine[512];\r
555         HANDLE hProcessOrig =\r
556                 OpenProcess(SYNCHRONIZE, TRUE, GetCurrentProcessId());\r
557         _sntprintf(commandLine, NUMBER_OF(commandLine), _T("%s %s %d"),\r
558                            tmp_setup_exe, i_uninstallOption, hProcessOrig);\r
559         STARTUPINFO si;\r
560         ::ZeroMemory(&si, sizeof(si));\r
561         si.cb = sizeof(si);\r
562         PROCESS_INFORMATION pi;\r
563         CreateProcess(NULL, commandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si,&pi);\r
564         Sleep(2000); // important\r
565         CloseHandle(hProcessOrig);\r
566         CloseHandle(hfile);\r
567 \r
568         return 0;\r
569 }\r
570 \r
571 // uninstall step2\r
572 // (after this function, we cannot use any resource)\r
573 void uninstallStep2(const _TCHAR *argByStep1)\r
574 {\r
575         // clone EXE: When original EXE terminates, delete it\r
576         HANDLE hProcessOrig = (HANDLE)_ttoi(argByStep1);\r
577         WaitForSingleObject(hProcessOrig, INFINITE);\r
578         CloseHandle(hProcessOrig);\r
579 }\r
580 \r
581 \r
582 /////////////////////////////////////////////////////////////////////////////\r
583 // Locale / StringResource\r
584 \r
585 \r
586 // constructor\r
587 Resource::Resource(const StringResource *i_stringResources)\r
588                 : m_stringResources(i_stringResources),\r
589                 m_locale(LOCALE_C)\r
590 {\r
591         struct LocaleInformaton {\r
592                 const _TCHAR *m_localeString;\r
593                 Locale m_locale;\r
594         };\r
595 \r
596         // set locale information\r
597         const _TCHAR *localeString = ::_tsetlocale(LC_ALL, _T(""));\r
598 \r
599         static const LocaleInformaton locales[] = {\r
600                 { _T("Japanese_Japan.932"), LOCALE_Japanese_Japan_932 },\r
601         };\r
602 \r
603         for (size_t i = 0; i < NUMBER_OF(locales); ++ i)\r
604                 if (_tcsicmp(localeString, locales[i].m_localeString) == 0) {\r
605                         m_locale = locales[i].m_locale;\r
606                         break;\r
607                 }\r
608 }\r
609 \r
610 \r
611 // get resource string\r
612 const _TCHAR *Resource::loadString(UINT i_id)\r
613 {\r
614         int n = static_cast<int>(m_locale);\r
615         int index = -1;\r
616         for (int i = 0; m_stringResources[i].m_str; ++ i)\r
617                 if (m_stringResources[i].m_id == i_id) {\r
618                         if (n == 0)\r
619                                 return m_stringResources[i].m_str;\r
620                         index = i;\r
621                         n --;\r
622                 }\r
623         if (0 <= index)\r
624                 return m_stringResources[index].m_str;\r
625         else\r
626                 return _T("");\r
627 }\r
628 }\r