C++ - GetFinalPathNameByHandleW を 2000 でも使いたい その2

C++ - GetFinalPathNameByHandleW が 2000 でも使いたい

以前作った関数ですが。

1. VOLUME_NAME_GUID に非対応
2. FILE_NAME_OPENED に非対応
3. 時々へんてこなファイル名が返ってくることがある

というわけで作りなおしてみました。


まず、テスト用のコード

int _tmain(int argc, _TCHAR* argv[])
{
    wchar_t result[640];
    wchar_t     fn[640]=L"C:\PROGRA~1\INTERN~1\IEXPLORE. EXE";
    if(argc >=2)
        lstrcpyW(fn,argv[1]);
    HANDLE hFile = CreateFileW(
        fn,
         FILE_READ_ATTRIBUTES, /* desired access */
        0, /* share mode */
        NULL, /* security attributes */
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|
            FILE_FLAG_OPEN_REPARSE_POINT,
        NULL);

    _tsetlocale(LC_ALL, _T(""));
    GetFinalPathNameByHandle3(hFile,result,640,VOLUME_NAME_DOS);
    wprintf(L"VOLUME_NAME_DOS: %s\n",result);
    GetFinalPathNameByHandle3(hFile,result,640,VOLUME_NAME_NT);
    wprintf(L"VOLUME_NAME_NT: %s\n",result);
    GetFinalPathNameByHandle3(hFile,result,640,VOLUME_NAME_NONE);
    wprintf(L"VOLUME_NAME_NONE: %ws\n",result);
   GetFinalPathNameByHandle3(hFile,result,640,VOLUME_NAME_GUID);
    wprintf(L"VOLUME_NAME_GUID: %ws\n",result);
    GetFinalPathNameByHandle3(hFile,result,640,VOLUME_NAME_DOS
|FILE_NAME_OPENED);
    wprintf(L"VOLUME_NAME_DOS[O]: %s\n",result);
    GetFinalPathNameByHandle3(hFile,result,640,VOLUME_NAME_NT
|FILE_NAME_OPENED);
    wprintf(L"VOLUME_NAME_NT[O]: %s\n",result);
    GetFinalPathNameByHandle3(hFile,result,640,VOLUME_NAME_NONE
|FILE_NAME_OPENED);
    wprintf(L"VOLUME_NAME_NONE[O]: %ws\n",result);
   GetFinalPathNameByHandle3(hFile,result,640,VOLUME_NAME_GUID
|FILE_NAME_OPENED);
    wprintf(L"VOLUME_NAME_GUID[O]: %ws\n",result);
    CloseHandle(hFile);
    return 0;
}

Windows 2000向けのコード

