國慶小禮物,微軟"查詢目標的實現”附帶三個小工具 (6千字)

看雪資料發表於2015-11-15

一直使用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     ebpesp
.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    eaxeax
.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    eaxeax
.text:7FD0404F                 jl      loc_7FD040F6
.text:7FD04055                 push    220h             uBytes
.text:7FD0405A                 push    40h              uFlags
.text:7FD0405C                 call    ds:LocalAlloc
.text:7FD04062                 mov     esieax
.text:7FD04064                 test    esiesi
.text:7FD04066                 jz      loc_7FD040ED
.text:7FD0406C                 mov     eaxds: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     edieax
.text:7FD040C7                 test    ediedi
.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    eaxeax
.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     eaxeax
.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;
}

相關文章