水無瀬の部屋 > Programming > sample > atlnk > shitemid.cpp |
---|
1: //*********************************************************
2: // プロジェクト: atlnk - @link.target
3: // ファイル名: shitemid.cpp
4: //*********************************************************
5: #include "shitemid.h" //
6: #include <misc/atoffset.h>
7:
8:
9: //---------------------------------------------------------
10: // マクロ関数 の 定義
11: //---------------------------------------------------------
12: #define NEXTITEMID( ptr, offset ) (&atoffset( ITEMIDLIST, (ptr), (offset) ))
13:
14:
15: //---------------------------------------------------------
16: // ファイルスコープ関数 の 宣言
17: //---------------------------------------------------------
18: static bool IsValidItemIDList( const ITEMIDLIST *pidl );
19: static ITEMIDLIST *ITEMIDLIST_GetNextItemID( const ITEMIDLIST *pidl );
20: static bool ShellLink_GetTargetFile( const char *LinkFile, ITEMIDLIST **ppidl );
21: static bool OpenParentIDList( IMalloc *pMalloc, const ITEMIDLIST *pidl, const char *verb );
22: static HINSTANCE ITEMIDLIST_ShellExecute( HWND hWnd, const char *verb, const ITEMIDLIST *pidl, const char *lpParameters, const char *lpDirectory, int nShowCmd );
23:
24:
25: //*********************************************************
26: // OpenLinkTargetLocation()
27: // ショートカット の リンク先 がある フォルダ を 動詞 verb で 開く
28: //*********************************************************
29: bool
30: OpenLinkTargetLocation
31: (
32: int argc,
33: char **argv,
34: const char *verb // 動詞
35: )
36: {
37: // パラメタの仮定
38: ASSERT( IsValidArgcArgv( argc, argv ) );
39: ASSERT( !verb || IsValidStringPtr( verb ) );
40:
41: // シェル・アロケータの取得
42: IMalloc *pMalloc;
43: if ( NOERROR != SHGetMalloc( &pMalloc ) )
44: {
45: return false;
46: }
47:
48: //
49: {for( int i = 0; i < argc; ++i )
50: {
51: ASSERT( IsPathExist( argv[ i ] ) );
52:
53: if ( IsPathFile( argv[ i ] ) )
54: {
55: // リンク先を取得
56: ITEMIDLIST *pidl = null;
57: if ( ShellLink_GetTargetFile( argv[ i ], &pidl ) )
58: {
59: ASSERT( IsValidItemIDList( pidl ) );
60:
61: // リンク先があるフォルダを開く
62: VERIFY( OpenParentIDList( pMalloc, pidl, verb ) );
63:
64: pMalloc->Free( pidl );
65: }
66: }
67: }}
68:
69: // シェル・アロケータの解放
70: pMalloc->HeapMinimize();
71: pMalloc->Release();
72:
73: // 終了
74: return true;
75: }//OpenLinkTargetLocation
76:
77:
78: //******************************************************************************************************************
79: // private
80: //******************************************************************************************************************
81: static bool OpenIDList( const ITEMIDLIST *pidl, const char *verb );
82: static ITEMIDLIST *GetParentIDList( IMalloc *pMalloc, const ITEMIDLIST *pidl );
83: static ITEMIDLIST *GetNextIDList( const ITEMIDLIST *pidl );
84:
85:
86: //*********************************************************
87: // OpenParentIDList
88: // 親フォルダ(オブジェクトが存在するフォルダ)を開く
89: //*********************************************************
90: static
91: bool
92: OpenParentIDList
93: (
94: IMalloc *pMalloc,
95: const ITEMIDLIST *pidl,
96: const char *verb
97: )
98: {
99: // パラメタの仮定
100: ASSERT( IsValidPtr( pMalloc, sizeof( *pMalloc ) ) );
101: ASSERT( IsValidItemIDList( pidl ) );
102: ASSERT( IsValidStringPtr( verb ) );
103:
104: // 親フォルダを取得
105: ITEMIDLIST *pidlParent = GetParentIDList( pMalloc, pidl );
106: if ( !pidlParent )
107: {
108: return false; //
109: }
110: ASSERT( IsValidItemIDList( pidlParent ) );
111:
112: // 親フォルダを開く
113: OpenIDList( pidlParent, verb );
114:
115: // 親フォルダの解放
116: pMalloc->Free( pidlParent );
117:
118: // 成功終了
119: return true;
120: }//OpenParentIDList
121:
122: //*********************************************************
123: // OpenIDList
124: // 指定のフォルダ pidl を開く
125: // => 指定の pidl に何かする
126: //*********************************************************
127: static
128: bool
129: OpenIDList
130: (
131: const ITEMIDLIST *pidl,
132: const char *verb
133: )
134: {
135: // パラメタの仮定
136: ASSERT( IsValidItemIDList( pidl ) );
137: ASSERT( IsValidStringPtr( verb ) );
138:
139:
140: // 指定の pidl を開く
141: // ShellExecuteEx() より ShellExecute() の方が
142: // 古い OS で安定動作するようなので可能であれば ShellExecute() を使う
143: // 例えば "c:\\windows\\command\\" を
144: // "c:\\windows\\command.com" と間違えないように
145: // if ( GetPathFromIDList( pidl, path, numof(path) ) )
146: // {
147: // ASSERT( IsPathDirectory( path ) );
148: // ASSERT( 0 != strlen( path ) );
149: // strncat( path, ".\\", sizeof(path) - strlen(path) - 1 );
150:
151: SHELLEXECUTEINFO sei;
152: memzero( &sei, sizeof( sei ) );
153: sei.cbSize = sizeof( sei );
154: sei.fMask = SEE_MASK_IDLIST;
155: sei.hwnd = HWND_DESKTOP;
156: sei.nShow = SW_SHOWNORMAL;
157: sei.lpVerb = verb;
158: sei.lpFile = null;
159: sei.lpParameters = null;
160: sei.lpDirectory = null;
161: sei.lpIDList = const_cast<ITEMIDLIST *>( pidl );
162: VERIFY( ShellExecuteEx( &sei ) );
163:
164: return SHELLEXECUTE_SUCCEEDED( sei.hInstApp );
165: }//OpenIDList
166:
167: //*********************************************************
168: // GetParentIDList
169: // 親フォルダ(オブジェクトが存在するフォルダ)を取得
170: //*********************************************************
171: static
172: ITEMIDLIST *
173: GetParentIDList
174: (
175: IMalloc *pMalloc,
176: const ITEMIDLIST *pidl
177: )
178: {
179: // パラメタの仮定
180: ASSERT( IsValidPtr( pMalloc, sizeof( *pMalloc ) ) );
181: ASSERT( IsValidItemIDList( pidl ) );
182:
183: //
184: int cbPre = 0; // 直前の項目サイズ
185: int cbTotal; // ここまでのサイズ
186: int cbTotalPre; // 直前までのサイズ
187:
188: // pidlParent に必要なサイズを試算
189: {
190: cbTotal = 0;
191: cbTotalPre = 0;
192:
193: int cb;
194: const ITEMIDLIST *pidlNext = pidl;
195: while( 0 != (cb = pidlNext->mkid.cb) )
196: {
197: ASSERT( (0 < cb) && (cb <= USHRT_MAX) );
198:
199: cbPre = cb;
200: cbTotalPre = cbTotal;
201: cbTotal += cb;
202:
203: pidlNext = ITEMIDLIST_GetNextItemID( pidlNext );
204: ASSERT( cbTotal == cbTotalPre + cbPre );
205: }
206: ASSERT( 0 == pidlNext->mkid.cb );
207:
208: ASSERT( IsValidPtr( (ITEMIDLIST *)pidl, cbTotal + sizeof( pidlNext->mkid.cb ) ) );
209: cbTotal = cbTotalPre + sizeof( pidlNext->mkid.cb );
210: ASSERT( IsValidPtr( (ITEMIDLIST *)pidl, cbTotal ) );
211: }
212:
213: // pidlParent の構築
214: ITEMIDLIST *pidlParent = (ITEMIDLIST *)pMalloc->Alloc( cbTotal );
215: if ( !pidlParent )
216: {
217: // 領域の確保に失敗
218: return null;
219: }
220: ASSERT( IsValidPtr( pidlParent, cbTotal ) );
221:
222: // 親フォルダまで複写
223: memmove( pidlParent, pidl, cbTotal );
224: ITEMIDLIST *tail = NEXTITEMID( pidlParent, cbTotalPre );
225: ASSERT( tail->mkid.cb == cbPre );
226: tail->mkid.cb = 0;
227:
228: ASSERT( IsValidItemIDList( pidlParent ) );
229: ASSERT( IsValidItemIDList( pidl ) );
230:
231: return pidlParent;
232: }//GetParentIDList
233:
234:
235: //******************************************************************************************************************
236: // util ( shell link )
237: //******************************************************************************************************************
238: //*********************************************************
239: // ShellLink_GetTargetFile
240: // ショートカット path が指すオブジェクトへの ITEMIDLIST を取得する。
241: //*********************************************************
242: static
243: bool
244: ShellLink_GetTargetFile
245: (
246: const char *path,
247: ITEMIDLIST **ppidl
248: )
249: {
250: // パラメタの仮定
251: ASSERT( IsPathFile( path ) );
252: ASSERT( IsValidPtr( ppidl, sizeof( *ppidl ) ) );
253:
254: //
255: *ppidl = null;
256:
257: // ショートカット path へのインタフェイスを取得する
258: IShellLink *psl = LoadShellLinkInstance( CLSCTX_INPROC_SERVER, path, STGM_READ );
259: if ( !psl )
260: {
261: return false; // [失敗]
262: }
263: ASSERT( IsValidPtr( psl, sizeof( *psl ) ) );
264:
265: // リンク先を取得
266: if ( S_OK != psl->GetIDList( ppidl ) )
267: {
268: psl->Release();
269: *ppidl = null;
270: return false; // [失敗]
271: }
272:
273: psl->Release();
274: ASSERT( IsValidPtr( ppidl, sizeof( *ppidl ) ) );
275: ASSERT( IsValidItemIDList( *ppidl ) );
276: return boolean_cast( *ppidl ); // [成功]
277: }//ShellLink_GetTargetFile
278:
279:
280: //******************************************************************************************************************
281: //
282: //******************************************************************************************************************
283: //*********************************************************
284: // IsValidItemIDList
285: //*********************************************************
286: static
287: bool
288: IsValidItemIDList
289: (
290: const ITEMIDLIST *pidl
291: )
292: {
293: VALID_TEST( pidl );
294: VALID_TEST( IsValidReadPtr( pidl, sizeof( *pidl ) ) );
295:
296: //
297: int cbTotal = 0;
298: {
299: int cb;
300: const ITEMIDLIST *p = pidl;
301: while( 0 != (cb = p->mkid.cb) )
302: {
303: ASSERT( (0 < cb) && (cb <= USHRT_MAX) );
304: VALID_TEST( IsValidReadPtr( p, cb ) );
305:
306: // 次の項目の位置を指す
307: cbTotal += cb;
308: p = NEXTITEMID( p, cb );
309: }
310: ASSERT( 0 == p->mkid.cb );
311: cbTotal += sizeof( p->mkid.cb );
312: }
313:
314: //
315: VALID_TEST( IsValidReadPtr( pidl, cbTotal ) );
316:
317: return true;
318: }//IsValidItemIDList
319:
320: //*********************************************************
321: // ITEMIDLIST_GetNextItemID
322: //*********************************************************
323: static
324: ITEMIDLIST *
325: ITEMIDLIST_GetNextItemID
326: (
327: const ITEMIDLIST *pidl
328: )
329: {
330: // パラメタの仮定
331: ASSERT( IsValidItemIDList( pidl ) );
332:
333: // 先頭項目のサイズを取得
334: const int cb = pidl->mkid.cb;
335: if ( cb <= 0 )
336: {
337: return null;
338: }
339: ASSERT( (0 < cb) && (cb <= USHRT_MAX) );
340:
341: // 次の項目の位置を指す
342: ITEMIDLIST *pidlNext = NEXTITEMID( pidl, cb );
343: ASSERT( IsValidItemIDList( pidlNext ) );
344:
345: return pidlNext;
346: }//ITEMIDLIST_GetNextItemID
347:
348:
349: //** end **
参照:
水無瀬の部屋 > sample > atlnk > shitemid.cpp |
---|
このページは cpp2web が出力しました。
水無瀬 優 postmaster@katsura-kotonoha.sakura.ne.jp
http://katsura-kotonoha.sakura.ne.jp/prog/code/atlnk/shitemid_cpp.shtml