__declspec(dllexport) DWORD WINAPI GetFinalPathNameByHandle3(
HANDLE hFile,
LPTSTR lpszFilePath,
DWORD  cchFilePath,
DWORD  dwFlags
){
  FILE_BOTH_DIR_INFORMATION xx;
  BYTE  *u8_Buffer = NULL;
  DWORD result = 0, eee = 0x80, sz, dsz,sz2 ,errorno = 0, fff = 0x80;
  wchar_t *szTemp = 0, *szTemp2 = 0,*szTemp4 = 0,*szTemp5 = 0;
  wchar_t *lfn = 0, *p;
  int i, j, r, tmpKind = dwFlags & 7;
  if(dwFlags & VOLUME_NAME_GUID) tmpKind = VOLUME_NAME_DOS;
  if (hFile == INVALID_HANDLE_VALUE || hFile == ((HANDLE)(LONG_PTR)0)) {
    errorno = ERROR_INVALID_HANDLE;
    goto error;
  }
  if ((dwFlags>15)  ||  ((dwFlags&VOLUME_NAME_NONE)
    &&(dwFlags&(VOLUME_NAME_NT|VOLUME_NAME_GUID)))) {
    errorno = ERROR_INVALID_PARAMETER;
    goto error;
  }
  u8_Buffer=(BYTE*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,eee);
  do{
    // NtQueryObject(hFile,  ObjectNameInformation, u8_Buffer, eee, &j);
    _asm{
      lea eax,j
      push eax
      push eee
      push u8_Buffer
      push ObjectNameInformation
      push hFile
      call GP2  
      mov i,eax
    }
    if(i & 0x80000000) {
      eee<<=1;
      u8_Buffer =(BYTE*)HeapReAlloc(GetProcessHeap(),0,u8_Buffer ,eee);
    } else{
      eee=j;
      break;
    }
  }while((i & 0x80000000) && (eee < 0x8000));
  if(i & 0x800000000) {
    errorno = ERROR_INVALID_HANDLE;
    goto error;
  }
  UNICODE_STRING *u = (UNICODE_STRING*)u8_Buffer;
  dsz = GetLogicalDriveStrings(0,szTemp)*2;
  szTemp = (wchar_t*)HeapAlloc(GetProcessHeap()
,HEAP_ZERO_MEMORY,dsz);   if (GetLogicalDriveStrings(dsz, szTemp)){       lfn = (wchar_t*)HeapAlloc(GetProcessHeap()
,HEAP_ZERO_MEMORY,1024);       p=szTemp;       if (result = ffx(L"\\Device\\Mup", u->Buffer, L"\\\\?\\UNC"
,VOLUME_NAME_DOS, 1024,lfn)){       } else if (result = ffx(L"\\Device\\LanmanRedirector"
, u->Buffer, L"\\\\?\\UNC",VOLUME_NAME_DOS, 1024,lfn)){       } else do{         p[2]=0;         szTemp2 = (wchar_t*)HeapAlloc(GetProcessHeap()
,HEAP_ZERO_MEMORY,fff);//Aloc4         if(szTemp2){           do{             r = QueryDosDeviceW(p,szTemp2, fff);             if(r==0) {               fff<<=1;               szTemp2 =(wchar_t*)HeapReAlloc(GetProcessHeap()
,0,szTemp2 ,fff);               if(fff >0x8000){                 errorno = ERROR_NOT_ENOUGH_MEMORY;                 result = 0;                 goto error;               }             }           }while(r==0);           if (result = ffx(szTemp2, u->Buffer, p,VOLUME_NAME_DOS
, eee,lfn)){             HeapFree(GetProcessHeap(),0,szTemp2); ///Free4             szTemp2 = 0;             break;           }           HeapFree(GetProcessHeap(),0,szTemp2);           szTemp2 = 0;         }         p+=4;       }while(*p);       if(*p==0){         errorno = ERROR_INVALID_PARAMETER;         goto error;       }       int pz = 0;       if(!wcsncmp(lfn,L"\\\\?\\UNC",7)) {         pz = 6;               } else if(!wcsncmp(lfn,L"\\\\.\\",4)) {         pz = 4;       }       lstrcpyW(lfn,lfn+pz);       if(pz == 6){         *lfn = '\\';       }       sz = GetLongPathNameW(lfn, 0, 0)*2;       sz2 = GetCurrentDirectoryW(0,lfn)*2;       if (sz < sz2) {sz= sz2;}       sz+= 128;       if (sz < 1024) {sz= 1024;}       szTemp4 = (wchar_t*)HeapAlloc(GetProcessHeap()
,HEAP_ZERO_MEMORY,sz);       szTemp5 = (wchar_t*)HeapAlloc(GetProcessHeap()
,HEAP_ZERO_MEMORY,sz);       if( (dwFlags & FILE_NAME_OPENED)==0) {         GetLongPathNameW(lfn,szTemp4, sz);         int k = (lstrlenW(szTemp4)-lstrlenW(lfn))*2;         if(k > 0) {           if(*(int*)lfn == 0x5c005c){             lstrcpyW(szTemp4,szTemp4 + 1);             lstrcpyW(lfn,lfn + 1);           } else if(dwFlags & (VOLUME_NAME_NONE | VOLUME_NAME_NT)) {             lstrcpyW(szTemp4,szTemp4 + 2);             lstrcpyW(lfn,lfn + 2);           }           u =(UNICODE_STRING *)HeapReAlloc(GetProcessHeap()
,0,u8_Buffer ,eee + k); ///Aloc           u->MaximumLength += k;           u->Buffer = (PWSTR)u+4;           u8_Buffer =(BYTE*)u;         }       } else {         if(dwFlags & (VOLUME_NAME_NONE | VOLUME_NAME_NT)) {           lstrcpyW(lfn,lfn + 2);         }         lstrcpyW(szTemp4, lfn);       } //      printf("LFN1:%ws\n",szTemp4); //      printf("LFN2:%ws\n",lfn);       if(tmpKind == VOLUME_NAME_NT && *szTemp4) {         p = wcsstr(u->Buffer, lfn);         if(p) {           lstrcpyW(p,szTemp4);         }         lstrcpyW(szTemp5,u->Buffer);         goto success;       } else {         szTemp2 = (wchar_t*)HeapAlloc(GetProcessHeap()
,HEAP_ZERO_MEMORY,fff);         GetLogicalDriveStrings(dsz, szTemp);         p=szTemp;         do{           int r;           p[2]=0;           do{             r = QueryDosDeviceW(p,szTemp2, fff);             if(r==0) {               fff<<=1;               szTemp2 =(wchar_t*)HeapReAlloc(GetProcessHeap()
,0,szTemp2 ,fff);               if(fff >0x8000){                 errorno = ERROR_NOT_ENOUGH_MEMORY;                 result = 0;                 goto error;               }             }           }while(r==0);           SetLastError(0);           if (result = ffx(szTemp2, u->Buffer, p,tmpKind, sz
,szTemp5)){             p=wcsstr(szTemp5, lfn);             if(!lstrcmpW(p, lfn)){               lstrcpy(p, szTemp4);             }             if(dwFlags & VOLUME_NAME_GUID) {               lstrcpyW(szTemp4+1, szTemp5);               *szTemp4=szTemp4[4];               szTemp4[4]=0;            GetVolumeNameForVolumeMountPointW(szTemp4+1
,szTemp5,sz);               szTemp4[4]=*szTemp4;               lstrcatW(szTemp5,szTemp4+4);               goto success;             }             if((dwFlags & 7)==0) {               lstrlcpyW(szTemp5,4);               *(int*)szTemp5=0x5c005c;               *(int*)(szTemp5+2)=0x5c003f;             }             goto success;           }           p+=4;         }while(*p);         if(dwFlags & VOLUME_NAME_GUID) {           errorno = ERROR_PATH_NOT_FOUND;           goto error;         }         SetLastError(0);         if (result = ffx(L"\\Device\\Mup", u->Buffer,
L"\\\\?\\UNC",tmpKind,sz ,szTemp5)){           p=wcsstr(szTemp5, lfn);           if(!lstrcmpW(p, lfn)){               lstrcpy(p, szTemp4);           }           goto success;         }         if (result = ffx(L"\\Device\\LanmanRedirector", u->Buffer
, L"\\\\?\\UNC",tmpKind,sz,szTemp5)){           p=wcsstr(szTemp5, lfn);           if(!lstrcmpW(p, lfn)){               lstrcpy(p, szTemp4);           }           goto success;         }              }   success:     result = lstrlenW(szTemp5);     if(cchFilePath>= result){       lstrcpyW(lpszFilePath,szTemp5);       if(lfn)         HeapFree(GetProcessHeap(),0,lfn);       if(szTemp)         HeapFree(GetProcessHeap(),0,szTemp);       if(szTemp2)         HeapFree(GetProcessHeap(),0,szTemp2);       if(u8_Buffer)         HeapFree(GetProcessHeap(),0,u8_Buffer);       if(szTemp4)         HeapFree(GetProcessHeap(),0,szTemp4);       if(szTemp5)         HeapFree(GetProcessHeap(),0,szTemp5);       SetLastError(0);       return result;     } else {       errorno = ERROR_NOT_ENOUGH_MEMORY;     }   error:   if(lpszFilePath){     *lpszFilePath = 0;   }   if(lfn)     HeapFree(GetProcessHeap(),0,lfn);//Free3   if(szTemp)     HeapFree(GetProcessHeap(),0,szTemp);   if(szTemp2)     HeapFree(GetProcessHeap(),0,szTemp2);   if(szTemp4)     HeapFree(GetProcessHeap(),0,szTemp4);   if(u8_Buffer)     HeapFree(GetProcessHeap(),0,u8_Buffer);   if(szTemp5)     HeapFree(GetProcessHeap(),0,szTemp5);   SetLastError(errorno);   if(errorno == ERROR_NOT_ENOUGH_MEMORY)     return result;   else     return 0;   } else {     SetLastError(ERROR_INVALID_PARAMETER);     return 0;   } }

