LPWSTR SH_FormatFileSizeWithBytes(const PULARGE_INTEGER lpQwSize, LPWSTR pwszResult, UINT cchResultMax) { /* Format bytes in KBs, MBs etc */ if (StrFormatByteSizeW(lpQwSize->QuadPart, pwszResult, cchResultMax) == NULL) return NULL; /* If there is less bytes than 1KB, we have nothing to do */ if (lpQwSize->QuadPart < 1024) return pwszResult; /* Concate " (" */ UINT cchWritten = wcslen(pwszResult); LPWSTR pwszEnd = pwszResult + cchWritten; size_t cchRemaining = cchResultMax - cchWritten; StringCchCopyExW(pwszEnd, cchRemaining, L" (", &pwszEnd, &cchRemaining, 0); /* Write formated bytes count */ cchWritten = SH_FormatByteSize(lpQwSize->QuadPart, pwszEnd, cchRemaining); pwszEnd += cchWritten; cchRemaining -= cchWritten; /* Copy ")" to the buffer */ StringCchCopyW(pwszEnd, cchRemaining, L")"); return pwszResult; }
BOOL CFileDefExt::GetFileTimeString(LPFILETIME lpFileTime, LPWSTR pwszResult, UINT cchResult) { FILETIME ft; SYSTEMTIME st; if (!FileTimeToLocalFileTime(lpFileTime, &ft) || !FileTimeToSystemTime(&ft, &st)) return FALSE; size_t cchRemaining = cchResult; LPWSTR pwszEnd = pwszResult; int cchWritten = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, pwszEnd, cchRemaining); if (cchWritten) --cchWritten; // GetDateFormatW returns count with terminating zero else ERR("GetDateFormatW failed\n"); cchRemaining -= cchWritten; pwszEnd += cchWritten; StringCchCopyExW(pwszEnd, cchRemaining, L", ", &pwszEnd, &cchRemaining, 0); cchWritten = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, pwszEnd, cchRemaining); if (cchWritten) --cchWritten; // GetTimeFormatW returns count with terminating zero else ERR("GetTimeFormatW failed\n"); TRACE("result %s\n", debugstr_w(pwszResult)); return TRUE; }
UINT SH_FormatByteSize(LONGLONG cbSize, LPWSTR pwszResult, UINT cchResultMax) { /* Write formated bytes count */ INT cchWritten = SH_FormatInteger(cbSize, pwszResult, cchResultMax); if (!cchWritten) return 0; /* Copy " bytes" to buffer */ LPWSTR pwszEnd = pwszResult + cchWritten; size_t cchRemaining = cchResultMax - cchWritten; StringCchCopyExW(pwszEnd, cchRemaining, L" ", &pwszEnd, &cchRemaining, NULL); cchWritten = LoadStringW(shell32_hInstance, IDS_BYTES_FORMAT, pwszEnd, cchRemaining); cchRemaining -= cchWritten; return cchResultMax - cchRemaining; }
// 1つ目の引数だけファイルとして扱い、実行する。 // // コマンドは こんな感じで連結されます。 // exe linkpath linkarg cmdarg2 cmdarg3 cmdarg4 ... // static HRESULT HookAndExecute(int show) { int argc = 0; LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); if(!argv) { return HresultFromLastError(); } if(argc <= 1) { char buffer [256]; LoadStringA(GetModuleHandleA(NULL), IDS_USAGE, buffer, 256); MessageBoxA(NULL, buffer ,"gdi++", MB_OK|MB_ICONINFORMATION); LocalFree(argv); return S_OK; } int i; size_t length = 1; for(i=2; i<argc; i++) { length += wcslen(argv[i]) + 3; } LPWSTR cmdline = (WCHAR*)calloc(sizeof(WCHAR), length); if(!cmdline) { LocalFree(argv); return E_OUTOFMEMORY; } LPWSTR p = cmdline; *p = L'\0'; for(i=2; i<argc; i++) { const bool dq = !!wcschr(argv[i], L' '); if (dq) { *p++ = '"'; length--; } StringCchCopyExW(p, length, argv[i], &p, &length, STRSAFE_NO_TRUNCATION); if (dq) { *p++ = '"'; length--; } *p++ = L' '; length--; } *CharPrevW(cmdline, p) = L'\0'; WCHAR file[MAX_PATH], dir[MAX_PATH]; GetCurrentDirectoryW(_countof(dir), dir); StringCchCopyW(file, _countof(file), argv[1]); if(PathIsRelativeW(file)) { PathCombineW(file, dir, file); } else { WCHAR gdippDir[MAX_PATH]; GetModuleFileNameW(NULL, gdippDir, _countof(gdippDir)); PathRemoveFileSpec(gdippDir); // カレントディレクトリがgdi++.exeの置かれているディレクトリと同じだったら、 // 起動しようとしているEXEのフルパスから抜き出したディレクトリ名をカレント // ディレクトリとして起動する。(カレントディレクトリがEXEと同じ場所である // 前提で作られているアプリ対策) if (wcscmp(dir, gdippDir) == 0) { StringCchCopyW(dir, _countof(dir), argv[1]); PathRemoveFileSpec(dir); } } LocalFree(argv); argv = NULL; #ifdef _DEBUG if((GetAsyncKeyState(VK_CONTROL) & 0x8000) && MessageBoxW(NULL, cmdline, NULL, MB_YESNO) != IDYES) { free(cmdline); return NOERROR; } #endif LPITEMIDLIST pidl = NULL; HRESULT hr; //fileのアイテムIDリストを取得 hr = _SHILCreateFromPath(file, &pidl, NULL); if(SUCCEEDED(hr) && pidl) { //SEE_MASK_INVOKEIDLISTを使うと //explorerでクリックして起動したのと同じ動作になる SHELLEXECUTEINFOW sei = { sizeof(SHELLEXECUTEINFOW) }; sei.fMask = SEE_MASK_INVOKEIDLIST | SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_DOENVSUBST | SEE_MASK_WAITFORINPUTIDLE; sei.hwnd = GetDesktopWindow(); sei.lpParameters = cmdline; sei.lpDirectory = dir; sei.nShow = show; sei.lpIDList = pidl; //ShellExecuteExWが内部で呼び出すCreateProcessWをフックして //HookChildProcesses相当の処理を行う DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)ORIG_CreateProcessW, IMPL_CreateProcessW); hr = DetourTransactionCommit(); if(hr == NOERROR) { if(ShellExecuteExW(&sei)) { hr = S_OK; } else { hr = HresultFromLastError(); } } DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)ORIG_CreateProcessW, IMPL_CreateProcessW); DetourTransactionCommit(); } if(pidl) _SHFree(pidl); free(cmdline); return hr; }
BOOL ProcessPlugIn( NDAS_LOGICALUNIT_ADDRESS Address, int argc, TCHAR** argv) { if (argc < 1) { usage(); return FALSE; } PNDAS_LOGICALUNIT_DESCRIPTOR logicalUnitDescriptor = NULL; if (0 == lstrcmpi(_T("filedisk"), argv[0])) { if (argc != 4 ) { usage(); return FALSE; } LPCTSTR filePath = argv[1]; // const WCHAR FileNamePrefix[] = L"\\\\?\\"; const WCHAR FileNamePrefix[] = L"\\??\\"; #ifdef UNICODE DWORD fileFullPathLength = GetFullPathName(filePath, 0, NULL, NULL); if (0 == fileFullPathLength) { _tprintf(_T("Error: GetFullPathName failed!\n")); return FALSE; } fileFullPathLength += RTL_NUMBER_OF(FileNamePrefix); LPWSTR fileFullPathBuffer = static_cast<LPWSTR>(HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, fileFullPathLength * sizeof(WCHAR))); if (!fileFullPathBuffer) { _tprintf(_T("Error: Out of memory!\n")); SetLastError(ERROR_OUTOFMEMORY); return FALSE; } LPWSTR fileFullPath = NULL; size_t remainingLength = 0; StringCchCopyExW( fileFullPathBuffer, fileFullPathLength, FileNamePrefix, &fileFullPath, &remainingLength, STRSAFE_IGNORE_NULLS); GetFullPathName( filePath, static_cast<DWORD>(remainingLength), fileFullPath, NULL); #else C_ASSERT(FALSE && "not implemented"); #endif _tprintf(_T("File Name=%s\n"), fileFullPathBuffer); _tprintf(_T("Length=%d bytes\n"), fileFullPathLength * sizeof(WCHAR)); DWORD descriptorLength = FIELD_OFFSET(FILEDISK_DESCRIPTOR, FilePath) + fileFullPathLength * sizeof(WCHAR); PFILEDISK_DESCRIPTOR descriptor = static_cast<PFILEDISK_DESCRIPTOR>( HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, descriptorLength)); if (NULL == descriptor) { _tprintf(_T("Error: Out of memory!\n")); HeapFree(GetProcessHeap(), 0, fileFullPathBuffer); SetLastError(ERROR_OUTOFMEMORY); return FALSE; } descriptor->Header.Version = sizeof(NDAS_LOGICALUNIT_DESCRIPTOR); descriptor->Header.Size = descriptorLength; descriptor->Header.Address = Address; descriptor->Header.Type = NdasExternalType; descriptor->Header.ExternalTypeGuid = NDASPORT_FILEDISK_TYPE_GUID; descriptor->LogicalBlockAddress.QuadPart = 750LL * 1024LL * 1024LL * 1024LL / 512LL; descriptor->BytesPerBlock = 512; descriptor->FileDiskFlags = FILEDISK_FLAG_USE_SPARSE_FILE; CopyMemory( descriptor->FilePath, fileFullPathBuffer, fileFullPathLength * sizeof(WCHAR)); HeapFree(GetProcessHeap(), 0, fileFullPathBuffer); logicalUnitDescriptor = reinterpret_cast<PNDAS_LOGICALUNIT_DESCRIPTOR>( static_cast<PFILEDISK_DESCRIPTOR>(descriptor)); } else if (0 == lstrcmpi(_T("ramdisk"), argv[0])) { return TRUE; } else if (0 == lstrcmpi(_T("ndasdlu"), argv[0])) { logicalUnitDescriptor = ProcessPlugIn_Dlu(Address, argc - 1, argv + 1); if (NULL == logicalUnitDescriptor) { return FALSE; } } else { // // Reserve 2MB from the end // LARGE_INTEGER logicalBlockAddress; logicalBlockAddress.QuadPart = -2 * 1024 * 1024 / 512; NDAS_DEVICE_IDENTIFIER ndasDeviceIdentifier; BOOL success = ParseNdasDeviceId(argv[0], &ndasDeviceIdentifier); if (!success) { _tprintf(_T("Error: NDAS Device Identifier is invalid.\n\n")); usage(); return FALSE; } ACCESS_MASK accessMode; if (0 == lstrcmpi(_T("ro"), argv[1])) { accessMode = GENERIC_READ; } else if (0 == lstrcmpi(_T("rw"), argv[1])) { accessMode = GENERIC_READ | GENERIC_WRITE; } else { _tprintf(_T("Error: Access mode is invalid or not specified.\n\n")); usage(); return FALSE; } if (argc > 2 && 0 == lstrcmpi(_T("noreserve"), argv[2])) { logicalBlockAddress.QuadPart = 0; _tprintf(_T("No reserve mode\n")); } #ifdef _DEBUG _tprintf(_T("(%d,%d,%d) %02X-%02X-%02X-%02X-%02X-%02X %d\n"), Address.PathId, Address.TargetId, Address.Lun, ndasDeviceIdentifier.Identifier[0], ndasDeviceIdentifier.Identifier[1], ndasDeviceIdentifier.Identifier[2], ndasDeviceIdentifier.Identifier[3], ndasDeviceIdentifier.Identifier[4], ndasDeviceIdentifier.Identifier[5], ndasDeviceIdentifier.UnitNumber); #endif logicalUnitDescriptor = NdasPortCtlBuildNdasAtaDeviceDescriptor( Address, 0, &ndasDeviceIdentifier, 0, 0, accessMode, 0, &logicalBlockAddress); if (NULL == logicalUnitDescriptor) { _tprintf(_T("Error: Out of memory!\n")); return FALSE; } } _ASSERT(NULL != logicalUnitDescriptor); XTL::AutoProcessHeap logicalUnitDescriptorPtr = logicalUnitDescriptor; XTL::AutoFileHandle handle = NdasPortCtlCreateControlDevice(GENERIC_READ | GENERIC_WRITE); if (handle.IsInvalid()) { ErrorHolder lastError; _tprintf(_T("Opening NDAS Port device file failed.\n")); _tprintf(_T("Error %u (0x%X): %hs\n"), lastError.GetCode(), lastError.GetCode(), lastError.GetDescriptionA()); return FALSE; } BOOL success = NdasPortCtlGetPortNumber( handle, &logicalUnitDescriptor->Address.PortNumber); if (!success) { ErrorHolder lastError; _tprintf(_T("Getting the port number failed.\n")); _tprintf(_T("Error %u (0x%X): %hs\n"), lastError.GetCode(), lastError.GetCode(), lastError.GetDescriptionA()); return FALSE; } success = NdasPortCtlPlugInLogicalUnit( handle, logicalUnitDescriptor); if (!success) { ErrorHolder lastError; _tprintf(_T("PlugIn failed.\n")); _tprintf(_T("Error %u (0x%X): %hs\n"), lastError.GetCode(), lastError.GetCode(), lastError.GetDescriptionA()); return FALSE; } return TRUE; }