source: trunk/pdr/src/call_file_dlg.c

Last change on this file was 5, checked in by bart, 17 years ago

Initial check in of port driver source

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