source: branches/branch-1-0/include/helpers/call_file_dlg.c

Last change on this file was 264, checked in by pr, 21 years ago

Fix spelling errors.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 17.0 KB
Line 
1
2/*
3 *@@ ImplCallFileDlg:
4 * this code contacts XFLDR.DLL to show the
5 * XWorkplace file dialog. This does not
6 * return until either an error occurred
7 * or XFLDR.DLL has dismissed the dialog,
8 * either because the user pressed "OK"
9 * or "Cancel".
10 *
11 * In summary, this can almost be called
12 * instead of WinFileDlg.
13 *
14 * If this fails because FILEDLG contains
15 * options that are presently not supported
16 * by XWP's dialog replacement, we set
17 * *pfCallDefault to TRUE and return NULLHANDLE.
18 * As a result, you should check that flag
19 * on return and call WinFileDlg instead
20 * if the flag is TRUE.
21 *
22 *@@added V0.9.19 (2002-04-24) [umoeller]
23 *@@changed V1.0.2 (2003-03-07) [umoeller]: HWND_DESKTOP owner causes focus problems, fixed
24 */
25
26HWND APIENTRY ImplCallFileDlg(HWND hwndOwner, // in: owner for dialog
27 PFILEDLG pfd, // in/out: as with WinFileDlg
28 PBOOL pfCallDefault) // out: set to TRUE if replacement failed
29{
30 HWND hwndReturn = NULLHANDLE;
31
32 *pfCallDefault = TRUE;
33
34 // first, some compatibility checks...
35 if ( (pfd)
36 && ( (!(pfd->fl & ( FDS_CUSTOM
37 | FDS_MODELESS // we can't handle non-modal dialogs
38 | FDS_MULTIPLESEL // we can't handle multiple selections for now
39 )
40 )))
41 )
42 {
43 // OK:
44
45 // check if XWP is running; if so, a block of
46 // named shared memory must exist
47 APIRET arc;
48 PXWPGLOBALSHARED pXwpGlobalShared = 0;
49 if (!(arc = DosGetNamedSharedMem((PVOID*)&pXwpGlobalShared,
50 SHMEM_XWPGLOBAL, // "\\SHAREMEM\\XWORKPLC\\DMNSHARE.DAT",
51 PAG_READ | PAG_WRITE)))
52 {
53 // we can get the shared memory --> XWP running:
54 PID pidWPS = 0;
55 TID tidWPS = 0;
56 CHAR szEmptyTitle[1];
57 HWND hwndNotify;
58 HAB hab;
59
60 szEmptyTitle[0] = 0;
61
62 // create temporary object window for notifications from XFLDR.DLL;
63 // this handle is passed to XFLDR.DLL in the shared memory block
64 // so it can post WM_USER back to this window, upon which we
65 // terminate our modal loop here
66 if ( (hwndNotify = WinCreateWindow(HWND_OBJECT,
67 WC_STATIC,
68 szEmptyTitle,
69 0,
70 0,0,0,0,
71 0,
72 HWND_BOTTOM,
73 0,
74 NULL,
75 NULL))
76 // and we need the anchor block for WinGetMsg:
77 && (hab = WinQueryAnchorBlock(hwndNotify))
78 // is thread-1 object window in XFLDR.DLL running?
79 && (pXwpGlobalShared->hwndThread1Object)
80 && (WinIsWindow(hab,
81 pXwpGlobalShared->hwndThread1Object))
82 // get WPS PID from thread-1 object window
83 && (WinQueryWindowProcess(pXwpGlobalShared->hwndThread1Object,
84 &pidWPS, // on stack
85 &tidWPS)) // on stack
86 )
87 {
88 // yes:
89 PXWPFILEDLG pfdShared = NULL;
90
91 // sum up how much shared memory we need:
92 // this is the sum of FILEDLG plus buffers for
93 // all the strings the stupid caller gave to WinFileDlg
94 // (we're cross-process here)
95
96 // 1) at least the size of FILEDLG
97 ULONG cbShared = sizeof(XWPFILEDLG),
98 cTypes = 0; // count of types in papszITypes
99
100 // 2) add memory for extra fields
101 if (pfd->pszTitle)
102 cbShared += strlen(pfd->pszTitle) + 1;
103 if (pfd->pszOKButton)
104 cbShared += strlen(pfd->pszOKButton) + 1;
105
106 // 3) type
107 if (pfd->pszIType)
108 cbShared += strlen(pfd->pszIType) + 1;
109 // and types array: this is especially sick...
110 // this is a pointer to an array of PSZ's, so
111 // we need:
112 // a) 4 bytes for each PSZ in the PSZ's array
113 // b) string length + 1 for each string pointed
114 // to from the array
115 // c) another 4 bytes for the NULL array terminator
116 if (pfd->papszITypeList)
117 {
118 PSZ *ppszThis = pfd->papszITypeList[0];
119 while (*ppszThis)
120 {
121 cbShared += sizeof(PSZ) // for the PSZ array item
122 + strlen(*ppszThis) // string length
123 + 1; // null terminator
124 ppszThis++;
125 cTypes++; // count the types so we can align
126 // properly below
127 }
128 cbShared += 4; // array is terminated with a NULL psz,
129 // which we must allocate too
130 }
131
132 // 4) drives array... ignored for now
133 /* if (pfd->pszIType)
134 cbShared += strlen(pfd->pszIDrive) + 1;
135 if (pfd->papszIDriveList)
136 {
137 PSZ *ppszThis = pfd->papszIDriveList[0];
138 while (*ppszThis)
139 {
140 cbShared += strlen(*ppszThis) + 1;
141 ppszThis++;
142 }
143 } */
144
145 // OK, now we know how much memory we need...
146 // allocate a block of shared memory with this size
147 if ( (!(arc = DosAllocSharedMem((PVOID*)&pfdShared, // on stack
148 NULL, // unnamed
149 cbShared,
150 PAG_COMMIT | OBJ_GIVEABLE | OBJ_TILE
151 | PAG_READ | PAG_WRITE)))
152 && (pfdShared)
153 )
154 {
155 // OK, we got shared memory:
156 PPIB ppib = NULL;
157 PTIB ptib = NULL;
158 ULONG ulCurDisk = 0;
159 ULONG ulMap = 0;
160 ULONG cbBuf = CCHMAXPATH;
161
162 ULONG cbThis;
163 PBYTE pb = (PBYTE)pfdShared + sizeof(XWPFILEDLG);
164 // current offset where to copy to
165
166 // ZERO the structure
167 memset((PBYTE)pfdShared, 0, cbShared);
168
169 // fix HWND_DESKTOP owner V1.0.2 (2003-03-07) [umoeller]
170 if (hwndOwner == HWND_DESKTOP)
171 hwndOwner = NULLHANDLE;
172
173 // copy owner window
174 pfdShared->hwndOwner = hwndOwner;
175
176 // store PID and TID of caller
177 DosGetInfoBlocks(&ptib, &ppib);
178 pfdShared->pidCaller = ppib->pib_ulpid;
179 pfdShared->tidCaller = ptib->tib_ptib2->tib2_ultid;
180
181 // get the process's current directory so
182 // file dialog can base on that
183 if ( (arc = DosQueryCurrentDisk(&ulCurDisk, &ulMap))
184 || (ulCurDisk == 0)
185 )
186 DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
187 &ulCurDisk,
188 sizeof(ulCurDisk));
189
190 pfdShared->szCurrentDir[0] = 'A' + ulCurDisk - 1;
191 pfdShared->szCurrentDir[1] = ':';
192 pfdShared->szCurrentDir[2] = '\\';
193 DosQueryCurrentDir(0,
194 &pfdShared->szCurrentDir[3],
195 &cbBuf);
196
197 // copy FILEDLG
198 memcpy((PBYTE)&pfdShared->fd,
199 (PBYTE)pfd,
200 _min(pfd->cbSize, sizeof(FILEDLG)));
201
202 // now pack the various fields into the
203 // shared mem AFTER the XWPFILEDLG
204 if (pfd->pszTitle)
205 {
206 cbThis = strlen(pfd->pszTitle) + 1;
207 memcpy(pb, pfd->pszTitle, cbThis);
208 pfdShared->fd.pszTitle = pb;
209 pb += cbThis;
210 }
211 if (pfd->pszOKButton)
212 {
213 cbThis = strlen(pfd->pszOKButton) + 1;
214 memcpy(pb, pfd->pszOKButton, cbThis);
215 pfdShared->fd.pszOKButton = pb;
216 pb += cbThis;
217 }
218
219 // types array
220 if (pfd->pszIType)
221 {
222 cbThis = strlen(pfd->pszIType) + 1;
223 memcpy(pb, pfd->pszIType, cbThis);
224 pfdShared->fd.pszIType = pb;
225 pb += cbThis;
226 }
227
228 if (cTypes) // we counted types in the array above:
229 {
230 ULONG ul;
231
232 // 1) reserve room for the array of PSZ's;
233 // that's (cTypes + 1) * sizeof(PSZ) (null-terminator!)
234
235 PAPSZ papszTarget = (PAPSZ)pb;
236
237 PSZ *ppszSourceThis = pfd->papszITypeList[0],
238 *ppszTargetThis = papszTarget[0];
239
240 pb += ((cTypes + 1) * sizeof(PSZ));
241
242 // 2) pb points to the room for the first string now...
243 // (after the PSZ's array)
244
245 for (ul = 0;
246 ul < cTypes;
247 ul++)
248 {
249 // copy this string from buffer to buffer
250 cbThis = strlen(*ppszSourceThis) + 1;
251 memcpy(pb, *ppszSourceThis, cbThis);
252
253 // set target PSZ array item
254 *ppszTargetThis = pb;
255 // advance pointers
256 pb += cbThis;
257 ppszSourceThis++;
258 ppszTargetThis++;
259 }
260
261 // set null terminator in target array... christ
262 *ppszTargetThis = 0;
263
264 pfdShared->fd.papszITypeList = papszTarget;
265 }
266
267 // drives array
268 /* if (pfd->pszIDrive)
269 {
270 cbThis = strlen(pfd->pszIDrive) + 1;
271 memcpy(pb, pfd->pszIDrive, cbThis);
272 pfdShared->fd.pszIDrive = pb;
273 pb += cbThis;
274 }
275 if (pfd->papszIDriveList)
276 {
277 PSZ *ppszThis = pfd->papszIDriveList[0];
278 PBYTE pbFirst = pb;
279 while (*ppszThis)
280 {
281 cbThis = strlen(*ppszThis) + 1;
282 memcpy(pb, *ppszThis, cbThis);
283 pb += cbThis;
284
285 ppszThis++;
286 }
287
288 pfdShared->fd.papszIDriveList = (PVOID)pbFirst;
289 } */
290
291 // OK, now we got everything in shared memory...
292 // give the WPS access to it
293 if (!(arc = DosGiveSharedMem(pfdShared,
294 pidWPS,
295 PAG_READ | PAG_WRITE)))
296 {
297 // send this block to XFLDR.DLL;
298 // we can't use WinSendMsg because this would
299 // block the msg queue for the calling thread.
300 // So instead we use WinPostMsg and wait for
301 // XFLDR.DLL to post something back to our
302 // temporary object window here...
303
304 pfdShared->hwndNotify = hwndNotify;
305
306 if (WinPostMsg(pXwpGlobalShared->hwndAPIObject,
307 APIM_FILEDLG,
308 (MPARAM)pfdShared,
309 0))
310 {
311 // the file dialog should be showing up now
312 // in the WPS process...
313
314 QMSG qmsg;
315 BOOL fQuit = FALSE;
316 USHORT fsFrameFlags = 0;
317
318 // OK, if we got this far:
319
320 // 1) do not show the default dialog
321 *pfCallDefault = FALSE;
322
323 // 2) DISABLE the owner window... we need to
324 // simulate a modal dialog here, but this doesn't
325 // really work because the dialog is in the WPS
326 // process, so a couple hacks are needed
327
328 if (hwndOwner) // WinEnableWindow
329 WinEnableWindow(hwndOwner, FALSE);
330
331 // keep processing our message queue until
332 // XFLDR.DLL posts back WM_USER to the
333 // object window
334 while (WinGetMsg(hab,
335 &qmsg, // on stack
336 0,
337 0,
338 0))
339 {
340 // current message for our object window?
341 if ( (qmsg.hwnd == hwndNotify)
342 && (qmsg.msg == WM_USER)
343 )
344 // yes: this means the file dlg has been
345 // dismissed, and we can get outta here
346 fQuit = TRUE;
347
348 WinDispatchMsg(hab,
349 &qmsg); // on stack
350
351 if (fQuit)
352 break;
353 }
354
355 // return hwndReturn from XFLDR.DLL;
356 // this is either TRUE or FALSE (stupid cast)
357 hwndReturn = pfdShared->hwndReturn;
358
359 // copy stuff back from shared block (filled
360 // by WPS code) into caller's FILEDLG
361 pfd->lReturn = pfdShared->fd.lReturn;
362 pfd->lSRC = pfdShared->fd.lSRC;
363 memcpy(pfd->szFullFile,
364 pfdShared->fd.szFullFile,
365 sizeof(pfd->szFullFile));
366
367 pfd->ulFQFCount = pfdShared->fd.ulFQFCount;
368 pfd->sEAType = pfdShared->fd.sEAType;
369 // @@todo: papszFQFilename for multiple selections
370
371 // re-enable the owner and bring it back to top
372 if (hwndOwner)
373 {
374 WinEnableWindow(hwndOwner, TRUE);
375 WinSetActiveWindow(HWND_DESKTOP, hwndOwner);
376 }
377 }
378 } // end DosGiveSharedMem(pfdShared,
379
380 DosFreeMem(pfdShared);
381
382 } // end DosAllocSharedMem
383
384 } // end if hwndNotify and stuff
385
386 if (hwndNotify)
387 WinDestroyWindow(hwndNotify);
388
389 } // end if !arc = DosGetNamedSharedMem((PVOID*)&pXwpGlobalShared,
390 } // end if if ( (pfd)
391
392 return hwndReturn;
393}
394
Note: See TracBrowser for help on using the repository browser.