國慶小禮物,微軟"查詢目標的實現”附帶三個小工具 (6千字)
一直使用VC++6.0,很希望自己實現一個外掛能開啟包含VC中開啟檔案的資料夾。以前用ShellExecuteEx實現過,但效果不理想,原因有1,同一個資料夾會開啟多個例項,2.目標檔案在資料夾中不會被選中。後來在網上發現可以透過執行explore /select 來完成上述功能,但還不夠理想,原因是,如果資料夾已被開啟,目標檔案在資料夾中不會被選中。
我看了不少有關Windows Shell的程式設計方面的書也沒有找到答案。
在Windows桌面上的圖示,右單擊,選“屬性”,按“查詢目標”可以非常理想的完成上述功能。但是它是怎樣實現的呢?
先開啟屬性對話方塊,在SoftICE下下萬能斷點hmemcpy, 經過幾次F12, 來到Shell32.dll中,記下其虛擬地址,用IDA開啟Shell32.dll:
.text:7FD04025 CreateShortcutPage proc near CODE XREF: sub_7FD05C24+159p
.text:7FD04025
.text:7FD04025 var_34 = PROPSHEETPAGEA ptr -34h
.text:7FD04025 var_4 = dword ptr -4
.text:7FD04025 arg_0 = dword ptr 8
.text:7FD04025 lpString2 = dword ptr 0Ch
.text:7FD04025 arg_8 = dword ptr 10h
.text:7FD04025 arg_C = dword ptr 14h
.text:7FD04025
.text:7FD04025 push ebp
.text:7FD04026 mov ebp, esp
.text:7FD04028 sub esp, 34h
.text:7FD0402B push esi
.text:7FD0402C push edi
.text:7FD0402D push [ebp+lpString2]
.text:7FD04030 call IsLnkFile
.text:7FD04035 test eax, eax
.text:7FD04037 jz loc_7FD040F6
.text:7FD0403D lea eax, [ebp+var_4]
.text:7FD04040 push eax
.text:7FD04041 push offset dword_7FCBCE50
.text:7FD04046 push 0
.text:7FD04048 call sub_7FCBCA41
.text:7FD0404D test eax, eax
.text:7FD0404F jl loc_7FD040F6
.text:7FD04055 push 220h uBytes
.text:7FD0405A push 40h uFlags
.text:7FD0405C call ds:LocalAlloc
.text:7FD04062 mov esi, eax
.text:7FD04064 test esi, esi
.text:7FD04066 jz loc_7FD040ED
.text:7FD0406C mov eax, ds:hModule
.text:7FD04071 push 104h iMaxLength
.text:7FD04076 push [ebp+lpString2] lpString2
.text:7FD04079 mov [ebp+var_34.hInstance], eax
.text:7FD0407C lea eax, [esi+18h]
.text:7FD0407F mov [ebp+var_34.dwSize], 30h
.text:7FD04086 push eax lpString1
.text:7FD04087 mov [ebp+var_34.dwFlags], 80h
.text:7FD0408E mov dword ptr [ebp+var_34.anonymous_0], 1040
.text:7FD04095 mov [ebp+var_34.pfnDlgProc], offset PropDlgProc 注意這裡!
.text:7FD0409C mov [ebp+var_34.pfnCallback], offset loc_7FD03FFF
.text:7FD040A3 mov [ebp+var_34.lParam], esi
.text:7FD040A6 call ds:lstrcpynA
.text:7FD040AC mov eax, [ebp+arg_0]
.text:7FD040AF or dword ptr [esi+14h], 0FFFFFFFFh
.text:7FD040B3 mov [esi], eax
.text:7FD040B5 mov eax, [ebp+var_4]
.text:7FD040B8 mov [esi+4], eax
.text:7FD040BB lea eax, [ebp+var_34]
.text:7FD040BE push eax LPCPROPSHEETPAGEA
.text:7FD040BF call ds:CreatePropertySheetPageA
.text:7FD040C5 mov edi, eax
.text:7FD040C7 test edi, edi
.text:7FD040C9 jz short loc_7FD040E6
.text:7FD040CB push [ebp+arg_C]
.text:7FD040CE push edi
.text:7FD040CF call [ebp+arg_8]
.text:7FD040D2 test eax, eax
.text:7FD040D4 jz short loc_7FD040DF
.text:7FD040D6 push 1
.text:7FD040D8 pop eax
.text:7FD040D9
.text:7FD040D9 loc_7FD040D9: CODE XREF: CreateShortcutPage+D3j
.text:7FD040D9 pop edi
.text:7FD040DA pop esi
.text:7FD040DB leave
.text:7FD040DC retn 10h
.text:7FD040DF ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
.text:7FD040DF
.text:7FD040DF loc_7FD040DF: CODE XREF: CreateShortcutPage+AFj
.text:7FD040DF push edi HPROPSHEETPAGE
.text:7FD040E0 call ds:DestroyPropertySheetPage
.text:7FD040E6
.text:7FD040E6 loc_7FD040E6: CODE XREF: CreateShortcutPage+A4j
.text:7FD040E6 push esi hMem
.text:7FD040E7 call ds:LocalFree
.text:7FD040ED
.text:7FD040ED loc_7FD040ED: CODE XREF: CreateShortcutPage+41j
.text:7FD040ED mov eax, [ebp+var_4]
.text:7FD040F0 push eax
.text:7FD040F1 mov ecx, [eax]
.text:7FD040F3 call dword ptr [ecx+8]
.text:7FD040F6
.text:7FD040F6 loc_7FD040F6: CODE XREF: CreateShortcutPage+12j
.text:7FD040F6 CreateShortcutPage+2Aj
.text:7FD040F6 xor eax, eax
.text:7FD040F8 jmp short loc_7FD040D9
.text:7FD040F8 CreateShortcutPage endp
經過整整4天的艱苦挖掘,得到了後面的原始碼。這些原始碼和作者(微軟)手裡的因該是完全等價的。說實在的,裡面有些東西是值得學習的。從中我們可以發現問題的關鍵在於SHDOCVW.DLL中的SHGetIDispatchForFolder這個未公開函式,我曾試著在google搜尋它,發現只有一個不能開啟的網站上有它。雖然我極其佩服微軟,但從這個例子中我們可以看出微軟的技術壟斷的痕跡。
為了幹這活,我還做了一個工具CLSIDSEE, 它可以從4個dword查詢CLS_ID, ProgID...,用於破解COM程式碼非常有用。
用這些程式碼我還做了一個VC外掛,實現開始提到的功能,我個人覺得非常有用。
用這些程式碼我還做了一個Shell擴充套件,將查詢目標這個功能直接放到桌面圖示右單擊的選單中,我也覺得非常有用。
這三個小工具我會放到CrackABC的FTP上。
1. 原始碼(1)
int GetNumberOfSelected(HGLOBAL hMem)
{
int ret = 0;
int* pInt;
if ((pInt = (int*)GlobalLock(hMem)) != NULL) {
ret = *pInt;
GlobalUnlock(hMem);
}
return ret;
}
BOOL _7FD0276A(DWORD* vp, DWORD var)
{
if (var <= vp[0])
return SHELL32_25((BYTE*)vp + vp[1], (BYTE*)vp + vp[var + 2]);
return FALSE;
}
LPCITEMIDLIST GetPIDL(HGLOBAL hGlobal, int var)
{
LPVOID vp;
if ((vp = GlobalLock(hGlobal)) != NULL) {
LPCITEMIDLIST pidl = _7FD0276A(vp, var);
GlobalUnlock(hGlobal);
return pidl;
}
return NULL;
}
BOOL GetTargetInfo(HGLOBAL hGlobal, int var, char FilePath[MAX_PATH], WIN32_FIND_DATA* lpFindData)
{
LPCITEMIDLIST pidl;
PathName[0] = '\0';
if ((pidl = GetPIDL(hGlobal, var)) != NULL) {
if (SHGetPathFromIDList(pidl, FilePath)) {
if (lpFindData) {
if ((hFff = FindFirstFile(FilePath, lpFindData)) == INVALID_HANDLE_VALUE)
memset(lpFindData, 0, sizeof(WIN32_FIND_DATA));
else
CloseHandle(hFff);
}
SHELL32_155_FreePidl(pidl);
return TRUE;
}
else {
SHELL32_155_FreePidl(pidl);
return FALSE;
}
}
return FALSE;
}
int CreatePropDialog(p1, pfn, IDataObject* pDataObj)
{
FORMATETC formatetc;
STGMEDIUM medium;
PROPSHEETPAGE psp;
HLOCAL hLocal;
HGLOBAL hGlobal;
WIN32_FIND_DATA ffd;
HPROPSHEETPAGE hPsp;
char PathName[MAX_PATH];
BOOL var_4;
int var_8;
formatetc.lindex = -1;
formatetc.cfFormat = gcfFormat;
formatetc.ptd = 0;
formatetc.dwAspect = 1;
formatetc.tymed = TYMED_HGLOBAL;
var_4 = FALSE;
var_8 = 0;
if (FAILED(pDataObj->GetData(&formatetc, &medium)))
return FALSE;
PathName[0] = 0;
psp.hInstance = ghModule;
psp.dwSize = 952; //NOT sizeof(psp); !!!
psp.dwFlags = PSP_USECALLBACK; //0x80;
psp.pfnCallback = PropCallback;
var_2a0 = 1;
var_3a8 = 0;
var_34 = 0;
var_30 = 0;
hGlobal = medium.hGlobal;
if (hGlobal) {
hLocal = LocalAlloc(LPTR, GlobalSize(hGlobal));
if (hLocal)
memmove(hLocal, hGlobal, GlobalSize(hGlobal));
}
else
hLocal = NULL;
if (GetNumberOfSelected(hGlobal) == 1) { // else 7fd05dd5
if (GetTargetInfo(hGlobal, 0, &PathName, &ffd)) { // else 7fd05d9f
psp.pfnDlgProc = ConventionalDlgProc;
psp.pResource = MAKEINTRESOURCE(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY? 1044 : 1041);
if ((hPsp = CreatePropertySheetPage(&psp)) != NULL) { // else loc_7FD05D9F
if (pfn(hPsp, p1)) { // else loc_7FD05E07
var_4 = 1;
if (CreateShortcutPage(hGlobal, &PathName, pfn, p1))
var_8 = 2;
CreateVersionPage(&PathName, pfn, p1);
}
else // loc_7FD05E07
DestroyPropertySheetPage(hPsp);
}
}
}
else { // loc_7FD05DD5
psp.pResource = MAKEINTRESOURCE(1043);
psp.pfnDlgProc = MultiSelDlgProc;
if ((hPsp = CreatePropertySheetPage(&psp)) != NULL) { // else loc_7FD05D9F
if (pfn(hPsp, p1))
var_4 = 1;
else
DestroyPropertySheetPage(hPsp);
}
}
// loc_7FD05D9F
_7FCC6204(&medium);
if (!var_4 && hLocal)
LocalFree(hLocal);
return var_8;
}
BOOL IsLnkFile(char* PathName)
{
if (PathName)
return lstrcmpi(PathFindExtension(PathName), ".lnk") == 0;
return FALSE;
}
HRESULT CreateShellInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv)
{
CShellFactory* pCShellFactory;
HRESULT hr;
if (pUnknownOuter)
return CLASS_E_NOAGGREGATION;
pCShellFactory = new CShellFactory;
if (pCShellFactory == NULL)
return E_OUTOFMEMORY;
pCShellFactory->m_cRef = 1;
pCShellFactory->Init();
hr = pCShellFactory->CreateInstance(iid, ppv);
pCShellFactory->Release();
return hr;
}
typedef struct FindTargetData
{
HGLOBAL hGlobal; // 0
IShellLinkA* pIShellLink; // 4
int hDlgWnd; // 8
int dwc; // c
int dw10; // 10
int dw14; // 14
int dw18; // 18
char Path[MAX_PATH]; // 1c
};
BOOL CreateShortcutPage(HGLOBAL hGlobal, char PathName[MAX_MATH], pfn, p1)
{
PROPSHEETPAGE psp;
IShellLink* pIShellLink;
FindTargetData* pFtd;
HPROPSHEETPAGE hPsp;
if (IsLinkFile(PathName) &&
SUCCEEDED(CreateShellInstance(NULL, IID_IShellLink, &pIShellLink)))
{ // else loc_7FD040F6
pFtd = (FindTargetData*) LocalAlloc(LPTR, sizeof(FindTargetData));
if (pFtd != NULL) { // else loc_7FD040ED
psp.hInstance = ghModule;
psp.dwSize = sizeof(PROPSHEETPAGE);
psp.dwFlags = PSP_USECALLBACK;
psp.pResource = MAKEINTRESOURCE(1040);
psp.pfnDlgProc = ShortcutDlgProc;
psp.pfnCallback = CallbackProc;
psp.lParam = pFtd;
lstrcpyn(pFtd->Path, PathName, MAX_PATH);
pFtd->dw14 = -1;
pFtd->hGlobal = hGlobal;
pFtd->pIShellLink = pIShellLink;
if ((hPsp = CreatePropertySheetPage(&psp)) != NULL) {
if (pfn(hPsp, p1))
return TRUE;
DestroyPropertySheetPage(hPsp);
}
LocalFree(pFtd);
}
pObj->Release();
}
return FALSE;
}
#define IDC_
#define IDC_Name 0x66 // 名稱
#define IDC_StartLocation 0x3002 // 起始位置
#define IDC_Target 0x3302 // 目標
#define IDC_TargetType 0x3303 // 目標型別
#define IDC_TargetLocation 0x3309 // 目標位置
#define IDC_Shortcut 0x3404 // 快捷鍵
#define IDC_FindTarget 0x3406 // 查詢目標
#define IDC_ChangeIcon 0x3407 // 更改圖示
#define IDC_RunMode 0x3408 // 執行方式
BOOL CALLBACK ShortcutDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPPROPSHEETPAGE psp;
FindTargetData* pFtd;
LPNMHDR pnmh;
LPHELPINFO lphi;
pFtd = GetWindowLong(hWnd, DWL_USER);
switch (uMsg)
{
case WM_INITDIALOG:
psp = (LPPROPSHEETPAGE)lParam;
pFtd = psp->lParam;
SetWindowLong(hWnd, DWL_USER, pFtd);
pFtd->hDlgWnd = hWnd;
SendDlgItemMessage(hWnd, 0x3302/*ID for 目標*/, WM_LIMITTEXT, MAX_PATH - 1, 0);
COMCTL32_384(GetDlgItem(hWnd, 0x3302), 1);
SendDlgItemMessage(hWnd, 0x3002/*ID for 起始位置*/, EM_LIMITTEXT, MAX_PATH - 1, 0);
COMCTL32_384(GetDlgItem(hWnd, 0x3002), 1);
SendDlgItemMessage(hWnd, 0x3404/*ID for 快捷鍵*/, 0x403, 0xf, 6);
FindTargetInit(pFtd, 0);
return TRUE;
case WM_NOTIFY:
// If the message handler is in a dialog box procedure, you must use
// the SetWindowLong function with DWL_MSGRESULT to set a return value.
pnmh = (LPNMHDR) lParam;
if (pnmh->code != -202) {
if (pnmh->code == -201)
SetWindowLong(hwnd, DWL_MSGRESULT, !_7FD03BDA(pFtd));
}
else if (FAILED(_7FD03A38(pFtd)))
SetWindowLong(hWnd, DWL_MSGRESULT, 2);
return TRUE;
case WM_HELP:
lphi = (LPHELPINFO) lParam;
// HELP_WM_HELP:
// Displays the topic for the control identified
// by the hWndMain parameter in a pop-up window.
// HelpData:
// Address of an array of double word pairs.
// The first double word in each pair is a control identifier,
// and the second is a context identifier for a topic.
// The array must be terminated by a pair of zeros {0,0}.
// If you do not want to add Help to a particular control,
// set its context identifier to -1.
WinHelp(lphi->hItemHandle, NULL, HELP_WM_HELP, &HelpData);
break;
case WM_CONTEXTMENU:
WinHelp(lParam, NULL, HELP_CONTEXTMENU, &HelpData);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case 3002: // 起始位置
case 3302: // 目標
case 3404: // 快捷鍵
if (HIWORD(wParam) == 0x300) {
SendMessage(GetParent(hWnd), 0x468, hWnd, 0);
pFtd->dw10 = 1;
}
return TRUE;
case 3406: // 查詢目標
OnCmdFindTarget(pFtd);
return TRUE;
case 3407: // 更改圖示
if (OnCmdChangeIcon(pFtd))
pFtd->dw10 = TURE;
return TRUE;
case 3408: // 執行方式
if (HIWORD(wParam) == 1)
SendMessage(GetParent(hWnd), 0x468, hWnd, 0);
return TRUE;
}
return FALSE;
case 0x464:
SwitchToThisWindow(GetLastActivePopup(lParam), TRUE);
SetForegroundWindow(uMsg); // 奇怪!
break;
}
return FALSE;
}
2.原始碼(2)
int gdwShowCmds[] = {1, 7, 3};
void FindTargetInit(FindTargetData* pFtd, BOOL bFlag)
{
HRESULT hr;
OLECHAR wPath[MAX_PATH];
char Path[MAX_PATH];
char TargetPath[MAX_PATH];
char Msg[MAX_PATH];
SHFILEINFO ShellFileInfo;
SHDWORD ShDw;
WORD Hotkey;
int ShowCmd;
ITEMIDLIST* pidl;
IPersistFile* pIPersistFile;
if (!bFlag &&
SUCCEEDED(pFtd->pIShellLink->QueryInterface(IID_IPersistFile, &pIPersistFile))
{ // else loc_7FD032B3
SHELL32_163(wPath, &pFtd->dw18);
hr = pIPersistFile->Load(wPath, STGM_DIRECT);
pIPersistFile->Release();
if (FAILED(hr)) {
LoadString(ghModule, 4216/*ID for 不是有效的快捷方式。*/, &Msg, MAX_PATH);
SetDlgItemText(pFtd->hDlgWnd, 0x3303/*ID for "目標型別"*/, Msg);
_7FD031BF(pFtd->hDlgWnd);
return;
}
}
//loc_7FD032B3
if (pFtd->pIShellLink->b7d & FILE_ATTRIBUTE_DIRECTORY) {
GetTargetIcon(pFtd, 0);
GetTargetName(pFtd->hGlobal, 0, &Msg);
SetDlgItemText(pFtd->hDlgWnd, 0x66/*ID for 圖示旁邊的名稱*/, &Msg);
EnableWindow(GetDlgItem(pFtd->hDlgWnd, 0x3012/*ID for*/), FALSE);
EnableWindow(GetDlgItem(pFtd->hDlgWnd, 0x3302/*ID for*/), FALSE);
EnableWindow(GetDlgItem(pFtd->hDlgWnd, 0x3002/*ID for*/), FALSE);
EnableWindow(GetDlgItem(pFtd->hDlgWnd, 0x3404/*ID for*/), FALSE);
EnableWindow(GetDlgItem(pFtd->hDlgWnd, 0x3408/*ID for*/), FALSE);
EnableWindow(GetDlgItem(pFtd->hDlgWnd, 0x3406/*ID for*/), FALSE);
EnableWindow(GetDlgItem(pFtd->hDlgWnd, 0x3407/*ID for*/), FALSE);
return;
} // goto loc_Return
GetTargetName(pFtd->hGlobal, 0, &Msg);
SetDlgItemText(pFtd->hDlgWnd, 0x66/*ID for 圖示旁邊的名稱*/, &Msg);
if (SUCCEEDED(hr = pFtd->pIShellLink->GetPath(&TargetPath, MAX_PATH, NULL, SLGP_RAWPATH)) || // else loc_7FD033C0
SUCCEEDED(hr = pFtd->pIShellLink->GetPath(&TargetPath, MAX_PATH, NULL, 0)) && hr != S_FALSE)
{// else loc_7FD035B7
pFtd->dwc = TRUE;
if (!SHGetFileInfo(TargetPath, 0, &ShellFileInfo, sizeof(SHFILEINFO), SHGFI_TYPENAME)) { // loc_7FD03424
ExpandEnvironmentStrings(TargetPath, Path, MAX_PATH);
SHGetFileInfo(Path, 0, ShellFileInfo, sizeof(SHFILEINFO), SHGFI_TYPENAME);
}
SetDlgItemText(pFtd->hDlgWnd, 0x3303/*ID for "目標型別"*/, ShellFileInfo.szTypeName);
lstrcpy(Msg, TargetPath);
PathRemoveFileSpec(Msg);
SetDlgItemText(pFtd->hDlgWnd, 0x3309/*ID for "目標位置"*/, PathFindFileName(Msg));
pFtd->pIShellLink->GetArguments(Msg, MAX_PATH);
_7FD030E9(TargetPath, Msg);
GetDlgItemText(pFtd->hDlgWnd, 0x3302/*ID for "目標"*/, Msg, MAX_PATH);
if (lstrcmp(TargetPath, Msg))
// loc_7FD034C0
SetDlgItemText(pFtd->hDlgWnd, 0x3302/*ID for "目標"*/, TargetPath);
}
else { // loc_7FD035B7
pFtd->dwc = FALSE;
EnableWindow(GetDlgItem(pFtd->hDlgWnd, 0x3302/*ID for*/), FALSE);
EnableWindow(GetDlgItem(pFtd->hDlgWnd, 0x3002/*ID for*/), FALSE);
pFtd->pIShellLink->GetIDList(&pidl);
if (pidl) { // else loc_7FD034D1
SHELL32_15(pidl, &TargetPath);
SHELL32_17(pidl);
SHELL32_186(0, pidl, &Msg, 1);
SHELL32_155_FreePidl(pidl);
SetDlgItemText(pFtd->hDlgWnd, 0x3309, Msg);
SetDlgItemText(pFtd->hDlgWnd, 0x3303, TargetPath);
// optimized as jmp loc_7FD034C0
SetDlgItemText(pFtd->hDlgWnd, 0x3302/*ID for "目標"*/, TargetPath);
}
}
// loc_7FD034D1
if (!bFlag) { // else loc_Return
pFtd->pIShellLink->GetWorkingDirectory(Msg, MAX_PATH);
_7FD03173(pFtd->hDlgWnd, 0x3002, Msg);
pFtd->pIShellLink->GetHotkey(&Hotkey);
SendDlgItemMessage(pFtd->hDlgWnd, 0x3404/*ID for 快捷鍵*/, 0x401, (WPARAM)Hotkey, 0);
for (uID = 0x1034; /*ID for 常規視窗*/ uID <= 0x1036; uID++) {
LoadString(ghModule, uID, Msg, MAX_PATH);
SendDlgItemMessage(pFtd->hDlgWnd, 0x3408, CB_ADDSTRING, 0, (LPARAM)&Msg);
uID++;
}
pFtd->pIShellLink->GetShowCmd(&ShowCmd);
for (int i = 0; i < 3; i++)
if (gdwShowCmd[i] == ShowCmd) break;
if (i == 3) i = 0;
SendDlgItemMessage(pFtd->hDlgWnd, 0x3408, CB_SETCURSEL, 0, 0);
GetTargetIcon(pFtd, 0);
}
}
HRESULT GetSHGetIDispatchForFolderFunc(ITEMIDLIST* pidl, IWebBrowserApp* ppIWebBrowserApp)
{
if (ghSHDOCVW == NULL)
ghSHDOCVW = LoadLibrary("SHDOCVW.DLL");
if (ghSHDOCVW == NULL)
return E_FAIL;
if (gpfSHGetIDispatchForFolder == NULL) {
gpfSHGetIDispatchForFolder = GetProcAddress(ghModule, "SHGetIDispatchForFolder");
if (gpfSHGetIDispatchForFolder == NULL)
return E_FAIL;
}
return gpfSHGetIDispatchForFolder(pidl, ppIWebBrowserApp);
}
HRESULT GetShellFolderViewDual(ITEMIDLIST* pidl, IShellFolderViewDual** ppIShellFolderViewDual)
{
IWebBrowserApp* pIWebBrowserApp;
IDispatch* pDoc;
HWND hWnd;
HRESULT hr;
*ppIShellFolderViewDual = NULL;
if (SUCCEEDED(hr = GetSHGetIDispatchForFolderFunc(pidl, &pIWebBrowserApp)) {
if (SUCCEEDED(pIWebBrowserApp->get_HWND(&hWnd)) {
SetForegroundWindow(hWnd);
ShowWindow(hWnd, SW_SHOWNORMAL);
}
if (SUCCEEDED(hr = pIWebBrowserApp->get_Document(&pDoc)) {
pDoc->QueryInterface(IID_IShellFolderViewDual, ppIShellFolderViewDual);
pDoc->Release();
}
pIWebBrowserApp->Release();
}
return hr;
}
ITEMIDLIST* SHELL32_16_GetFilePidl(ITEMIDLIST* pidl)
{
ITEMIDLIST* pIdlFile = pidl;
USHORT cb;
if (pIdlFile) {
while (cb = pidl->mkid.cb) {
pIdlFile = pidl;
pidl = (ITEMIDLIST*)((BYTE*)pidl + cb);
}
}
return pIdlFile;
}
int SHELL32_152_GetPidlSize(ITEMIDLIST* pidl)
{
int sz = 0;
USHORT cb;
if (pidl) {
sz = 2;
while (cb = pidl->mkid.cb) {
sz += cb;
pidl = (ITEMIDLIST*)((BYTE*)pidl + cb);
}
}
return sz;
}
SAFEARRAY* CreateSaveArray(VARTYPE vt, long lLbound, unsigned int cElements)
{
if (ghOleAut32 == NULL)
LoadLibrary("OLEAUT32.DLL");
if (ghOleAut32) {
if (pfnSafeArrayCreateVector == NULL)
pfnSafeArrayCreateVector = GetProcAddress(ghOleAut32, "SafeArrayCreateVector");
if (pfnSafeArrayCreateVector != NULL)
return pfnSafeArrayCreateVector(vt, lLbound, cElements);
}
return NULL;
}
SAFEARRAY* AllocSafeArrayForPidl(ITEMIDLIST* pidl, int sz)
{
SAFEARRAY* parray;
if (pidl && sz) {
parray = CreateSaveArray(VT_UI1, 0, sz);
if (parray)
memcpy(parray->pvData, pidl, sz);
return parray;
}
return NULL;
}
BOOL SetVariantArg(VARIANTARG* pVariantArg, ITEMIDLIST* pidl)
{
SAFEARRAY* parray;
if ((parray = AllocSafeArrayForPidl(pidl, SHELL32_153_GetPidlSize(pidl))) != NULL) {
memset(pVariantArg, sizeof(VARIANTARG));
pVariantArg->vt = VT_ARRAY | VT_UI1);
pVariantArg->parray = parray;
return TRUE;
}
return FALSE;
}
HRESULT ClearVariantArg(VARIANTARG* pVariantArg)
{
if (ghOleAut32 == NULL)
LoadLibrary("OLEAUT32.DLL");
if (ghOleAut32) {
if (pfnVariantClear == NULL)
pfnVariantClear = GetProcAddress(ghOleAut32, "VariantClear");
if (pfnVariantClear != NULL)
return pfnVariantClear(pVariantArg);
}
return E_FAIL;
}
HRESULT SelectItem(IShellFolderViewDual* pIShellFolderViewDual, ITEMIDLIST* pidl, int dwFlags)
{
HRESULT hr = E_FAIL;
VARIANTARG VariantArg;
if (SetVariantArg(&VariantArg, pidl)) {
hr = pIShellFolderViewDual->SelectItem(&VariantArg, dwFlags);
ClearVariantArg(&VariantArg);
}
return hr;
}
void OnCmdFindTarget(FindTargetData* pFtd)
{
ITEMIDLIST* pidl, *pidl2;
USHORT cb;
IShellFolderViewDual* pIShellFolderViewDual;
int var_8;
if (pFtd->pIShellLink->Resolve(pFtd->hDlgWnd, 0) == NOERROR) { // 0? 奇怪!
FindTargetInit(pFtd, TRUE);
pFtd->pIShellLink->GetIDList(&pidl);
if (pidl == NULL) return;
var_10 = 0x1000000;
if (FAILED(_7FCD197A(pidl, 0, 0, 0, &var_10)) {
Msg(ghModule, pFtd->hDlgWnd, 6456/*ID for "找不到 %1!ls!"*/, NULL, 0x10030);
SHELL32_155_FreePidl(pidl);
return;
}
// Get the pidl for the item in its folder
pidl2 = SHELL32_16_GetFilePidl(pidl);
if (pidl2 != pidl)
cb = pidl2->mkid.cb, pidl2->mkid.cb = 0;
else
cb = 0;
EnterCriticalSec();
if ((tmp = _7FCB255B(0, 0x10, 0)) != 0) {
tmp = SHELL32_21(pidl, tmp);
var_8 = 1;
if (!tmp) var_8 = 0;
}
else
var_8 = 0;
LeaveCriticalSec();
if (var_8 == 0 && cb != 0) { // else loc_7FD03761
DoOleInitialize();
if (SUCCEEDED(GetShellFolderViewDual(pidl, &pIShellFolderViewDual)) {
pidl2->mkid.cb = cb;
// 0 Deselect the item.
// 1 Select the item.
// 3 Put the item in edit mode.
// 4 Deselect all but the specified item.
// 8 Ensure the item is displayed in the view.
// 0x10 Give the item the focus.
SelectItem(pIShellFolderViewDual, pidl2, 0x1d);
pIShellFolderViewDual->Release();
}
}
else { // loc_7FD03761, target is on the desktop
HWND hwnd;
// 6457: 檔案位於桌面上。要找到它,請用滑鼠右鍵單擊
// 工作列的空白區域,然後單擊“最小化所有視窗
Msg(ghModule, pFtd->hDlgWnd, 6457, NULL, 0);
if ((hwnd = FindWindow("Progman", NULL)) != NULL)
PostMessage(pFtd->hDlgWnd, 0x464, 0, hwnd);
}
SHELL32_155_FreePidl(pidl);
return;
}
}
相關文章
- 實現個人目標的七個步驟2009-02-10
- 國慶快樂!附ssh實戰2024-10-03
- IEA:實現1.5 °C 目標的可靠途徑2023-05-06
- 重慶醫保查詢2024-03-21
- 查詢同時附帶查主表的第二列2024-04-16
- 幾個SQL查詢小技巧2022-12-21SQL
- 二分查詢—包括查詢第一個目標元素和最後一個目標元素2020-11-01
- 開學送給她的禮物(Python實現)2022-02-28Python
- SQL多個表實現聯合查詢2013-11-22SQL
- 國慶,帶上 Google 翻譯探索城市2017-09-28Go
- Access查詢實現Mysql的 limit 查詢2016-08-23MySqlMIT
- Nielsen: 實現財政目標的道路上需要指點2014-01-22
- 這個實時公交查詢小程式,支援全國 100 個城市2018-12-13
- 開源髮絲分割資料集CelebAHairMask-HQ(國慶獻禮)2020-10-02AI
- iOS 直播間送禮物邏輯(禮物連擊)2018-03-26iOS
- java實現折半查詢。2011-04-08Java
- 給TAE!的小禮物---對DISKdata v3.3.2註冊演算法的分析 (14千字)2001-07-13演算法
- 查詢演算法集:順序查詢、二分查詢、插值查詢、動態查詢(陣列實現、連結串列實現)2008-01-03演算法陣列
- 最能討好程式設計師的6件禮物2015-01-13程式設計師
- 專案是實現企業戰略目標的載體(轉)2007-08-11
- 波士頓諮詢:具有強大目標的領導力2024-03-13
- 經濟學人評AI行業現狀:小心那些帶著禮物來的極客們2017-12-09AI行業
- MyBatis帶參查詢2020-11-19MyBatis
- Excel VBA小程式 -使 用VBA實現VLOOKUP函式查詢?2020-10-02Excel函式
- 推動和實現物聯網成功的6個問題2021-10-29
- SSH:hiberate實現資料的查詢(單查詢和全查詢)2019-01-01
- 成為一個有目標的學習者2019-05-22
- Stax處理XML(一)——基於游標的查詢2013-12-31XML
- indexdb實現分頁查詢2022-01-16Index
- mysql多表查詢如何實現2021-09-11MySql
- 折半查詢(C++實現)2020-12-07C++
- mysql實現隨機查詢2014-03-13MySql隨機
- 提高 Laravel Eloquent 查詢的5個小技巧2021-03-12Laravel
- Laravel Query Builder 複雜查詢案例:子查詢實現分割槽查詢 partition by2018-11-27LaravelUI
- 查詢皮膚中如何實現兩個 select 下拉框的關聯查詢?2020-06-18
- 使用mybatis example 和 java 8的特性來實現多表關聯且帶有查詢條件的查詢2018-10-10MyBatisJava
- 新年小禮——給最愛圖靈會員的禮物(入圍名單出爐)2012-01-06圖靈
- select查詢之三:子查詢2016-10-08