1 /*
2 	vfdshext.cpp
3 
4 	Virtual Floppy Drive for Windows
5 	Driver control library
6 	shell extension COM shell extension class
7 
8 	Copyright (c) 2003-2005 Ken Kato
9 */
10 
11 #define WIN32_LEAN_AND_MEAN
12 #include <windows.h>
13 #include <shellapi.h>
14 #include <shlobj.h>
15 
16 #include "vfdtypes.h"
17 #include "vfdapi.h"
18 #include "vfdlib.h"
19 
20 //	class header
21 #include "vfdshext.h"
22 
23 //
24 //	Constructor
25 //
26 CVfdShExt::CVfdShExt()
27 {
28 	VFDTRACE(0, ("CVfdShExt::CVfdShExt()\n"));
29 
30 	m_cRefCnt		= 0L;
31 	m_pDataObj		= NULL;
32 	m_nDevice		= (ULONG)-1;
33 	m_sTarget[0]	= '\0';
34 	m_bDragDrop		= FALSE;
35 
36 	g_cDllRefCnt++;
37 }
38 
39 //
40 //	Destructor
41 //
42 CVfdShExt::~CVfdShExt()
43 {
44 	VFDTRACE(0, ("CVfdShExt::~CVfdShExt()\n"));
45 
46 	if (m_pDataObj) {
47 		m_pDataObj->Release();
48 	}
49 
50 	g_cDllRefCnt--;
51 }
52 
53 //	IUnknown members
54 
55 STDMETHODIMP CVfdShExt::QueryInterface(
56 	REFIID			riid,
57 	LPVOID			*ppv)
58 {
59 	*ppv = NULL;
60 
61 	if (IsEqualIID(riid, IID_IShellExtInit) ||
62 		IsEqualIID(riid, IID_IUnknown)) {
63 		VFDTRACE(0,
64 			("CVfdShExt::QueryInterface()==>IID_IShellExtInit\n"));
65 
66 		*ppv = (LPSHELLEXTINIT)this;
67 	}
68 	else if (IsEqualIID(riid, IID_IContextMenu)) {
69 		VFDTRACE(0,
70 			("CVfdShExt::QueryInterface()==>IID_IContextMenu\n"));
71 
72 		*ppv = (LPCONTEXTMENU)this;
73 	}
74 	else if (IsEqualIID(riid, IID_IShellPropSheetExt)) {
75 		VFDTRACE(0,
76 			("CVfdShExt::QueryInterface()==>IID_IShellPropSheetExt\n"));
77 
78 		*ppv = (LPSHELLPROPSHEETEXT)this;
79 	}
80 
81 	if (*ppv) {
82 		AddRef();
83 
84 		return NOERROR;
85 	}
86 
87 	VFDTRACE(0,
88 		("CVfdShExt::QueryInterface()==>Unknown Interface!\n"));
89 
90 	return E_NOINTERFACE;
91 }
92 
93 STDMETHODIMP_(ULONG) CVfdShExt::AddRef()
94 {
95 	VFDTRACE(0, ("CVfdShExt::AddRef()\n"));
96 
97 	return ++m_cRefCnt;
98 }
99 
100 STDMETHODIMP_(ULONG) CVfdShExt::Release()
101 {
102 	VFDTRACE(0, ("CVfdShExt::Release()\n"));
103 
104 	if (--m_cRefCnt) {
105 		return m_cRefCnt;
106 	}
107 
108 #ifndef __REACTOS__
109 	delete this;
110 #endif
111 
112 	return 0L;
113 }
114 
115 //	IShellExtInit members
116 
117 //
118 //	Initialize
119 //	Called by the shell to initialize the shell extension object
120 //
121 STDMETHODIMP CVfdShExt::Initialize(
122 	LPCITEMIDLIST	pIDFolder,
123 	LPDATAOBJECT	pDataObj,
124 	HKEY			hRegKey)
125 {
126 	CHAR drive = '\0';
127 
128 	VFDTRACE(0, ("CVfdShExt::Initialize()\n"));
129 
130 	UNREFERENCED_PARAMETER(hRegKey);
131 
132 	// Initialize can be called more than once
133 
134 	if (m_pDataObj) {
135 		m_pDataObj->Release();
136 		m_pDataObj = NULL;
137 	}
138 
139 	m_nDevice = (ULONG)-1;
140 	m_sTarget[0] = '\0';
141 
142 	//	Get the folder name
143 	if (SHGetPathFromIDList(pIDFolder, m_sTarget)) {
144 
145 		//	act as a Drag-and-Drop Handler
146 
147 		VFDTRACE(0, ("Drag-Drop: %s\n", m_sTarget));
148 
149 		if (GetDriveType(m_sTarget) != DRIVE_REMOVABLE) {
150 			VFDTRACE(0, ("Not a VFD drive\n"));
151 			return NOERROR;
152 		}
153 
154 		drive = m_sTarget[0];
155 		m_bDragDrop = TRUE;
156 	}
157 	else {
158 
159 		//	act as a context menu handler
160 
161 		VFDTRACE(0, ("Context menu:\n"));
162 		m_bDragDrop = FALSE;
163 	}
164 
165 	// Extract the target object name
166 
167 	if (pDataObj) {
168 
169 		STGMEDIUM medium;
170 		FORMATETC fmt = {
171 			CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL
172 		};
173 
174 		if (SUCCEEDED(pDataObj->GetData(&fmt, &medium))) {
175 			if (DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0)) {
176 
177 				DragQueryFile((HDROP)medium.hGlobal,
178 					0, m_sTarget, sizeof(m_sTarget));
179 			}
180 
181 			ReleaseStgMedium(&medium);
182 		}
183 	}
184 
185 	VFDTRACE(0, ("Target %s\n", m_sTarget));
186 
187 	if (!drive) {
188 		//	Contect menu handler
189 		//	-- Data object is the target drive
190 		drive = m_sTarget[0];
191 	}
192 
193 	HANDLE hDevice = VfdOpenDevice(drive);
194 
195 	if (hDevice == INVALID_HANDLE_VALUE) {
196 		VFDTRACE(0, ("Not a VFD drive\n"));
197 		return NOERROR;
198 	}
199 
200 	ULONG ret = VfdGetDeviceNumber(hDevice, &m_nDevice);
201 
202 	CloseHandle(hDevice);
203 
204 	if (ret != ERROR_SUCCESS) {
205 		m_nDevice = (ULONG)-1;
206 		return NOERROR;
207 	}
208 
209 	VFDTRACE(0, ("VFD device %d\n", m_nDevice));
210 	//	Store the data object
211 
212 	m_pDataObj = pDataObj;
213 	m_pDataObj->AddRef();
214 
215 	return NOERROR;
216 }
217 
218 /*
219 STDMETHODIMP CVfdShExt::GetInfoFlags(
220 	DWORD *pdwFlags)
221 {
222 	VFDTRACE(0, ("CVfdShExt::GetInfoFlags\n"));
223 	*pdwFlags = 0;
224 	return NOERROR;
225 }
226 
227 STDMETHODIMP CVfdShExt::GetInfoTip(
228 	DWORD dwFlags,
229 	LPWSTR *ppwszTip)
230 {
231 	VFDTRACE(0, ("CVfdShExt::GetInfoTip\n"));
232 	*ppwszTip = NULL;
233 	return NOERROR;
234 }
235 */
236