-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathFix-SHBrowseForFolder.js
More file actions
62 lines (51 loc) · 2.35 KB
/
Fix-SHBrowseForFolder.js
File metadata and controls
62 lines (51 loc) · 2.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
"use strict";
console.log("Starting");
const Win32 = require('../common/win32');
const Struct = require('../common/struct');
const GUID = require('../common/guid');
const COM = require('../common/com');
// Define API's from windows headers.
var CLSID_FileOpenDialog = GUID.alloc("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7");
var FOS_PICKFOLDERS = 0x20;
var IFileDialog = new COM.Interface(COM.IUnknown, {
Show: [0, ['uint']],
SetOptions: [6, ['uint']],
GetResult: [17, ['pointer']],
}, "42f85136-db7e-439c-85f1-e4075d135fc8");
var IShellItem = new COM.Interface(COM.IUnknown, {
}, "43826d1e-e718-42ee-bc55-a1e261c37bfe");
var SHBrowseForFolderPtr = Module.findExportByName('shell32.dll', 'SHBrowseForFolderW');
var SHBrowseForFolder = new NativeFunction(SHBrowseForFolderPtr, 'pointer', ['pointer']);
var SHGetIDListFromObject = new NativeFunction(Module.findExportByName('shell32.dll', 'SHGetIDListFromObject'), 'uint', ['pointer','pointer']);
var BIF_EDITBOX = (0x00000010);
var BIF_NEWDIALOGSTYLE = (0x00000040);
var BIF_RETURNONLYFSDIRS = (0x00000001);
// Intercept and replace SHBrowseForFolderW
Interceptor.replace(SHBrowseForFolderPtr, new NativeCallback(function (browseinfoPtr) {
console.log("SHBrowseForFolderW Entry");
var browseinfo = new Struct({ // BROWSEINFO
'hwndOwner':'int',
'pidlRoot':'pointer',
'pszDisplayName':'pointer',
'lpszTitle':'pointer',
'ulFlags':'uint',
'lpfn':'pointer',
'lParam':'long',
'iImage':'int',
}, browseinfoPtr);
console.log("SHBrowseForFolderW ulFlags: 0x" + browseinfo.ulFlags.toString(16));
// Per the docs, COM should already be initialized but this wasn't the case when testing against a real app.
COM.Initialize(COM.ApartmentType.STA);
// Create and show the replacement dialog
var modalWindow = COM.CreateInstance(CLSID_FileOpenDialog, COM.ClassContext.InProc, IFileDialog);
modalWindow.SetOptions(FOS_PICKFOLDERS);
modalWindow.Show(browseinfo.hwndOwner);
var shellItem = new COM.Pointer(IShellItem);
COM.ThrowIfFailed(modalWindow.GetResult(shellItem.GetAddressOf()));
// Convert IShellItem result to an idlist to return to SHBrowseForFolderW.
var pidl = Memory.alloc(Process.pointerSize);
COM.ThrowIfFailed(SHGetIDListFromObject(shellItem.Get(), pidl));
console.log("SHBrowseForFolderW Exit pidl=" + pidl);
return Memory.readPointer(pidl);
}, 'pointer', ['pointer'], Win32.Abi));
console.log("Ready");