// Classic Shell (c) 2009-2017, Ivo Beltchev // Open-Shell (c) 2017-2018, The Open-Shell Team // Confidential information of Ivo Beltchev. Not for disclosure or distribution without prior written consent from the author #define STRICT_TYPED_ITEMIDS #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit #include #include #include #include #include #include "StringUtils.h" #include "FNVHash.h" #include "SettingsParser.h" #include "resource.h" #include "ResourceHelper.h" #include #include "SaveLogFile.h" // Manifest to enable the 6.0 common controls #pragma comment(linker, \ "\"/manifestdependency:type='Win32' "\ "name='Microsoft.Windows.Common-Controls' "\ "version='6.0.0.0' "\ "processorArchitecture='*' "\ "publicKeyToken='6595b64144ccf1df' "\ "language='*'\"") HINSTANCE g_hInstance; void EditLoggingOptions( void ); void ManualUninstall( void ); void ShowMetroColorViewer( void ); #ifndef _WIN64 /////////////////////////////////////////////////////////////////////////////// static void LoadFile( const wchar_t *fname, std::vector &buf ) { buf.clear(); FILE *f=NULL; if (_wfopen_s(&f,fname,L"rb") || !f) return; fseek(f,0,SEEK_END); int size=ftell(f); fseek(f,0,SEEK_SET); buf.resize(size); if (size==0 || fread(&buf[0],1,size,f)!=size) buf.clear(); fclose(f); } static unsigned int CalcFileFNV( const wchar_t *fname ) { std::vector buf; LoadFile(fname,buf); if (buf.empty()) return 0; return CalcFNVHash(&buf[0],(int)buf.size(),FNV_HASH0); } static void Printf( const char *format, ... ) { char buf[1024]; va_list args; va_start(args,format); int len=Vsprintf(buf,_countof(buf),format,args); va_end(args); DWORD q; WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),buf,len,&q,NULL); #if _DEBUG OutputDebugStringA(buf); #endif } /////////////////////////////////////////////////////////////////////////////// struct Chunk { int start1, start2, len; }; int CalcMsiChecksum( wchar_t *const *params, int count ) { if (count<2) return 2; AttachConsole(ATTACH_PARENT_PROCESS); // load files wchar_t path1[_MAX_PATH]; std::vector buf1, buf2; Sprintf(path1,_countof(path1),L"%s\\Setup32.msi",params[1]); LoadFile(path1,buf1); if (buf1.empty()) { Printf("Failed to open file %s\n",path1); return 1; } wchar_t path2[_MAX_PATH]; Sprintf(path2,_countof(path2),L"%s\\Setup64.msi",params[1]); LoadFile(path2,buf2); if (buf2.empty()) { Printf("Failed to open file %s\n",path2); return 1; } int len1=(int)buf1.size(); int len2=(int)buf2.size(); for (std::vector::iterator it=buf1.begin();it!=buf1.end();++it) *it^=0xFF; for (std::vector::iterator it=buf2.begin();it!=buf2.end();++it) *it^=0xFF; // detect common blocks (assuming at least 256K in size and in the same order in both files) const int BLOCK_SIZE=256*1024; std::vector chunks; int start2=0; for (int i=0;i0 && chunk.start2>0 && buf1[chunk.start1-1]==buf2[chunk.start2-1]) { chunk.start1--; chunk.start2--; chunk.len++; } while (chunk.start1+chunk.len::const_iterator it=chunks.begin();it!=chunks.end();++it) { if (it->start2-start>0) fwrite(&buf2[start],1,it->start2-start,f); start=it->start2+it->len; } if (len2-start>0) fwrite(&buf2[start],1,len2-start,f); fclose(f); } unsigned int fnvs[2]; fnvs[0]=CalcFNVHash(&buf1[0],len1,FNV_HASH0); fnvs[1]=CalcFNVHash(&buf2[0],len2,FNV_HASH0); // save fnvs and chunks { FILE *f=NULL; if (_wfopen_s(&f,L"msichecksum.bin",L"wb") || !f) { Printf("Failed to write msichecksum.bin\n"); return 1; } fwrite(fnvs,4,_countof(fnvs),f); int count=(int)chunks.size(); fwrite(&count,1,4,f); fwrite(&chunks[0],sizeof(Chunk),count,f); fclose(f); } return 0; } /////////////////////////////////////////////////////////////////////////////// int MakeEnglishDll( wchar_t *const *params, int count ) { if (count<5) return 2; AttachConsole(ATTACH_PARENT_PROCESS); HMODULE hEn0=LoadLibraryEx(L"en-US.dll",NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); if (!hEn0) { Printf("Failed to open en-US.dll (err: %d)\n",GetLastError()); return 1; } std::vector version; { HRSRC hResInfo=FindResource(hEn0,MAKEINTRESOURCE(VS_VERSION_INFO),RT_VERSION); if (hResInfo) { HGLOBAL hRes=LoadResource(hEn0,hResInfo); void *pRes=LockResource(hRes); if (pRes) { DWORD len=SizeofResource(hEn0,hResInfo); if (len>=40+sizeof(VS_FIXEDFILEINFO)) { version.resize(len); memcpy(&version[0],pRes,len); } } } } FreeLibrary(hEn0); if (version.empty()) { Printf("Can't find version resource in en-US.dll\n"); return 1; } HANDLE hEn=BeginUpdateResource(L"en-US.dll",FALSE); if (!hEn) { Printf("Failed to open en-US.dll (err: %d)\n",GetLastError()); return 1; } int res=1; HMODULE hExplorer=NULL, hMenu=NULL, hIE=NULL; WORD language=MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US); // get version, strings and dialog from ClassicExplorer32.dll hExplorer=LoadLibraryEx(params[1],NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); if (!hExplorer) { Printf("Failed to open %S (err: %d)\n",params[1],GetLastError()); goto qqq; } // copy version { HRSRC hResInfo=FindResource(hExplorer,MAKEINTRESOURCE(VS_VERSION_INFO),RT_VERSION); void *pRes=NULL; if (hResInfo) { HGLOBAL hRes=LoadResource(hExplorer,hResInfo); pRes=LockResource(hRes); } if (!pRes) { Printf("Can't find version resource in %S\n",params[1]); goto qqq; } VS_FIXEDFILEINFO *pVer=(VS_FIXEDFILEINFO*)((char*)pRes+40); VS_FIXEDFILEINFO *pVer0=(VS_FIXEDFILEINFO*)(&version[40]); pVer0->dwProductVersionMS=pVer->dwProductVersionMS; pVer0->dwProductVersionLS=pVer->dwProductVersionLS; pVer0->dwFileVersionMS=pVer->dwFileVersionMS; pVer0->dwFileVersionLS=pVer->dwFileVersionLS; UpdateResource(hEn,RT_VERSION,MAKEINTRESOURCE(VS_VERSION_INFO),language,&version[0],version.size()); } // copy strings for (int i=2000;i<3000;i+=16) { int id=i/16; HRSRC hResInfo=FindResource(hExplorer,MAKEINTRESOURCE(id),RT_STRING); if (!hResInfo) continue; HGLOBAL hRes=LoadResource(hExplorer,hResInfo); void *pRes=LockResource(hRes); if (!pRes) continue; UpdateResource(hEn,RT_STRING,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hExplorer,hResInfo)); } // copy dialogs for (int id=2000;id<2010;id++) { HRSRC hResInfo=FindResource(hExplorer,MAKEINTRESOURCE(id),RT_DIALOG); if (!hResInfo) continue; HGLOBAL hRes=LoadResource(hExplorer,hResInfo); void *pRes=LockResource(hRes); if (!pRes) continue; UpdateResource(hEn,RT_DIALOG,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hExplorer,hResInfo)); } // get strings and dialog from StartMenuDLL.dll hMenu=LoadLibraryEx(params[2],NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); if (!hMenu) { Printf("Failed to open %S (err: %d)\n",params[2],GetLastError()); goto qqq; } // copy strings for (int i=3000;i<5000;i+=16) { int id=i/16; HRSRC hResInfo=FindResource(hMenu,MAKEINTRESOURCE(id),RT_STRING); if (!hResInfo) continue; HGLOBAL hRes=LoadResource(hMenu,hResInfo); void *pRes=LockResource(hRes); if (!pRes) continue; UpdateResource(hEn,RT_STRING,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hMenu,hResInfo)); } for (int i=7000;i<8000;i+=16) { int id=i/16; HRSRC hResInfo=FindResource(hMenu,MAKEINTRESOURCE(id),RT_STRING); if (!hResInfo) continue; HGLOBAL hRes=LoadResource(hMenu,hResInfo); void *pRes=LockResource(hRes); if (!pRes) continue; UpdateResource(hEn,RT_STRING,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hMenu,hResInfo)); } // copy dialogs for (int id=3000;id<4010;id++) { HRSRC hResInfo=FindResource(hMenu,MAKEINTRESOURCE(id),RT_DIALOG); if (!hResInfo) continue; HGLOBAL hRes=LoadResource(hMenu,hResInfo); void *pRes=LockResource(hRes); if (!pRes) continue; UpdateResource(hEn,RT_DIALOG,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hMenu,hResInfo)); } // get strings from ClassicIEDLL.dll hIE=LoadLibraryEx(params[3],NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); if (!hIE) { Printf("Failed to open %S (err: %d)\n",params[3],GetLastError()); goto qqq; } // copy strings for (int i=5000;i<6000;i+=16) { int id=i/16; HRSRC hResInfo=FindResource(hIE,MAKEINTRESOURCE(id),RT_STRING); if (!hResInfo) continue; HGLOBAL hRes=LoadResource(hIE,hResInfo); void *pRes=LockResource(hRes); if (!pRes) continue; UpdateResource(hEn,RT_STRING,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hIE,hResInfo)); } // get strings and dialog from Update.exe hMenu=LoadLibraryEx(params[4],NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); if (!hMenu) { Printf("Failed to open %S (err: %d)\n",params[4],GetLastError()); goto qqq; } // copy strings for (int i=6000;i<7000;i+=16) { int id=i/16; HRSRC hResInfo=FindResource(hMenu,MAKEINTRESOURCE(id),RT_STRING); if (!hResInfo) continue; HGLOBAL hRes=LoadResource(hMenu,hResInfo); void *pRes=LockResource(hRes); if (!pRes) continue; UpdateResource(hEn,RT_STRING,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hMenu,hResInfo)); } // copy dialogs for (int id=6000;id<6010;id++) { HRSRC hResInfo=FindResource(hMenu,MAKEINTRESOURCE(id),RT_DIALOG); if (!hResInfo) continue; HGLOBAL hRes=LoadResource(hMenu,hResInfo); void *pRes=LockResource(hRes); if (!pRes) continue; UpdateResource(hEn,RT_DIALOG,MAKEINTRESOURCE(id),language,pRes,SizeofResource(hMenu,hResInfo)); } res=0; qqq: if (!EndUpdateResource(hEn,res!=0) && res==0) { Printf("Failed to update en-US.dll (err: %d)\n",GetLastError()); res=1; } if (hExplorer) FreeLibrary(hExplorer); if (hMenu) FreeLibrary(hMenu); if (hIE) FreeLibrary(hIE); return res; } /////////////////////////////////////////////////////////////////////////////// static void UnsescapeString( wchar_t *string ) { wchar_t *dst=string; int len=Strlen(string); bool bQuoted=false; if (string[0]=='"' && string[len-1]=='"') { bQuoted=true; string[len-1]=0; if (*string) string++; } for (const wchar_t *src=string;*src;src++) { if (*src=='\\') { src++; if (!*src) break; if (*src=='t') *dst++='\t'; else if (*src=='r') *dst++='\r'; else if (*src=='n') *dst++='\n'; else *dst++=*src; } else if (*src=='"' && bQuoted) { src++; if (!*src) break; *dst++=*src; } else *dst++=*src; } *dst=0; } static void WriteString( HANDLE csv, int id, const wchar_t *string1, int len1, const wchar_t *string2, int len2, CSettingsParser &parser, int subid=INT_MAX ) { DWORD q; wchar_t buf[256]; int len3; if (subid!=INT_MAX) len3=Sprintf(buf,_countof(buf),L"%d/%d",id,subid&65535); else len3=Sprintf(buf,_countof(buf),L"%d",id); const wchar_t *comment=parser.FindSetting(buf); if (comment && _wcsicmp(comment,L"ignore")==0) return; WriteFile(csv,buf,len3*2,&q,NULL); WriteFile(csv,L"\t",2,&q,NULL); for (int i=0;iflags&=~SWP_SHOWWINDOW; } return FALSE; } static void WriteDialog( HWND parent, HANDLE csv, int id, HINSTANCE hInstance1, const DLGTEMPLATE *pTemplate1, HINSTANCE hInstance2, const DLGTEMPLATE *pTemplate2, CSettingsParser &parser ) { HWND dlg1=CreateDialogIndirect(hInstance1,pTemplate1,parent,DefaultDlgProc); if (dlg1) { HWND dlg2=pTemplate2?CreateDialogIndirect(hInstance2,pTemplate2,parent,DefaultDlgProc):NULL; wchar_t text1[1024]; wchar_t text2[1024]; GetWindowText(dlg1,text1,_countof(text1)); if (*text1) { if (dlg2) GetWindowText(dlg2,text2,_countof(text2)); else text2[0]=0; WriteString(csv,id,text1,Strlen(text1),text2,Strlen(text2),parser,0); } for (HWND child1=GetWindow(dlg1,GW_CHILD);child1;child1=GetWindow(child1,GW_HWNDNEXT)) { GetWindowText(child1,text1,_countof(text1)); if (*text1) { int childId=(int)GetWindowLong(child1,GWL_ID); HWND child2=dlg2?GetDlgItem(dlg2,childId):NULL; if (child2) GetWindowText(child2,text2,_countof(text2)); else text2[0]=0; WriteString(csv,id,text1,Strlen(text1),text2,Strlen(text2),parser,childId); } } DestroyWindow(dlg1); if (dlg2) DestroyWindow(dlg2); } } int ExtractStrings( wchar_t *const *params, int count ) { if (count<3) return 3; const wchar_t *dllName1=params[1]; const wchar_t *dllName2=NULL; const wchar_t *csvName=params[2]; if (count>3) { dllName2=csvName; csvName=params[3]; } HMODULE hDLL1=LoadLibraryEx(dllName1,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); if (!hDLL1) { Printf("Failed to open %S (err: %d)\n",dllName1,GetLastError()); return 1; } HMODULE hDLL2=NULL; if (dllName2) { hDLL2=LoadLibraryEx(dllName2,NULL,LOAD_LIBRARY_AS_DATAFILE|LOAD_LIBRARY_AS_IMAGE_RESOURCE); if (!hDLL2) { Printf("Failed to open %S (err: %d)\n",dllName2,GetLastError()); return 1; } } int res=1; CSettingsParser parser; parser.LoadText(L"LocComments.txt"); parser.ParseText(); HANDLE hCSV=CreateFile(csvName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); if (hCSV==INVALID_HANDLE_VALUE) { Printf("Failed to write %S\n",csvName); FreeLibrary(hDLL1); if (hDLL2) FreeLibrary(hDLL2); return 1; } wchar_t title[]=L"\xFEFFID\tEnglish\tTranslation\tComment\r\n"; DWORD q; WriteFile(hCSV,title,Strlen(title)*2,&q,NULL); // copy strings for (int i=2000;i<8000;i+=16) { int id=i/16; HRSRC hResInfo=FindResource(hDLL1,MAKEINTRESOURCE(id),RT_STRING); if (!hResInfo) continue; HGLOBAL hRes=LoadResource(hDLL1,hResInfo); void *pRes=LockResource(hRes); if (!pRes) continue; const WORD *data=(WORD*)pRes; for (int j=0;j<16;j++) { int len=*data; if (len>0) { int stringId=(id-1)*16+j; wchar_t buf[1024]; if (!hDLL2 || !LoadString(hDLL2,stringId,buf,_countof(buf))) buf[0]=0; WriteString(hCSV,stringId,(const wchar_t*)data+1,len,buf,Strlen(buf),parser); } data+=len+1; } } HWND parent=CreateWindow(L"button",NULL,WS_POPUP,0,0,10,10,NULL,NULL,NULL,NULL); // copy dialogs for (int id=2000;id<7000;id++) { if (id>=2010 && id<3000) continue; if (id>=3010 && id<4000) continue; if (id>=4010 && id<5000) continue; if (id>=5010 && id<6000) continue; if (id>=6010 && id<7000) continue; HRSRC hResInfo1=FindResource(hDLL1,MAKEINTRESOURCE(id),RT_DIALOG); if (!hResInfo1) continue; void *pRes1=LockResource(LoadResource(hDLL1,hResInfo1)); if (!pRes1) continue; void *pRes2=NULL; if (hDLL2) { HRSRC hResInfo2=FindResource(hDLL2,MAKEINTRESOURCE(id),RT_DIALOG); if (hResInfo2) pRes2=LockResource(LoadResource(hDLL2,hResInfo2)); } WriteDialog(parent,hCSV,id,hDLL1,(DLGTEMPLATE*)pRes1,hDLL2,(DLGTEMPLATE*)pRes2,parser); } // additional strings { HRSRC hResInfo=FindResource(hDLL1,MAKEINTRESOURCE(1),L"L10N"); if (hResInfo) { HGLOBAL hRes=LoadResource(hDLL1,hResInfo); const wchar_t *pRes=(wchar_t*)LockResource(hRes); if (pRes) { int size=SizeofResource(hDLL1,hResInfo)/2; if (*pRes==L'\xFEFF') pRes++, size--; wchar_t *pBuf=new wchar_t[size+1]; memcpy(pBuf,pRes,size*2); pBuf[size]=0; for (int i=0;i> &oldStrings=*(std::vector>*)lParam; oldStrings.emplace_back(PtrToInt(lpszName),wIDLanguage); } return TRUE; } static BOOL CALLBACK EnumResNameProc( HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam ) { EnumResourceLanguages(hModule,lpszType,lpszName,EnumResLangProc,lParam); return TRUE; } static int ImportStrings( wchar_t *const *params, int count ) { if (count<3) return 3; const wchar_t *dllName=params[1]; const wchar_t *csvName=params[2]; HANDLE hCSV=CreateFile(csvName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if (hCSV==INVALID_HANDLE_VALUE) { Printf("Failed to read %S\n",csvName); return 1; } int size=SetFilePointer(hCSV,0,NULL,FILE_END)/2; SetFilePointer(hCSV,0,NULL,FILE_BEGIN); std::vector buf(size+1); DWORD q; ReadFile(hCSV,&buf[0],size*2,&q,NULL); CloseHandle(hCSV); buf[size]=0; for (int i=0;i lines; wchar_t *str=&buf[0]; int min=100000, max=0; while (str<&buf[size]) { int len=Strlen(str); wchar_t *next=str+len+1; wchar_t *tab=wcschr(str,'\t'); if (tab) { *tab=0; int id=_wtol(str); bool bNumber=id>0; for (;*str;str++) if (*str<'0' || *str>'9') { bNumber=false; break; } if (bNumber) { tab=wcschr(tab+1,'\t'); if (tab) { str=tab+1; tab=wcschr(str,'\t'); if (tab) *tab=0; if (lines.find(id)!=lines.end()) { Printf("Duplicate string ID %d\n",id); return 1; } UnsescapeString(str); lines[id]=str; if (min>id) min=id; if (max> oldStrings; EnumResourceNames(hDll,RT_STRING,EnumResNameProc,(LONG_PTR)&oldStrings); FreeLibrary(hDll); HANDLE hUpdate=BeginUpdateResource(dllName,FALSE); if (!hUpdate) { Printf("Failed to open %S (err: %d)\n",dllName,GetLastError()); return 1; } // delete all string resources for (int i=0;i<(int)oldStrings.size();i++) { UpdateResource(hUpdate,RT_STRING,MAKEINTRESOURCE(oldStrings[i].first),oldStrings[i].second,NULL,0); } // add new string lines max+=32; for (int i=min;i res; for (int j=0;j<16;j++,idx++) { std::map::const_iterator it=lines.find(idx); const wchar_t *str=L""; if (it!=lines.end()) str=it->second; int len=Strlen(str); res.push_back((wchar_t)len); for (int c=0;c16) UpdateResource(hUpdate,RT_STRING,MAKEINTRESOURCE(id),LANG_NEUTRAL,&res[0],res.size()*2); } if (!EndUpdateResource(hUpdate,FALSE)) { Printf("Failed to update %S (err: %d)\n",dllName,GetLastError()); return 1; } return 0; } #endif /////////////////////////////////////////////////////////////////////////////// static HRESULT CALLBACK TaskDialogCallback( HWND hwnd, UINT uNotification, WPARAM wParam, LPARAM lParam, LONG_PTR dwRefData ) { if (uNotification==TDN_HYPERLINK_CLICKED) { const wchar_t *link=(const wchar_t*)lParam; ShellExecute(hwnd,NULL,link,NULL,NULL,SW_SHOWNORMAL); } return S_OK; } /////////////////////////////////////////////////////////////////////////////// // Open-Shell utility - multiple utilities for building and maintaining Open-Shell // Usage: // no parameters - saves a troubleshooting log // crcmsi // creates a file with checksum of both msi files // makeEN // extracts the localization resources and creates a sample en-US.DLL // extract // extracts the string table, the dialog text, and the L10N text from a DLL and stores it in a CSV // extract en-us.dll // extracts the string table, the dialog text, and the L10N text from two DLL and stores it in a CSV // import // replaces the string table in the DLL with the text from the CSV int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpstrCmdLine, int nCmdShow ) { g_hInstance=hInstance; if (!*lpstrCmdLine) { #ifndef _WIN64 DWORD winVer=GetVersionEx(GetModuleHandle(L"user32.dll")); TASKDIALOG_BUTTON taskButtons[4]={ {101,L"Save system log\nSaves detailed information about your system for troubleshooting purposes."}, {102,L"Open-Shell logging options\nEnable or disable various logging options."}, {103,L"Remove Open-Shell\nManually removes Open-Shell from your system. Use only if the conventional methods for uninstallation do not work."}, {104,L"Show Metro colors\nSee the color palette that can be used in start menu skins."}, }; TASKDIALOGCONFIG tasks={sizeof(tasks)}; tasks.dwFlags=TDF_USE_HICON_MAIN|TDF_USE_COMMAND_LINKS|TDF_ENABLE_HYPERLINKS; tasks.dwCommonButtons=TDCBF_CANCEL_BUTTON; tasks.pszWindowTitle=L"Open-Shell Utility"; tasks.hMainIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1)); tasks.pszMainInstruction=L"Select task to perform"; tasks.cButtons=HIWORD(winVer)>=0x0602?4:3; tasks.pButtons=taskButtons; tasks.pszFooter=L"Open-Shell Homepage"; tasks.pfCallback=TaskDialogCallback; int seleciton; if (TaskDialogIndirect(&tasks,&seleciton,NULL,NULL)==IDCANCEL) return 0; if (seleciton==101) { ShowSaveLogFile(); } else if (seleciton==102) { EditLoggingOptions(); } else if (seleciton==103) { wchar_t exe[_MAX_PATH]; GetModuleFileName(NULL,exe,_countof(exe)); CoInitialize(NULL); ShellExecute(NULL,L"runas",exe,L"uninstall",NULL,SW_SHOWNORMAL); CoUninitialize(); } else if (seleciton==104) { ShowMetroColorViewer(); } #endif return 0; } int count; wchar_t *const *params=CommandLineToArgvW(lpstrCmdLine,&count); #ifndef _WIN64 if (_wcsicmp(params[0],L"crcmsi")==0) { return CalcMsiChecksum(params,count); } if (_wcsicmp(params[0],L"makeEN")==0) { return MakeEnglishDll(params,count); } if (_wcsicmp(params[0],L"extract")==0) { return ExtractStrings(params,count); } if (_wcsicmp(params[0],L"import")==0) { return ImportStrings(params,count); } if (_wcsicmp(params[0],L"colors")==0) { ShowMetroColorViewer(); return 0; } if (_wcsicmp(params[0],L"uninstall")==0) { ManualUninstall(); return 0; } #endif if (_wcsicmp(params[0],L"savelog")==0 || _wcsicmp(params[0],L"saveloga")==0) { if (count<=1) return 1; return SaveLogFile(params[1],_wcsicmp(params[0],L"saveloga")==0); } return 1; }