テスト結果

DOS: \\?\C:\Program Files\Internet Explorer\IEXPLORE.EXE(0)
NT: \Device\HarddiskVolume1\Program Files\Internet Explorer\IEXPLORE.EXE(0)
NONE: \Program Files\Internet Explorer\IEXPLORE.EXE(0)
GUID: \\?\Volume{085d09a1-433b-11dc-8967-806d6172696f}\Program Files\Internet Ex
plorer\IEXPLORE.EXE(0)

DOS[O]: \\?\C:\PROGRA~1\INTERN~1\IEXPLORE.EXE(0)

NT[O]: \Device\HarddiskVolume1\PROGRA~1\INTERN~1\IEXPLORE.EXE(0)
NONE[O]: \PROGRA~1\INTERN~1\IEXPLORE.EXE(0)
GUID[O]: \\?\Volume{085d09a1-433b-11dc-8967-806d6172696f}\PROGRA~1\INTERN~1\IEXPLOR
E.EXE(0)

・ω・ よさそうですね

おすすめ

3件のフィードバック

  1. Windows 2000 Warrior より:

    I think this function : GetFinalPathNameByHandleW
    responsible for starting office 2010 , it’s right ?

  2. 黒翼猫 より:

    >>1
    No, another request

  3. Thomas より:

    Thanks for looking into it (o˘◡˘o)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です