OSDN Git Service

20021009版ソース
[seraphyscrtools/SeraphyScriptTools.git] / Shell.cpp
1 // Shell.cpp : CShell \82Ì\83C\83\93\83v\83\8a\83\81\83\93\83e\81[\83V\83\87\83\93
2 #include "stdafx.h"
3 #include "SeraphyScriptTools.h"
4 #include "Shell.h"
5 #include "generic.h"
6 #include <list>
7 using namespace std;
8
9 /////////////////////////////////////////////////////////////////////////////
10 // CShell
11
12 STDMETHODIMP CShell::InterfaceSupportsErrorInfo(REFIID riid)
13 {
14         static const IID* arr[] = 
15         {
16                 &IID_ISeraphyScriptTools_Shell
17         };
18         for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
19         {
20                 if (IsEqualGUID(*arr[i],riid))
21                         return S_OK;
22         }
23         return S_FALSE;
24 }
25
26 STDMETHODIMP CShell::ShellExecute(VARIANT path, VARIANT param, VARIANT initdir, VARIANT show, VARIANT *punkVal)
27 {
28         CComVariant varPath,varParam,varInitDir,varMode;
29         CHAR szPath[MAX_PATH] = { 0 };
30         CHAR szInitDir[MAX_PATH] = { 0 };
31         int nShow = SW_SHOWNORMAL;
32         LPSTR pBuf = NULL;
33         if(varPath.ChangeType(VT_BSTR,&path) == S_OK){
34                 WideCharToMultiByte(GetACP(),0,varPath.bstrVal,-1,szPath,MAX_PATH,NULL,NULL);
35         }
36         if(varParam.ChangeType(VT_BSTR,&param) == S_OK){
37                 int needsize = WideCharToMultiByte(GetACP(),0,varParam.bstrVal,-1,NULL,0,NULL,NULL);
38                 pBuf = new CHAR[needsize+1];
39                 WideCharToMultiByte(GetACP(),0,varParam.bstrVal,-1,pBuf,needsize,NULL,NULL);
40         }
41         if(varInitDir.ChangeType(VT_BSTR,&initdir) == S_OK){
42                 WideCharToMultiByte(GetACP(),0,varInitDir.bstrVal,-1,szInitDir,MAX_PATH,NULL,NULL);
43         }
44         if(varMode.ChangeType(VT_I2,&show) == S_OK){
45                 switch(varMode.iVal)
46                 {
47                 case 0:
48                         nShow = SW_HIDE;
49                         break;
50                 case 1:
51                 default:
52                         nShow = SW_SHOWNORMAL;
53                         break;
54                 case 2:
55                         nShow = SW_SHOWMAXIMIZED;
56                         break;
57                 case 3:
58                         nShow = SW_SHOWMINIMIZED;
59                         break;
60                 case 4:
61                         nShow = SW_SHOWMINNOACTIVE;
62                         break;
63                 }
64         }
65         //
66         SHELLEXECUTEINFO info = {0};
67         info.cbSize = sizeof(SHELLEXECUTEINFO);
68         info.fMask  = SEE_MASK_DOENVSUBST | SEE_MASK_NOCLOSEPROCESS;
69         info.hwnd   = GetMainWindow();
70         info.lpVerb = "OPEN";
71         info.lpFile = szPath;
72         info.lpParameters = pBuf;
73         info.lpDirectory  = szInitDir;
74         info.nShow  = nShow;
75         if(ShellExecuteEx(&info)){
76                 // ShellExecObj\82Ì\90\90¬
77                 CComObject<CShellExecObj>* pExec = NULL;
78                 if(pExec->CreateInstance(&pExec) == S_OK){
79                         pExec->m_hProcess = info.hProcess;
80                         IUnknown* pUnk = NULL;
81                         pExec->QueryInterface(IID_IUnknown,(void**)&pUnk);
82                         punkVal->vt      = VT_UNKNOWN;
83                         punkVal->punkVal = pUnk;
84                 }
85         }
86         if(pBuf){
87                 delete[]pBuf;
88         }
89         return S_OK;
90 }
91
92 /////////////////////////////////////////////////////////////////////////////
93 // CShellExecObj
94
95
96 STDMETHODIMP CShellExecObj::Wait(VARIANT tim, VARIANT *pVal)
97 {
98         ::VariantInit(pVal);
99         BOOL bExit = true;
100         if(m_hProcess){
101                 CComVariant varTim;
102                 DWORD dwWaitTime = 0;
103                 if(varTim.ChangeType(VT_I4,&tim) == S_OK){
104                         if(varTim.lVal < 0){
105                                 // \96³\8cÀ\82Ü\82¿
106                                 dwWaitTime = INFINITE;
107                         }
108                         else{
109                                 dwWaitTime = (DWORD)varTim.lVal;
110                         }
111                 }
112                 DWORD ret = WaitForSingleObject(m_hProcess,dwWaitTime);
113                 if(ret == WAIT_TIMEOUT){
114                         // \83v\83\8d\83Z\83X\82Í\8fI\97¹\82µ\82Ä\82¢\82È\82¢
115                         bExit = false;
116                 }
117         }
118         pVal->vt      = VT_BOOL;
119         pVal->boolVal = bExit?VB_TRUE:VB_FALSE;
120         return S_OK;
121 }
122
123 STDMETHODIMP CShellExecObj::get_ExitCode(long *pVal)
124 {
125         if(m_hProcess){
126                 GetExitCodeProcess(m_hProcess,(DWORD*)pVal);
127         }
128         return S_OK;
129 }
130
131 class SPECIALFOLDERPAIR
132 {
133 public:
134         SPECIALFOLDERPAIR(LPCSTR arg_name,int arg_id){
135                 name = arg_name;
136                 id   = arg_id;
137         }
138         LPCSTR name;
139         int id;
140 };
141
142 STDMETHODIMP CShell::GetSpecialFolderLocations(IUnknown *punkVal)
143 {
144         if(!punkVal){
145                 return E_FAIL;
146         }
147         IObjectMap* pMap = NULL;
148         if(punkVal->QueryInterface(IID_IObjectMap,(void**)&pMap) != S_OK){
149                 return DISP_E_TYPEMISMATCH;
150         }
151         // \83V\83X\83e\83\80\83o\81[\83W\83\87\83\93\83`\83F\83b\83N
152         BOOL bWinNT;
153         get_IsWindowNT(&bWinNT);
154         // NT\8cn\82Ì\8fê\8d\87\82Æ9x\8cn\82Ì\8fê\8d\87\82Æ\82Í\8eæ\93¾\82Å\82«\82é\83t\83H\83\8b\83_\82Ì\8eí\97Þ\82ª\82¿\82ª\82¤\82Ì\82Å\95ª\82¯\82Ä\82¨\82­
155         list<SPECIALFOLDERPAIR> lst;
156         if(bWinNT){
157                 // WINNT
158                 lst.push_back(SPECIALFOLDERPAIR("ADMINTOOLS",CSIDL_ADMINTOOLS));
159                 lst.push_back(SPECIALFOLDERPAIR("ALTSTARTUP",CSIDL_ALTSTARTUP));
160                 lst.push_back(SPECIALFOLDERPAIR("APPDATA",CSIDL_APPDATA));
161                 lst.push_back(SPECIALFOLDERPAIR("COMMON_ADMINTOOLS",CSIDL_COMMON_ADMINTOOLS));
162                 lst.push_back(SPECIALFOLDERPAIR("COMMON_ALTSTARTUP",CSIDL_COMMON_ALTSTARTUP));
163                 lst.push_back(SPECIALFOLDERPAIR("COMMON_APPDATA",CSIDL_COMMON_APPDATA));
164                 lst.push_back(SPECIALFOLDERPAIR("COMMON_DESKTOPDIRECTORY",CSIDL_COMMON_DESKTOPDIRECTORY));
165                 lst.push_back(SPECIALFOLDERPAIR("COMMON_DOCUMENTS",CSIDL_COMMON_DOCUMENTS));
166                 lst.push_back(SPECIALFOLDERPAIR("COMMON_FAVORITES",CSIDL_COMMON_FAVORITES));
167                 lst.push_back(SPECIALFOLDERPAIR("COMMON_PROGRAMS",CSIDL_COMMON_PROGRAMS));
168                 lst.push_back(SPECIALFOLDERPAIR("COMMON_STARTMENU",CSIDL_COMMON_STARTMENU));
169                 lst.push_back(SPECIALFOLDERPAIR("COMMON_STARTUP",CSIDL_COMMON_STARTUP));
170                 lst.push_back(SPECIALFOLDERPAIR("COMMON_TEMPLATES",CSIDL_COMMON_TEMPLATES));
171                 lst.push_back(SPECIALFOLDERPAIR("COOKIES",CSIDL_COOKIES));
172                 lst.push_back(SPECIALFOLDERPAIR("DESKTOPDIRECTORY",CSIDL_DESKTOPDIRECTORY));
173                 lst.push_back(SPECIALFOLDERPAIR("FAVORITES",CSIDL_FAVORITES));
174                 lst.push_back(SPECIALFOLDERPAIR("FONTS",CSIDL_FONTS ));
175                 lst.push_back(SPECIALFOLDERPAIR("HISTORY",CSIDL_HISTORY));
176                 lst.push_back(SPECIALFOLDERPAIR("INTERNET_CACHE ",CSIDL_INTERNET_CACHE ));
177                 lst.push_back(SPECIALFOLDERPAIR("LOCAL_APPDATA ",CSIDL_LOCAL_APPDATA ));
178                 lst.push_back(SPECIALFOLDERPAIR("MYPICTURES",CSIDL_MYPICTURES));
179                 lst.push_back(SPECIALFOLDERPAIR("NETHOOD",CSIDL_NETHOOD));
180                 lst.push_back(SPECIALFOLDERPAIR("PERSONAL",CSIDL_PERSONAL));
181                 lst.push_back(SPECIALFOLDERPAIR("PRINTHOOD",CSIDL_PRINTHOOD));
182                 lst.push_back(SPECIALFOLDERPAIR("PROFILE ",CSIDL_PROFILE ));
183                 lst.push_back(SPECIALFOLDERPAIR("PROGRAM_FILES",CSIDL_PROGRAM_FILES));
184                 lst.push_back(SPECIALFOLDERPAIR("PROGRAM_FILES_COMMON",CSIDL_PROGRAM_FILES_COMMON));
185                 lst.push_back(SPECIALFOLDERPAIR("PROGRAMS",CSIDL_PROGRAMS));
186                 lst.push_back(SPECIALFOLDERPAIR("RECENT",CSIDL_RECENT ));
187                 lst.push_back(SPECIALFOLDERPAIR("SENDTO",CSIDL_SENDTO ));
188                 lst.push_back(SPECIALFOLDERPAIR("STARTMENU",CSIDL_STARTMENU));
189                 lst.push_back(SPECIALFOLDERPAIR("STARTUP",CSIDL_STARTUP));
190                 lst.push_back(SPECIALFOLDERPAIR("SYSTEM",CSIDL_SYSTEM));
191                 lst.push_back(SPECIALFOLDERPAIR("TEMPLATES",CSIDL_TEMPLATES));
192                 lst.push_back(SPECIALFOLDERPAIR("WINDOWS",CSIDL_WINDOWS));
193         }
194         else{
195                 // Win9x
196                 lst.push_back(SPECIALFOLDERPAIR("ADMINTOOLS",CSIDL_ADMINTOOLS));
197                 lst.push_back(SPECIALFOLDERPAIR("ALTSTARTUP",CSIDL_ALTSTARTUP));
198                 lst.push_back(SPECIALFOLDERPAIR("APPDATA",CSIDL_APPDATA));
199                 lst.push_back(SPECIALFOLDERPAIR("COMMON_ADMINTOOLS",CSIDL_ADMINTOOLS));
200                 lst.push_back(SPECIALFOLDERPAIR("COMMON_ALTSTARTUP",CSIDL_ALTSTARTUP));
201                 lst.push_back(SPECIALFOLDERPAIR("COMMON_APPDATA",CSIDL_APPDATA));
202                 lst.push_back(SPECIALFOLDERPAIR("COMMON_DESKTOPDIRECTORY",CSIDL_DESKTOPDIRECTORY));
203                 lst.push_back(SPECIALFOLDERPAIR("COMMON_DOCUMENTS",CSIDL_COMMON_DOCUMENTS));
204                 lst.push_back(SPECIALFOLDERPAIR("COMMON_FAVORITES",CSIDL_FAVORITES));
205                 lst.push_back(SPECIALFOLDERPAIR("COMMON_PROGRAMS",CSIDL_PROGRAMS));
206                 lst.push_back(SPECIALFOLDERPAIR("COMMON_STARTMENU",CSIDL_STARTMENU));
207                 lst.push_back(SPECIALFOLDERPAIR("COMMON_STARTUP",CSIDL_STARTUP));
208                 lst.push_back(SPECIALFOLDERPAIR("COMMON_TEMPLATES",CSIDL_TEMPLATES));
209                 lst.push_back(SPECIALFOLDERPAIR("COOKIES",CSIDL_COOKIES));
210                 lst.push_back(SPECIALFOLDERPAIR("DESKTOPDIRECTORY",CSIDL_DESKTOPDIRECTORY));
211                 lst.push_back(SPECIALFOLDERPAIR("FAVORITES",CSIDL_FAVORITES));
212                 lst.push_back(SPECIALFOLDERPAIR("FONTS",CSIDL_FONTS ));
213                 lst.push_back(SPECIALFOLDERPAIR("HISTORY",CSIDL_HISTORY));
214                 lst.push_back(SPECIALFOLDERPAIR("INTERNET_CACHE ",CSIDL_INTERNET_CACHE ));
215                 lst.push_back(SPECIALFOLDERPAIR("LOCAL_APPDATA ",CSIDL_LOCAL_APPDATA ));
216                 lst.push_back(SPECIALFOLDERPAIR("MYPICTURES",CSIDL_MYPICTURES));
217                 lst.push_back(SPECIALFOLDERPAIR("NETHOOD",CSIDL_NETHOOD));
218                 lst.push_back(SPECIALFOLDERPAIR("PERSONAL",CSIDL_PERSONAL));
219                 lst.push_back(SPECIALFOLDERPAIR("PRINTHOOD",CSIDL_PRINTHOOD));
220                 lst.push_back(SPECIALFOLDERPAIR("PROFILE ",CSIDL_PROFILE ));
221                 lst.push_back(SPECIALFOLDERPAIR("PROGRAM_FILES",CSIDL_PROGRAM_FILES));
222                 lst.push_back(SPECIALFOLDERPAIR("PROGRAM_FILES_COMMON",CSIDL_PROGRAM_FILES));
223                 lst.push_back(SPECIALFOLDERPAIR("PROGRAMS",CSIDL_PROGRAMS));
224                 lst.push_back(SPECIALFOLDERPAIR("RECENT",CSIDL_RECENT ));
225                 lst.push_back(SPECIALFOLDERPAIR("SENDTO",CSIDL_SENDTO ));
226                 lst.push_back(SPECIALFOLDERPAIR("STARTMENU",CSIDL_STARTMENU));
227                 lst.push_back(SPECIALFOLDERPAIR("STARTUP",CSIDL_STARTUP));
228                 lst.push_back(SPECIALFOLDERPAIR("SYSTEM",CSIDL_SYSTEM));
229                 lst.push_back(SPECIALFOLDERPAIR("TEMPLATES",CSIDL_TEMPLATES));
230                 lst.push_back(SPECIALFOLDERPAIR("WINDOWS",CSIDL_WINDOWS));
231         }
232         list<SPECIALFOLDERPAIR>::iterator p = lst.begin();
233         while(p != lst.end()){
234                 LPITEMIDLIST pid = NULL;
235                 if(SHGetSpecialFolderLocation(NULL,(*p).id,&pid) == NOERROR){
236                         CHAR buf[MAX_PATH] = {0};
237                         if(SHGetPathFromIDList(pid,buf)){
238                                 CComVariant key((LPCSTR)(*p).name);
239                                 CComVariant value((LPCSTR)buf);
240                                 pMap->put_Value(key,value);
241                         }
242                         m_pMalloc->Free(pid);
243                 }
244                 p++;
245         }
246         pMap->Release();
247         return S_OK;
248 }
249
250 STDMETHODIMP CShell::get_IsWindowNT(BOOL *pVal)
251 {
252         OSVERSIONINFO vinfo = {0};
253         vinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
254         GetVersionEx(&vinfo);
255         *pVal = (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
256         return S_OK;
257 }
258
259
260 STDMETHODIMP CShell::get_WindowsVersion(long *pVal)
261 {
262         // win9x\82Í0\81ANT\82Í\83o\81[\83W\83\87\83\93\82ð\95Ô\82·
263         *pVal = 0;
264         OSVERSIONINFO vinfo = {0};
265         vinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
266         GetVersionEx(&vinfo);
267         if(vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT){
268                 *pVal = (long)vinfo.dwMajorVersion;
269         }
270         return S_OK;
271 }
272
273 STDMETHODIMP CShell::GetDLLVersion(VARIANT text,VARIANT min, VARIANT *pVal)
274 {
275         CComVariant varText,varMin;
276         CHAR lpszDllName[MAX_PATH] = { 0 };
277         if(varText.ChangeType(VT_BSTR,&text) == S_OK){
278                 WideCharToMultiByte(GetACP(),0,varText.bstrVal,-1,lpszDllName,MAX_PATH,NULL,NULL);
279         }
280         BOOL bMin = false;
281         if(varMin.ChangeType(VT_I2,&min) == S_OK){
282                 bMin = varMin.iVal;
283         }
284         CComVariant ret;
285         DWORD siz = GetFileVersionInfoSize(lpszDllName,0);
286         if(siz){
287                 LPBYTE pBuf = new BYTE[siz+1];
288                 if(GetFileVersionInfo(lpszDllName,0,siz,pBuf)){
289                         // \83o\81[\83W\83\87\83\93\8fî\95ñ\82ð\8eæ\93¾\82·\82é
290                         VS_FIXEDFILEINFO* pverInfo;
291                         UINT sz = 0;
292                         if(VerQueryValue(pBuf,"\\",(void**)&pverInfo,&sz)){
293                                 // \83o\81[\83W\83\87\83\93\82ð\8am\94F\89Â\94\\82Å\82 \82é
294                                 CHAR mes[256];
295                                 if(bMin){
296                                         // \8fÚ\8d×
297                                         wsprintf(mes,"%d.%d.%d.%d"
298                                                 ,HIWORD(pverInfo->dwFileVersionMS),LOWORD(pverInfo->dwFileVersionMS)
299                                                 ,HIWORD(pverInfo->dwFileVersionLS),LOWORD(pverInfo->dwFileVersionLS));
300                                 }
301                                 else{
302                                         // \92Ê\8fí
303                                         wsprintf(mes,"%d.%d"
304                                                 ,HIWORD(pverInfo->dwFileVersionMS),LOWORD(pverInfo->dwFileVersionMS));
305                                 }
306                                 ret = (LPCSTR)mes;
307                         }
308                 }
309                 delete[]pBuf;
310         }
311         ret.Detach(pVal);
312         return S_OK;
313 }
314
315 STDMETHODIMP CShell::ParseName(VARIANT text, VARIANT *pVal)
316 {
317         ::VariantInit(pVal);
318         CComVariant varText;
319         if(varText.ChangeType(VT_BSTR,&text) == S_OK){
320                 CComObject<CParseName>* pParse = NULL;
321                 if(pParse->CreateInstance(&pParse) == S_OK){
322                         pParse->m_bstr_path = (LPCWSTR)varText.bstrVal;
323                         IUnknown* pUnk = NULL;
324                         if(pParse->QueryInterface(IID_IUnknown,(void**)&pUnk) == S_OK){
325                                 pVal->vt      = VT_UNKNOWN;
326                                 pVal->punkVal = pUnk;
327                         }
328                 }
329         }
330         return S_OK;
331 }
332
333 /////////////////////////////////////////////////////////////////////////////
334 // CParseName
335
336 STDMETHODIMP CParseName::InterfaceSupportsErrorInfo(REFIID riid)
337 {
338         static const IID* arr[] = 
339         {
340                 &IID_ISeraphyScriptTool_ParseName
341         };
342         for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
343         {
344                 if (IsEqualGUID(*arr[i],riid))
345                         return S_OK;
346         }
347         return S_FALSE;
348 }
349
350 STDMETHODIMP CParseName::get_PathName(BSTR *pVal)
351 {
352         *pVal = m_bstr_path.copy();
353         return S_OK;
354 }
355
356 STDMETHODIMP CParseName::put_PathName(BSTR newVal)
357 {
358         m_bstr_path = newVal;
359         return S_OK;
360 }
361
362 STDMETHODIMP CParseName::get_FileName(BSTR *pVal)
363 {
364         LPWSTR p = m_bstr_path;
365         while(*p)p++;
366         while(p > (LPCWSTR)m_bstr_path){
367                 if(*p == '\\' || *p == '/'){
368                         // \96\96\94ö\82©\82ç\8dÅ\8f\89\82É\94­\8c©\82³\82ê\82½\83t\83H\83\8b\83_\83v\83\8c\81[\83X\82Å\8e~\82Ü\82é
369                         p++;
370                         break;
371                 }
372                 p--;
373         }
374         *pVal = SysAllocString(p);
375         return S_OK;
376 }
377
378 STDMETHODIMP CParseName::put_FileName(BSTR newVal)
379 {
380         WCHAR buf[MAX_PATH];
381         lstrcpyW(buf,m_bstr_path);
382         LPWSTR p = buf;
383         while(*p)p++;
384         while(p > buf){
385                 if(*p == '\\' || *p == '/'){
386                         // \96\96\94ö\82©\82ç\8dÅ\8f\89\82É\94­\8c©\82³\82ê\82½\83t\83H\83\8b\83_\83v\83\8c\81[\83X\82Å\8e~\82Ü\82é
387                         p++;
388                         break;
389                 }
390                 p--;
391         }
392         lstrcpyW(p,newVal);
393         m_bstr_path = buf;
394         return S_OK;
395 }
396
397 STDMETHODIMP CParseName::get_Extention(BSTR *pVal)
398 {
399         BOOL bFind = false;
400         LPWSTR p = m_bstr_path;
401         while(*p)p++;
402         while(p > (LPCWSTR)m_bstr_path){
403                 if(*p == '.'){
404                         bFind = true;
405                         p++;
406                         break;
407                 }
408                 if(*p == '\\' || *p == '/'){
409                         // \83t\83H\83\8b\83_\83v\83\8c\81[\83X\82Å\92\86\8e~\82·\82é
410                         break;
411                 }
412                 p--;
413         }
414         if(!bFind){
415                 while(*p)p++;
416         }
417         *pVal = SysAllocString(p);
418         return S_OK;
419 }
420
421 STDMETHODIMP CParseName::put_Extention(BSTR newVal)
422 {
423         WCHAR buf[MAX_PATH];
424         lstrcpyW(buf,m_bstr_path);
425         BOOL bFind = false;
426         LPWSTR p = buf;
427         while(*p)p++;
428         while(p > buf){
429                 if(*p == '.'){
430                         bFind = true;
431                         p++;
432                         break;
433                 }
434                 if(*p == '\\' || *p == '/'){
435                         // \83t\83H\83\8b\83_\83v\83\8c\81[\83X\82Å\92\86\8e~\82·\82é
436                         break;
437                 }
438                 p--;
439         }
440         if(!bFind){
441                 // \89½\82à\82È\82¯\82ê\82Î\96\96\94ö\82É\92Ç\89Á\82·\82é
442                 while(*p)p++;
443                 lstrcpyW(p,L".");
444         }
445         lstrcpyW(p,newVal);
446         m_bstr_path = buf;
447         return S_OK;
448 }
449
450 STDMETHODIMP CParseName::get_Name(BSTR *pVal)
451 {
452         WCHAR buf[MAX_PATH];
453         lstrcpyW(buf,m_bstr_path);
454         LPWSTR p = buf;
455         while(*p)p++;
456         while(p > buf){
457                 if(*p == '\\' || *p == '/'){
458                         p++;
459                         break;
460                 }
461                 p--;
462         }
463         LPWSTR p2 = p;
464         while(*p2){
465                 if(*p2 == '.'){
466                         *p2 = 0;
467                         break;
468                 }
469                 p2++;
470         }
471         *pVal = SysAllocString(p);
472         return S_OK;
473 }
474
475 STDMETHODIMP CParseName::put_Name(BSTR newVal)
476 {
477         WCHAR buf[MAX_PATH];
478         WCHAR ext[MAX_PATH] = { 0 };
479         lstrcpyW(buf,m_bstr_path);
480         LPWSTR p = buf;
481         while(*p)p++;
482         while(p > buf){
483                 if(*p == '\\' || *p == '/'){
484                         p++;
485                         break;
486                 }
487                 p--;
488         }
489         LPWSTR p2 = p;
490         while(*p2){
491                 if(*p2 == '.'){
492                         p2++;
493                         lstrcpyW(ext,p2);
494                         break;
495                 }
496                 p2++;
497         }
498         lstrcpyW(p,newVal);
499         while(*p)p++;
500         *p++ = '.';
501         lstrcpyW(p,ext);
502         m_bstr_path = buf;
503         return S_OK;
504 }
505
506 STDMETHODIMP CParseName::get_Drive(BSTR *pVal)
507 {
508         WCHAR buf[MAX_PATH];
509         lstrcpyW(buf,m_bstr_path);
510         LPWSTR p = buf;
511         while(*p){
512                 if(*p == ':'){
513                         // \83h\83\89\83C\83u\8bæ\90Ø\82è\81A\82Ü\82½\82Í\83v\83\8d\83g\83R\83\8b\82ð\94­\8c©\82µ\82½
514                         *(p+1) = 0;
515                         p = buf;
516                         break;
517                 }
518                 p++;
519         }
520         *pVal = SysAllocString(p);
521         return S_OK;
522 }
523
524 STDMETHODIMP CParseName::put_Drive(BSTR newVal)
525 {
526         WCHAR buf[MAX_PATH];
527         lstrcpyW(buf,newVal);
528         LPWSTR p2 = buf;
529         while(*p2)p2++;
530         LPWSTR p = m_bstr_path;
531         BOOL bFind = false;
532         while(*p){
533                 if(*p == ':'){
534                         // \83h\83\89\83C\83u\8bæ\90Ø\82è\81A\82Ü\82½\82Í\83v\83\8d\83g\83R\83\8b\82ð\94­\8c©\82µ\82½
535                         p++;
536                         bFind = true;
537                         break;
538                 }
539                 p++;
540         }
541         if(!bFind){
542                 p = m_bstr_path;
543         }
544         lstrcpyW(p2,p);
545         m_bstr_path = buf;
546         return S_OK;
547 }
548
549 STDMETHODIMP CParseName::get_Directory(BSTR *pVal)
550 {
551         WCHAR buf[MAX_PATH];
552         LPWSTR p = m_bstr_path;
553         BOOL bFind = false;
554         while(*p){
555                 if(*p == ':'){
556                         // \83h\83\89\83C\83u\8bæ\90Ø\82è\81A\82Ü\82½\82Í\83v\83\8d\83g\83R\83\8b\82ð\94­\8c©\82µ\82½
557                         p++;
558                         bFind = true;
559                         break;
560                 }
561                 p++;
562         }
563         if(!bFind){
564                 p = m_bstr_path;
565         }
566         lstrcpyW(buf,p);
567         p = buf;
568         while(*p)p++;
569         while(p >= buf){
570                 if(*p == '\\' || *p== '/'){
571                         // \83t\83H\83\8b\83_\83v\83\8c\83C\83X\82ð\94­\8c©\82µ\82½
572                         if(p-1 > buf && (*(p-1) == '\\' || *(p-1) == '/')){
573                                 // \83l\83b\83g\83\8f\81[\83N\83p\83X\82É\93\9e\92B\82µ\82½\8fê\8d\87\82Í\96³\8e\8b\82·\82é
574                                 break;
575                         }
576                         p++;
577                         *p = 0;
578                         break;
579                 }
580                 p--;
581         }
582         *pVal = SysAllocString(buf);
583         return S_OK;
584 }
585
586 ///////////////////////////////////////////////////
587
588 STDMETHODIMP CShell::get_Confirm(BOOL *pVal)
589 {
590         *pVal = (m_bConfirm)?VB_TRUE:VB_FALSE;
591         return S_OK;
592 }
593
594 STDMETHODIMP CShell::put_Confirm(BOOL newVal)
595 {
596         m_bConfirm = newVal;
597         return S_OK;
598 }
599
600 STDMETHODIMP CShell::get_Silent(BOOL *pVal)
601 {
602         *pVal = (m_bSilent)?VB_TRUE:VB_FALSE;
603         return S_OK;
604 }
605
606 STDMETHODIMP CShell::put_Silent(BOOL newVal)
607 {
608         m_bSilent = newVal;
609         return S_OK;
610 }
611
612 STDMETHODIMP CShell::Copy(VARIANT from, VARIANT to, VARIANT *pVal)
613 {
614         return FileOperationCore(FO_COPY, 0, &from, &to, pVal);
615 }
616
617 STDMETHODIMP CShell::CopyRenameOnCollision(VARIANT from, VARIANT to, VARIANT *pVal)
618 {
619         return FileOperationCore(FO_COPY, FOF_RENAMEONCOLLISION, &from, &to, pVal);
620 }
621
622 STDMETHODIMP CShell::Move(VARIANT from, VARIANT to, VARIANT *pVal)
623 {
624         return FileOperationCore(FO_MOVE, 0, &from, &to, pVal);
625 }
626
627 STDMETHODIMP CShell::Delete(VARIANT from,VARIANT *pVal)
628 {
629         return FileOperationCore(FO_DELETE, 0, &from, NULL, pVal);
630 }
631
632 HRESULT CShell::FileOperationCore(UINT wFunc, FILEOP_FLAGS flag, VARIANT *from, VARIANT *to, VARIANT *pResult)
633 {
634         ::VariantInit(pResult);
635         CComVariant result;
636         CHAR szDest[MAX_PATH+2] = { 0 }; // double null
637         if(to){
638                 CComVariant varTo;
639                 if(to->vt != VT_NULL && to->vt != VT_ERROR || to->vt == VT_EMPTY
640                         || varTo.ChangeType(VT_BSTR,to) != S_OK){
641                         return DISP_E_TYPEMISMATCH;
642                 }
643                 WideCharToMultiByte(GetACP(),0,varTo.bstrVal,-1,szDest,MAX_PATH,NULL,NULL);
644         }
645         LPSTR pFrom = CreateDNStringFromVariant(*from);
646         if(!pFrom){
647                 return DISP_E_TYPEMISMATCH;
648         }
649         SHFILEOPSTRUCT info = {0};
650         info.fFlags = flag | FOF_ALLOWUNDO | (m_bSilent?FOF_SILENT:0) | (m_bConfirm?0:(FOF_NOCONFIRMMKDIR|FOF_NOCONFIRMATION));
651         info.hwnd   = GetMainWindow();
652         info.pFrom  = pFrom;
653         info.pTo    = szDest;
654         info.wFunc  = wFunc;
655         int ret = SHFileOperation(&info);
656         delete[]pFrom;
657         result = (bool)(!ret && !info.fAnyOperationsAborted);
658         result.Detach(pResult);
659         return S_OK;
660 }
661
662 LPSTR CShell::CreateDNStringFromVariant(VARIANT &from)
663 {
664         LPSTR pBuf = NULL;
665         CComVariant varFrom;
666         if(varFrom.ChangeType(VT_BSTR,&from) == S_OK){
667                 // BSTR\82É\95Ï\8a·\89Â\94\\82©?
668                 int needsize = WideCharToMultiByte(GetACP(),0,varFrom.bstrVal,-1,NULL,0,NULL,NULL);
669                 pBuf = new CHAR[needsize+2];
670                 WideCharToMultiByte(GetACP(),0,varFrom.bstrVal,-1,pBuf,needsize,NULL,NULL);
671                 pBuf[needsize  ] = 0;
672                 pBuf[needsize+1] = 0; // double null
673                 return pBuf;
674         }
675         else if(varFrom.ChangeType(VT_UNKNOWN,&from) == S_OK){
676                 // Unknown\82É\95Ï\8a·\89Â\94\\82©?
677                 IObjectVector* pVector = NULL;
678                 if(varFrom.punkVal->QueryInterface(IID_IObjectVector,(void**)&pVector) != S_OK){
679                         // IObjectVector\82Å\82Í\82È\82¢\82È\82ç\83G\83\89\81[
680                         return NULL;
681                 }
682                 // \94z\97ñ\82ð\8eæ\93¾\82·\82é
683                 long mx = 0;
684                 pVector->get_Count(&mx);
685                 long cnt = 0;
686                 // \94z\97ñ\91S\91Ì\82Ì\83T\83C\83Y\82ð\8b\81\82ß\82é
687                 DWORD needsize = 0;
688                 for(cnt = 0 ; cnt < mx ; cnt++){
689                         CComVariant tmp;
690                         CComVariant idx((long)cnt);
691                         pVector->get_Value(idx,&tmp);
692                         if(tmp.ChangeType(VT_BSTR) != S_OK){
693                                 // \95\8e\9a\97ñ\82É\95Ï\8a·\95s\89Â\94\
694                                 return NULL;
695                         }
696                         needsize += WideCharToMultiByte(GetACP(),0,tmp.bstrVal,-1,NULL,0,NULL,NULL) + 1;
697                 }
698                 needsize += 1; // dobulenull
699                 // \94z\97ñ\82ð\83_\83u\83\8b\83k\83\8b\82É\93W\8aJ\82·\82é
700                 pBuf = new CHAR[needsize];
701                 LPSTR p = pBuf;
702                 for(cnt = 0 ; cnt < mx ; cnt++){
703                         CComVariant tmp;
704                         CComVariant idx((long)cnt);
705                         pVector->get_Value(idx,&tmp);
706                         if(tmp.ChangeType(VT_BSTR) == S_OK){
707                                 int sz = WideCharToMultiByte(GetACP(),0,tmp.bstrVal,-1,p,MAX_PATH,NULL,NULL);
708                                 *(p + sz) = 0;
709                                 p += sz;
710                         }
711                 }
712                 *p = 0; // dobule null
713                 pVector->Release();
714                 return pBuf;
715         }
716         else{
717                 // SafeArray\82©?
718                 VARTYPE vt = VT_EMPTY;
719                 SAFEARRAY* pArray = GetArrayFromVariant(from,&vt);
720                 if(!pArray || vt != VT_VARIANT){
721                         // SafeArray\82Å\82È\82¢\82©\81A\8c^\82ª\82¿\82ª\82¤
722                         return NULL;
723                 }
724                 long lb = 0;
725                 long ub = 0;
726                 int dm = SafeArrayGetDim(pArray);
727                 SafeArrayGetLBound(pArray,1,&lb); // \8d\91¤\82Ì\93Y\82¦\8e\9a
728                 SafeArrayGetUBound(pArray,1,&ub);
729                 if(dm != 1 || lb != 0){
730                         // 1\8e\9f\8c³\94z\97ñ\82Å\82È\82¢\82©\81A0\83x\81[\83X\82Å\82È\82¢
731                         return NULL;
732                 }
733                 DWORD needsize = 0;
734                 long dim[1];
735                 long cnt;
736                 // \83o\83b\83t\83@\82É\95K\97v\82È\83T\83C\83Y\82ð\8b\81\82ß\82é
737                 for(cnt = 0 ; cnt <= ub ; cnt++){
738                         CComVariant tmp;
739                         dim[0] = cnt;
740                         SafeArrayGetElement(pArray,dim,&tmp);
741                         if(tmp.ChangeType(VT_BSTR) != S_OK){
742                                 // \95\8e\9a\97ñ\82É\95Ï\8a·\95s\89Â\94\
743                                 return NULL;
744                         }
745                         needsize += WideCharToMultiByte(GetACP(),0,tmp.bstrVal,-1,NULL,0,NULL,NULL) + 1;
746                 }
747                 // \83o\83b\83t\83@\82ð\8am\95Û\82µ\93W\8aJ\82·\82é
748                 pBuf = new CHAR[needsize];
749                 LPSTR p = pBuf;
750                 for(cnt = 0 ; cnt <= ub ; cnt++){
751                         CComVariant tmp;
752                         dim[0] = cnt;
753                         SafeArrayGetElement(pArray,dim,&tmp);
754                         if(tmp.ChangeType(VT_BSTR) != S_OK){
755                                 // \95\8e\9a\97ñ\82É\95Ï\8a·\95s\89Â\94\
756                                 return NULL;
757                         }
758                         int sz = WideCharToMultiByte(GetACP(),0,tmp.bstrVal,-1,p,MAX_PATH,NULL,NULL);
759                         *(p + sz) = 0;
760                         p += sz;
761                 }
762                 *p = 0;
763                 return pBuf;
764         }
765         return NULL;
766 }
767
768 STDMETHODIMP CShell::EmptyRecycleBin(VARIANT dir)
769 {
770         CComVariant varDir;
771         LPCSTR pTarget = NULL;
772         CHAR szPath[MAX_PATH];
773         if(dir.vt == VT_NULL || dir.vt == VT_ERROR || dir.vt == VT_EMPTY){
774                 // \82·\82×\82Ä\91Î\8fÛ\82Æ\82·\82é
775                 pTarget = NULL;
776         }
777         if(varDir.ChangeType(VT_BSTR,&dir) == S_OK){
778                 // \93Á\92è\82Ì\83h\83\89\83C\83u\82ð\83^\81[\83Q\83b\83g\82·\82é
779                 WideCharToMultiByte(GetACP(),0,varDir.bstrVal,-1,szPath,MAX_PATH,NULL,NULL);
780                 pTarget = szPath;
781         }
782         else{
783                 // \95Ï\8a·\95s\89Â
784                 return DISP_E_TYPEMISMATCH;
785         }
786         SHEmptyRecycleBin(NULL,pTarget,(m_bConfirm?0:SHERB_NOCONFIRMATION) | (m_bSilent?(SHERB_NOPROGRESSUI|SHERB_NOSOUND ):0));
787         return S_OK;
788 }
789
790 STDMETHODIMP CShell::RecentDocs(VARIANT text)
791 {
792         CComVariant varText;
793         LPCSTR pTarget = NULL;
794         CHAR szPath[MAX_PATH];
795         if(text.vt == VT_NULL || text.vt == VT_ERROR || text.vt == VT_EMPTY){
796                 // \97\9a\97ð\82ð\83N\83\8a\83A\82·\82é
797                 pTarget = NULL;
798         }
799         if(varText.ChangeType(VT_BSTR,&text) == S_OK){
800                 // \93Á\92è\82Ì\83t\83@\83C\83\8b\82ð\92Ç\89Á\82·\82é
801                 WideCharToMultiByte(GetACP(),0,varText.bstrVal,-1,szPath,MAX_PATH,NULL,NULL);
802                 pTarget = szPath;
803         }
804         else{
805                 // \95Ï\8a·\95s\89Â
806                 return DISP_E_TYPEMISMATCH;
807         }
808         SHAddToRecentDocs(SHARD_PATH,pTarget);
809         return S_OK;
810 }
811
812 STDMETHODIMP CShell::SetMainWindow(VARIANT varUnk)
813 {
814         // \8aù\91\82Ì\83C\83\93\83^\81[\83t\83F\83C\83X\82Ì\89ð\95ú
815         if(m_pMainWindow){
816                 m_pMainWindow->Release();
817                 m_pMainWindow = NULL;
818         }
819         // \83C\83\93\83^\81[\83t\83F\83C\83X\82Ì\8eæ\93¾
820         CComVariant tmp;
821         if(tmp.ChangeType(VT_UNKNOWN,&varUnk) == S_OK){
822                 if(tmp.punkVal->QueryInterface(IID_IOverlappedWindow,(void**)&m_pMainWindow) == S_OK){
823                         return S_OK;
824                 }
825         }
826         return DISP_E_UNKNOWNINTERFACE;
827 }
828
829 STDMETHODIMP CShell::IsExist(VARIANT name, VARIANT *pVal)
830 {
831         CComVariant varName,varRet;
832         if(varName.ChangeType(VT_BSTR,&name) != S_OK){
833                 return DISP_E_TYPEMISMATCH;
834         }
835         CHAR szPath[MAX_PATH];
836         WideCharToMultiByte(GetACP(),0,varName.bstrVal,-1,szPath,MAX_PATH,NULL,NULL);
837         DWORD attr = GetFileAttributes(szPath);
838         if(attr != (DWORD)-1){
839                 if(attr & FILE_ATTRIBUTE_DIRECTORY)
840                         varRet = 2;
841                 else
842                         varRet = 1;
843         }
844         varRet.Detach(pVal);
845         return S_OK;
846 }