blob: 73d0dca420051622b385564af8c94370e7c4decb [file] [log] [blame]
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001/*
2 * MMIO functions
3 *
4 * Copyright 1998 Andrew Taylor
Alexandre Julliard767e6f61998-08-09 12:47:43 +00005 * Copyright 1998 Ove Kåven
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00006 *
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00007 */
8
9
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000010#include <stdlib.h>
11#include <string.h>
12#include <errno.h>
Jim Aston2e1cafa1999-03-14 16:35:05 +000013#include "windef.h"
Marcus Meissner61afa331999-02-22 10:16:00 +000014#include "wine/winbase16.h"
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000015#include "heap.h"
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000016#include "file.h"
17#include "mmsystem.h"
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000018#include "debug.h"
19#include "xmalloc.h"
20
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000021DEFAULT_DEBUG_CHANNEL(mmio)
22
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000023/**************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +000024 * mmioDosIOProc [internal]
25 */
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000026static LRESULT mmioDosIOProc(LPMMIOINFO16 lpmmioinfo, UINT16 uMessage, LPARAM lParam1, LPARAM lParam2) {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +000027 TRACE(mmio, "(%p, %X, %ld, %ld);\n", lpmmioinfo, uMessage, lParam1, lParam2);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000028
29 switch (uMessage) {
30
31 case MMIOM_OPEN: {
32 /* Parameters:
33 * lParam1 = szFileName parameter from mmioOpen
Alexandre Julliard85ed45e1998-08-22 19:03:56 +000034 * lParam2 = reserved (we use it for 16-bitness)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000035 * Returns: zero on success, error code on error
36 * NOTE: lDiskOffset automatically set to zero
37 */
38
39 OFSTRUCT ofs;
40 LPSTR szFileName = (LPSTR) lParam1;
41
42 if (lpmmioinfo->dwFlags & MMIO_GETTEMP) {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +000043 FIXME(mmio, "MMIO_GETTEMP not implemented\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000044 return MMIOERR_CANNOTOPEN;
45 }
46
47 /* if filename NULL, assume open file handle in adwInfo[0] */
Alexandre Julliard85ed45e1998-08-22 19:03:56 +000048 if (!szFileName) {
49 if (lParam2) lpmmioinfo->adwInfo[0] =
Alexandre Julliarda3960291999-02-26 11:11:13 +000050 FILE_GetHandle(lpmmioinfo->adwInfo[0]);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000051 return 0;
Alexandre Julliard85ed45e1998-08-22 19:03:56 +000052 }
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000053
54 lpmmioinfo->adwInfo[0] =
Alexandre Julliarda3960291999-02-26 11:11:13 +000055 (DWORD) OpenFile(szFileName, &ofs, lpmmioinfo->dwFlags);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000056 if (lpmmioinfo->adwInfo[0] == -1)
57 return MMIOERR_CANNOTOPEN;
58
59 return 0;
60 }
61
62 case MMIOM_CLOSE: {
63 /* Parameters:
64 * lParam1 = wFlags parameter from mmioClose
65 * lParam2 = unused
66 * Returns: zero on success, error code on error
67 */
68
69 UINT16 uFlags = (UINT16) lParam1;
70
71 if (uFlags & MMIO_FHOPEN)
72 return 0;
73
Alexandre Julliarda3960291999-02-26 11:11:13 +000074 _lclose((HFILE)lpmmioinfo->adwInfo[0]);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000075 return 0;
76
77 }
78
79 case MMIOM_READ: {
80 /* Parameters:
81 * lParam1 = huge pointer to read buffer
82 * lParam2 = number of bytes to read
83 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
84 * in wErrorRet)
85 * NOTE: lDiskOffset should be updated
86 */
87
88 HPSTR pch = (HPSTR) lParam1;
89 LONG cch = (LONG) lParam2;
90 LONG count;
91
Alexandre Julliarda3960291999-02-26 11:11:13 +000092 count = _lread((HFILE)lpmmioinfo->adwInfo[0], pch, cch);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000093 if (count != -1)
94 lpmmioinfo->lDiskOffset += count;
95
96 return count;
97 }
98
99 case MMIOM_WRITE:
100 case MMIOM_WRITEFLUSH: {
101 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
102
103 /* Parameters:
104 * lParam1 = huge pointer to write buffer
105 * lParam2 = number of bytes to write
106 * Returns: number of bytes written, -1 for error (error code in
107 * wErrorRet)
108 * NOTE: lDiskOffset should be updated
109 */
110
111 HPSTR pch = (HPSTR) lParam1;
112 LONG cch = (LONG) lParam2;
113 LONG count;
114
Alexandre Julliarda3960291999-02-26 11:11:13 +0000115 count = _hwrite((HFILE)lpmmioinfo->adwInfo[0], pch, cch);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000116 if (count != -1)
117 lpmmioinfo->lDiskOffset += count;
118
119 return count;
120 }
121
122 case MMIOM_SEEK: {
123 /* Parameters:
124 * lParam1 = new position
125 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
126 * Returns: new file postion, -1 on error
127 * NOTE: lDiskOffset should be updated
128 */
129
130 LONG Offset = (LONG) lParam1;
131 LONG Whence = (LONG) lParam2;
132 LONG pos;
133
Alexandre Julliarda3960291999-02-26 11:11:13 +0000134 pos = _llseek((HFILE)lpmmioinfo->adwInfo[0], Offset, Whence);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000135 if (pos != -1)
136 lpmmioinfo->lDiskOffset = pos;
137
138 return pos;
139 }
140
141 case MMIOM_RENAME: {
142 /* Parameters:
143 * lParam1 = old name
144 * lParam2 = new name
145 * Returns: zero on success, non-zero on failure
146 */
147
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000148 FIXME(mmio, "MMIOM_RENAME unimplemented\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000149 return MMIOERR_FILENOTFOUND;
150 }
151
152 default:
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000153 FIXME(mmio, "unexpected message %u\n", uMessage);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000154 return 0;
155 }
156
157 return 0;
158}
159
160/**************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000161* mmioMemIOProc [internal]
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000162*/
163static LRESULT mmioMemIOProc(LPMMIOINFO16 lpmmioinfo, UINT16 uMessage, LPARAM lParam1, LPARAM lParam2) {
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000164 TRACE(mmio,"(%p,0x%04x,0x%08lx,0x%08lx)\n",lpmmioinfo,uMessage,lParam1,lParam2);
165 switch (uMessage) {
166
167 case MMIOM_OPEN: {
168 /* Parameters:
169 * lParam1 = filename (must be NULL)
170 * lParam2 = reserved (we use it for 16-bitness)
171 * Returns: zero on success, error code on error
172 * NOTE: lDiskOffset automatically set to zero
173 */
174
175 if (!(lpmmioinfo->dwFlags & MMIO_CREATE))
176 lpmmioinfo->pchEndRead = lpmmioinfo->pchEndWrite;
177
178 return 0;
179 }
180
181 case MMIOM_CLOSE: {
182 /* Parameters:
183 * lParam1 = wFlags parameter from mmioClose
184 * lParam2 = unused
185 * Returns: zero on success, error code on error
186 */
187
188 return 0;
189
190 }
191
192 case MMIOM_READ: {
193 /* Parameters:
194 * lParam1 = huge pointer to read buffer
195 * lParam2 = number of bytes to read
196 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
197 * in wErrorRet)
198 * NOTE: lDiskOffset should be updated
199 */
200
James Juranc2a10631999-01-28 16:33:44 +0000201 /* HPSTR pch = (HPSTR) lParam1; */
202 /* LONG cch = (LONG) lParam2; */
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000203
204 FIXME(mmio,"MMIOM_READ on memory files should not occur, buffer may be lost!\n");
205 return 0;
206 }
207
208 case MMIOM_WRITE:
209 case MMIOM_WRITEFLUSH: {
210 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
211
212 /* Parameters:
213 * lParam1 = huge pointer to write buffer
214 * lParam2 = number of bytes to write
215 * Returns: number of bytes written, -1 for error (error code in
216 * wErrorRet)
217 * NOTE: lDiskOffset should be updated
218 */
219
James Juranc2a10631999-01-28 16:33:44 +0000220 /* HPSTR pch = (HPSTR) lParam1; */
221 /* LONG cch = (LONG) lParam2; */
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000222
223 FIXME(mmio,"MMIOM_WRITE on memory files should not occur, buffer may be lost!\n");
224 return 0;
225 }
226
227 case MMIOM_SEEK: {
228 /* Parameters:
229 * lParam1 = new position
230 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
231 * Returns: new file postion, -1 on error
232 * NOTE: lDiskOffset should be updated
233 */
234
James Juranc2a10631999-01-28 16:33:44 +0000235 /* LONG Offset = (LONG) lParam1; */
236 /* LONG Whence = (LONG) lParam2; */
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000237
238 FIXME(mmio,"MMIOM_SEEK on memory files should not occur, buffer may be lost!\n");
239 return -1;
240 }
241
242 default:
243 FIXME(mmio, "unexpected message %u\n", uMessage);
244 return 0;
245 }
246
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000247 return 0;
248}
249
250/**************************************************************************
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000251 * MMIO_Open [internal]
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000252 */
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000253static HMMIO16 MMIO_Open(LPSTR szFileName, MMIOINFO16 * lpmmioinfo,
254 DWORD dwOpenFlags, int use16)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000255{
256 LPMMIOINFO16 lpmminfo;
257 HMMIO16 hmmio;
258 UINT16 result;
259
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000260 TRACE(mmio, "('%s', %p, %08lX);\n", szFileName, lpmmioinfo, dwOpenFlags);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000261
Eric Pouechb94ac221999-04-03 11:17:31 +0000262 if (dwOpenFlags & MMIO_PARSE) {
263 char buffer[MAX_PATH];
264
265 if (GetFullPathNameA(szFileName, sizeof(buffer), buffer, NULL) >= sizeof(buffer))
266 return (HMMIO16)FALSE;
267 strcpy(szFileName, buffer);
268 return (HMMIO16)TRUE;
269 }
270
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000271 hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
272 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
273 if (lpmminfo == NULL)
274 return 0;
275 memset(lpmminfo, 0, sizeof(MMIOINFO16));
276
277 /* assume DOS file if not otherwise specified */
278 if (!lpmmioinfo ||
279 (lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL)) {
280
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000281 lpmminfo->fccIOProc = FOURCC_DOS;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000282 lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
283 }
284 /* if just the four character code is present, look up IO proc */
285 else if (lpmmioinfo->pIOProc == NULL) {
286
287 lpmminfo->fccIOProc = lpmmioinfo->fccIOProc;
288 lpmminfo->pIOProc = mmioInstallIOProc16(lpmmioinfo->fccIOProc, NULL, MMIO_FINDPROC);
289
290 }
291 /* if IO proc specified, use it and specified four character code */
292 else {
293
294 lpmminfo->fccIOProc = lpmmioinfo->fccIOProc;
295 lpmminfo->pIOProc = lpmmioinfo->pIOProc;
296 }
297
298 if (dwOpenFlags & MMIO_ALLOCBUF) {
Eric Pouech46b68f01998-11-06 16:04:09 +0000299 if ((result = mmioSetBuffer16(hmmio, NULL, MMIO_DEFAULTBUFFER, 0))) {
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000300 if (lpmmioinfo)
301 lpmmioinfo->wErrorRet = result;
302 return 0;
303 }
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000304 } else
305 if (lpmminfo->fccIOProc == FOURCC_MEM) {
Eric Pouech46b68f01998-11-06 16:04:09 +0000306 if ((result = mmioSetBuffer16(hmmio, lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer, 0))) {
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000307 if (lpmmioinfo)
308 lpmmioinfo->wErrorRet = result;
309 return 0;
310 }
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000311 }
312
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000313 lpmminfo->dwFlags = dwOpenFlags;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000314 lpmminfo->hmmio = hmmio;
315
316 /* call IO proc to actually open file */
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000317 result = (UINT16) mmioSendMessage(hmmio, MMIOM_OPEN, (LPARAM) szFileName, (LPARAM) use16);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000318
319 GlobalUnlock16(hmmio);
320
321 if (result != 0) {
322 GlobalFree16(hmmio);
323 return 0;
324 }
325
326 return hmmio;
327}
328
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000329/**************************************************************************
330 * mmioOpenW [WINMM.123]
331 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000332HMMIO WINAPI mmioOpenW(LPWSTR szFileName, MMIOINFO * lpmmioinfo,
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000333 DWORD dwOpenFlags)
334{
335 LPSTR szFn = HEAP_strdupWtoA(GetProcessHeap(),0,szFileName);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000336 HMMIO ret = MMIO_Open(szFn,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags,FALSE);
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000337
338 HeapFree(GetProcessHeap(),0,szFn);
339 return ret;
340}
341
342/**************************************************************************
343 * mmioOpenA [WINMM.122]
344 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000345HMMIO WINAPI mmioOpenA(LPSTR szFileName, MMIOINFO * lpmmioinfo,
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000346 DWORD dwOpenFlags)
347{
348 return MMIO_Open(szFileName,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags,FALSE);
349}
350
351/**************************************************************************
352 * mmioOpen [MMSYSTEM.1210]
353 */
354HMMIO16 WINAPI mmioOpen16(LPSTR szFileName, MMIOINFO16 * lpmmioinfo,
355 DWORD dwOpenFlags)
356{
357 return MMIO_Open(szFileName,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags,TRUE);
358}
359
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000360
361/**************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000362 * mmioClose [WINMM.114]
363 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000364MMRESULT WINAPI mmioClose(HMMIO hmmio, UINT uFlags)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000365{
366 LPMMIOINFO16 lpmminfo;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000367 MMRESULT result;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000368
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000369 TRACE(mmio, "(%04X, %04X);\n", hmmio, uFlags);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000370
371 lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
372 if (lpmminfo == NULL)
373 return 0;
374
375 /* flush the file - if error reported, ignore */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000376 if (mmioFlush(hmmio, MMIO_EMPTYBUF) != 0)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000377 lpmminfo->dwFlags &= ~MMIO_DIRTY;
378
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000379 result = mmioSendMessage(hmmio,MMIOM_CLOSE,(LPARAM)uFlags,(LPARAM)0);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000380
Eric Pouech46b68f01998-11-06 16:04:09 +0000381 mmioSetBuffer16(hmmio, NULL, 0, 0);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000382
383 GlobalUnlock16(hmmio);
384 GlobalFree16(hmmio);
385
386 return result;
387}
388
389
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000390/**************************************************************************
391 * mmioClose [MMSYSTEM.1211]
392 */
393MMRESULT16 WINAPI mmioClose16(HMMIO16 hmmio, UINT16 uFlags)
394{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000395 return mmioClose(hmmio,uFlags);
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000396}
397
398
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000399
400/**************************************************************************
Eric Pouech46b68f01998-11-06 16:04:09 +0000401 * mmioRead [WINMM.124]
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000402 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000403LONG WINAPI mmioRead(HMMIO hmmio, HPSTR pch, LONG cch)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000404{
405 LONG count;
406 LPMMIOINFO16 lpmminfo;
407
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000408 TRACE(mmio, "(%04X, %p, %ld);\n", hmmio, pch, cch);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000409
410 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
411 if (lpmminfo == NULL)
412 return -1;
413
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000414 if (lpmminfo->pchNext != lpmminfo->pchEndRead) {
415 count = lpmminfo->pchEndRead - lpmminfo->pchNext;
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000416 if (count > cch || count < 0) count = cch;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000417 memcpy(pch, lpmminfo->pchNext, count);
418 lpmminfo->pchNext += count;
419 pch += count;
420 cch -= count;
421 } else
422 count = 0;
423
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000424 if (cch&&(lpmminfo->fccIOProc!=FOURCC_MEM)) {
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000425 if (lpmminfo->cchBuffer) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000426 mmioFlush(hmmio, MMIO_EMPTYBUF);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000427
428 while (cch) {
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000429 LONG size;
430 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
431 lpmminfo->pchNext = lpmminfo->pchBuffer;
432 lpmminfo->pchEndRead = lpmminfo->pchBuffer;
433 size = mmioSendMessage(hmmio, MMIOM_READ,
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000434 (LPARAM) lpmminfo->pchBuffer,
435 (LPARAM) lpmminfo->cchBuffer);
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000436 if (size<=0) break;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000437 lpmminfo->pchEndRead = lpmminfo->pchBuffer + size;
438 if (size > cch) size = cch;
439 memcpy(pch, lpmminfo->pchNext, size);
440 lpmminfo->pchNext += size;
441 pch += size;
442 cch -= size;
443 count += size;
444 }
445 } else {
446 count += mmioSendMessage(hmmio, MMIOM_READ, (LPARAM) pch, (LPARAM) cch);
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000447 if (count>0) lpmminfo->lBufOffset += count;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000448 }
449 }
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000450
451 GlobalUnlock16(hmmio);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000452 TRACE(mmio, "count=%ld\n", count);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000453 return count;
454}
455
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000456/**************************************************************************
457 * mmioRead [MMSYSTEM.1212]
458 */
459LONG WINAPI mmioRead16(HMMIO16 hmmio, HPSTR pch, LONG cch)
460{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000461 return mmioRead(hmmio,pch,cch);
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000462}
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000463
464/**************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000465 * mmioWrite [WINMM.133]
466 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000467LONG WINAPI mmioWrite(HMMIO hmmio, HPCSTR pch, LONG cch)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000468{
469 LONG count;
470 LPMMIOINFO16 lpmminfo;
471
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000472 TRACE(mmio, "(%04X, %p, %ld);\n", hmmio, pch, cch);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000473
474 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
475 if (lpmminfo == NULL)
476 return -1;
477
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000478 if (lpmminfo->cchBuffer) {
479 count = 0;
480 while (cch) {
481 if (lpmminfo->pchNext != lpmminfo->pchEndWrite) {
482 count = lpmminfo->pchEndWrite - lpmminfo->pchNext;
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000483 if (count > cch || count < 0) count = cch;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000484 memcpy(lpmminfo->pchNext, pch, count);
485 lpmminfo->pchNext += count;
486 pch += count;
487 cch -= count;
488 lpmminfo->dwFlags |= MMIO_DIRTY;
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000489 } else
490 if (lpmminfo->fccIOProc==FOURCC_MEM) {
491 if (lpmminfo->adwInfo[0]) {
492 /* from where would we get the memory handle? */
493 FIXME(mmio, "memory file expansion not implemented!\n");
494 } else break;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000495 }
496
497 if (lpmminfo->pchNext == lpmminfo->pchEndWrite
Alexandre Julliarda3960291999-02-26 11:11:13 +0000498 && mmioFlush(hmmio, MMIO_EMPTYBUF)) break;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000499 }
500 } else {
501 count = mmioSendMessage(hmmio, MMIOM_WRITE, (LPARAM) pch, (LPARAM) cch);
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000502 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000503 }
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000504
505 GlobalUnlock16(hmmio);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000506 TRACE(mmio, "count=%ld\n", count);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000507 return count;
508}
509
510/**************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000511 * mmioWrite [MMSYSTEM.1213]
512 */
513LONG WINAPI mmioWrite16(HMMIO16 hmmio, HPCSTR pch, LONG cch)
514{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000515 return mmioWrite(hmmio,pch,cch);
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000516}
517
518/**************************************************************************
519 * mmioSeek [MMSYSTEM.1214]
520 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000521LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, INT iOrigin)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000522{
523 int offset;
524 LPMMIOINFO16 lpmminfo;
525
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000526 TRACE(mmio, "(%04X, %08lX, %d);\n", hmmio, lOffset, iOrigin);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000527
528 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
529 if (lpmminfo == NULL)
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000530 return -1;
531
532 offset = (iOrigin==SEEK_SET)?(lOffset - lpmminfo->lBufOffset):
533 (iOrigin==SEEK_CUR)?(lOffset +
534 (lpmminfo->pchNext - lpmminfo->pchBuffer)):-1;
535
536 if ((lpmminfo->cchBuffer<0)||
537 ((offset>=0)&&(offset<=(lpmminfo->pchEndRead-lpmminfo->pchBuffer)))) {
538 lpmminfo->pchNext = lpmminfo->pchBuffer + offset;
539 GlobalUnlock16(hmmio);
540 return lpmminfo->lBufOffset + offset;
541 }
542
Alexandre Julliarda3960291999-02-26 11:11:13 +0000543 if ((lpmminfo->fccIOProc==FOURCC_MEM)||mmioFlush(hmmio, MMIO_EMPTYBUF)) {
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000544 GlobalUnlock16(hmmio);
545 return -1;
546 }
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000547
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000548 offset = mmioSendMessage(hmmio, MMIOM_SEEK, (LPARAM) lOffset, (LPARAM) iOrigin);
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000549 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000550
551 GlobalUnlock16(hmmio);
552 return offset;
553}
554
555/**************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000556 * mmioSeek [MMSYSTEM.1214]
557 */
558LONG WINAPI mmioSeek16(HMMIO16 hmmio, LONG lOffset, INT16 iOrigin)
559{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000560 return mmioSeek(hmmio,lOffset,iOrigin);
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000561}
562
563/**************************************************************************
564 * mmioGetInfo [MMSYSTEM.1215]
565 */
566UINT16 WINAPI mmioGetInfo16(HMMIO16 hmmio, MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000567{
568 LPMMIOINFO16 lpmminfo;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000569 TRACE(mmio, "mmioGetInfo\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000570 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
571 if (lpmminfo == NULL) return 0;
572 memcpy(lpmmioinfo, lpmminfo, sizeof(MMIOINFO16));
573 GlobalUnlock16(hmmio);
574 return 0;
575}
576
577/**************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000578 * mmioGetInfo [WINMM.118]
579 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000580UINT WINAPI mmioGetInfo(HMMIO hmmio, MMIOINFO*lpmmioinfo, UINT uFlags)
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000581{
582 MMIOINFO16 mmioinfo;
583 LPMMIOINFO16 lpmminfo=&mmioinfo;
584 UINT16 ret;
585
586 TRACE(mmio, "(0x%04x,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags);
587 ret = mmioGetInfo16(hmmio,&mmioinfo,uFlags);
588 if (!ret)
589 return 0;
590 lpmmioinfo->dwFlags = lpmminfo->dwFlags;
591 lpmmioinfo->fccIOProc = lpmminfo->fccIOProc;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000592 lpmmioinfo->pIOProc = (LPMMIOPROC)lpmminfo->pIOProc;
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000593 lpmmioinfo->wErrorRet = lpmminfo->wErrorRet;
594 lpmmioinfo->htask = lpmminfo->htask;
595 lpmmioinfo->cchBuffer = lpmminfo->cchBuffer;
596 lpmmioinfo->pchBuffer = lpmminfo->pchBuffer;
597 lpmmioinfo->pchNext = lpmminfo->pchNext;
598 lpmmioinfo->pchEndRead = lpmminfo->pchEndRead;
599 lpmmioinfo->pchEndWrite = lpmminfo->pchEndWrite;
600 lpmmioinfo->lBufOffset = lpmminfo->lBufOffset;
601 lpmmioinfo->lDiskOffset = lpmminfo->lDiskOffset;
602 memcpy(lpmmioinfo->adwInfo,lpmminfo->adwInfo,sizeof(lpmminfo->adwInfo));
603 lpmmioinfo->dwReserved1 = lpmminfo->dwReserved1;
604 lpmmioinfo->dwReserved2 = lpmminfo->dwReserved2;
605 lpmmioinfo->hmmio = lpmminfo->hmmio;
606 return 0;
607}
608
609/**************************************************************************
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000610 * mmioSetInfo [MMSYSTEM.1216]
611 */
612UINT16 WINAPI mmioSetInfo16(HMMIO16 hmmio, const MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
613{
614 LPMMIOINFO16 lpmminfo;
615 TRACE(mmio, "mmioSetInfo\n");
616 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
617 if (lpmminfo == NULL) return 0;
618 lpmminfo->pchNext = lpmmioinfo->pchNext;
619 lpmminfo->pchEndRead = lpmmioinfo->pchEndRead;
620 GlobalUnlock16(hmmio);
621 return 0;
622}
623
624/**************************************************************************
625 * mmioSetInfo [WINMM.130]
626 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000627UINT WINAPI mmioSetInfo(HMMIO hmmio, const MMIOINFO * lpmmioinfo, UINT uFlags)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000628{
629 LPMMIOINFO16 lpmminfo;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000630 TRACE(mmio, "mmioSetInfo\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000631 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
632 if (lpmminfo == NULL) return 0;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000633 lpmminfo->pchNext = lpmmioinfo->pchNext;
634 lpmminfo->pchEndRead = lpmmioinfo->pchEndRead;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000635 GlobalUnlock16(hmmio);
636 return 0;
637}
638
639/**************************************************************************
Eric Pouech46b68f01998-11-06 16:04:09 +0000640* mmioSetBuffer [WINMM.129]
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000641*/
Alexandre Julliarda3960291999-02-26 11:11:13 +0000642UINT WINAPI mmioSetBuffer(HMMIO hmmio, LPSTR pchBuffer,
643 LONG cchBuffer, UINT uFlags)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000644{
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000645 LPMMIOINFO16 lpmminfo;
646
Alexandre Julliarda3960291999-02-26 11:11:13 +0000647 if (mmioFlush(hmmio, MMIO_EMPTYBUF) != 0)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000648 return MMIOERR_CANNOTWRITE;
649
650 TRACE(mmio, "(hmmio=%04x, pchBuf=%p, cchBuf=%ld, uFlags=%#08x)\n",
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000651 hmmio, pchBuffer, cchBuffer, uFlags);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000652
653 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
654 if (lpmminfo == NULL) return 0;
655 if ((!cchBuffer || pchBuffer) && lpmminfo->dwFlags&MMIO_ALLOCBUF) {
656 GlobalUnlock16(lpmminfo->dwReserved1);
657 GlobalFree16(lpmminfo->dwReserved1);
658 lpmminfo->dwFlags &= ~MMIO_ALLOCBUF;
659 }
660 if (pchBuffer) {
661 lpmminfo->pchBuffer = pchBuffer;
Eric Pouech46b68f01998-11-06 16:04:09 +0000662 } else if (lpmminfo->dwFlags&MMIO_ALLOCBUF) {
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000663 HGLOBAL16 hNewBuf;
664 GlobalUnlock16(lpmminfo->dwReserved1);
665 hNewBuf = GlobalReAlloc16(lpmminfo->dwReserved1, cchBuffer, 0);
666 if (!hNewBuf) {
667 /* FIXME: this assumes the memory block didn't move */
668 GlobalLock16(lpmminfo->dwReserved1);
669 GlobalUnlock16(hmmio);
670 return MMIOERR_OUTOFMEMORY;
671 }
672 lpmminfo->dwReserved1 = hNewBuf;
673 lpmminfo->pchBuffer = GlobalLock16(hNewBuf);
Eric Pouech46b68f01998-11-06 16:04:09 +0000674 } else if (cchBuffer) {
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000675 HGLOBAL16 hNewBuf = GlobalAlloc16(GMEM_MOVEABLE, cchBuffer);
676 if (!hNewBuf) {
677 GlobalUnlock16(hmmio);
678 return MMIOERR_OUTOFMEMORY;
679 }
680 lpmminfo->dwReserved1 = hNewBuf;
681 lpmminfo->pchBuffer = GlobalLock16(hNewBuf);
682 lpmminfo->dwFlags |= MMIO_ALLOCBUF;
683 } else
684 lpmminfo->pchBuffer = NULL;
685 lpmminfo->cchBuffer = cchBuffer;
686 lpmminfo->pchNext = lpmminfo->pchBuffer;
687 lpmminfo->pchEndRead = lpmminfo->pchBuffer;
688 lpmminfo->pchEndWrite = lpmminfo->pchBuffer + cchBuffer;
689 lpmminfo->lBufOffset = 0;
690
691 GlobalUnlock16(hmmio);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000692 return (UINT16) 0;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000693}
694
695/**************************************************************************
Eric Pouech46b68f01998-11-06 16:04:09 +0000696* mmioSetBuffer [MMSYSTEM.1217]
697*/
698UINT16 WINAPI mmioSetBuffer16(HMMIO16 hmmio, LPSTR pchBuffer,
699 LONG cchBuffer, UINT16 uFlags)
700{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000701 return mmioSetBuffer(hmmio, pchBuffer, cchBuffer, uFlags);
Eric Pouech46b68f01998-11-06 16:04:09 +0000702}
703
704/**************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000705 * mmioFlush [WINMM.117]
706 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000707UINT WINAPI mmioFlush(HMMIO hmmio, UINT uFlags)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000708{
709 LPMMIOINFO16 lpmminfo;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000710 TRACE(mmio, "(%04X, %04X)\n", hmmio, uFlags);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000711 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
712 if (lpmminfo == NULL) return 0;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000713
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000714 if ((!lpmminfo->cchBuffer)||(lpmminfo->fccIOProc==FOURCC_MEM)) {
715 GlobalUnlock16(hmmio);
716 return 0;
717 }
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000718 /* not quite sure what to do here, but I'll guess */
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000719 if (lpmminfo->dwFlags & MMIO_DIRTY) {
720 mmioSendMessage(hmmio, MMIOM_SEEK,
721 (LPARAM) lpmminfo->lBufOffset,
722 (LPARAM) SEEK_SET);
723 mmioSendMessage(hmmio, MMIOM_WRITE,
724 (LPARAM) lpmminfo->pchBuffer,
725 (LPARAM) (lpmminfo->pchNext - lpmminfo->pchBuffer) );
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000726 lpmminfo->dwFlags &= ~MMIO_DIRTY;
727 }
728 if (uFlags & MMIO_EMPTYBUF) {
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000729 /* seems Windows doesn't do any seeking here, hopefully this
730 won't matter, otherwise a slight rewrite is necessary */
731 mmioSendMessage(hmmio, MMIOM_SEEK,
732 (LPARAM) (lpmminfo->lBufOffset +
733 (lpmminfo->pchNext - lpmminfo->pchBuffer)),
734 (LPARAM) SEEK_SET);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000735 lpmminfo->pchNext = lpmminfo->pchBuffer;
736 lpmminfo->pchEndRead = lpmminfo->pchBuffer;
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000737 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000738 }
739
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000740 GlobalUnlock16(hmmio);
741 return 0;
742}
743
744/**************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000745 * mmioFlush [MMSYSTEM.1218]
746 */
747UINT16 WINAPI mmioFlush16(HMMIO16 hmmio, UINT16 uFlags)
748{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000749 return mmioFlush(hmmio,uFlags);
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000750}
751
752/**************************************************************************
753 * mmioAdvance [MMSYSTEM.1219]
754 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000755UINT WINAPI mmioAdvance(HMMIO hmmio,MMIOINFO*lpmmioinfo,UINT uFlags)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000756{
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000757 LPMMIOINFO16 lpmminfo;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000758 TRACE(mmio, "mmioAdvance\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000759 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
760 if (lpmminfo == NULL) return 0;
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000761 if (!lpmminfo->cchBuffer) {
762 GlobalUnlock16(hmmio);
763 return MMIOERR_UNBUFFERED;
764 }
765 lpmminfo->pchNext = lpmmioinfo->pchNext;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000766 if (mmioFlush(hmmio, MMIO_EMPTYBUF)) {
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000767 GlobalUnlock16(hmmio);
768 return MMIOERR_CANNOTWRITE;
769 }
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000770 if (uFlags == MMIO_READ)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000771 lpmmioinfo->pchEndRead = lpmmioinfo->pchBuffer +
772 mmioSendMessage(hmmio, MMIOM_READ,
773 (LPARAM) lpmmioinfo->pchBuffer,
774 (LPARAM) lpmmioinfo->cchBuffer);
Eric Pouechb8742931999-03-15 15:16:13 +0000775#if 0 /* mmioFlush already did the writing */
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000776 if (uFlags == MMIO_WRITE)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000777 mmioSendMessage(hmmio, MMIOM_WRITE,
778 (LPARAM) lpmmioinfo->pchBuffer,
779 (LPARAM) lpmmioinfo->cchBuffer);
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000780#endif
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000781 lpmmioinfo->pchNext = lpmmioinfo->pchBuffer;
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000782 GlobalUnlock16(hmmio);
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000783 return 0;
784}
785
786/**************************************************************************
787 * mmioAdvance [MMSYSTEM.1219]
788 */
789UINT16 WINAPI mmioAdvance16(HMMIO16 hmmio,MMIOINFO16*lpmmioinfo,UINT16 uFlags)
790{
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000791 LPMMIOINFO16 lpmminfo;
792 TRACE(mmio, "mmioAdvance\n");
793 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
794 if (lpmminfo == NULL) return 0;
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000795 if (!lpmminfo->cchBuffer) {
796 GlobalUnlock16(hmmio);
797 return MMIOERR_UNBUFFERED;
798 }
799 lpmminfo->pchNext = lpmmioinfo->pchNext;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000800 if (mmioFlush(hmmio, MMIO_EMPTYBUF)) {
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000801 GlobalUnlock16(hmmio);
802 return MMIOERR_CANNOTWRITE;
803 }
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000804 if (uFlags == MMIO_READ)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000805 lpmmioinfo->pchEndRead = lpmmioinfo->pchBuffer +
806 mmioSendMessage(hmmio, MMIOM_READ,
807 (LPARAM) lpmmioinfo->pchBuffer,
808 (LPARAM) lpmmioinfo->cchBuffer);
Eric Pouechb8742931999-03-15 15:16:13 +0000809#if 0 /* mmioFlush already did the writing */
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000810 if (uFlags == MMIO_WRITE)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000811 mmioSendMessage(hmmio, MMIOM_WRITE,
812 (LPARAM) lpmmioinfo->pchBuffer,
813 (LPARAM) lpmmioinfo->cchBuffer);
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000814#endif
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000815 lpmmioinfo->pchNext = lpmmioinfo->pchBuffer;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000816 GlobalUnlock16(hmmio);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000817 return 0;
818}
819
820/**************************************************************************
821 * mmioStringToFOURCCA [WINMM.131]
822 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000823FOURCC WINAPI mmioStringToFOURCCA(LPCSTR sz, UINT uFlags)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000824{
825 return mmioStringToFOURCC16(sz,uFlags);
826}
827
828/**************************************************************************
829 * mmioStringToFOURCCW [WINMM.132]
830 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000831FOURCC WINAPI mmioStringToFOURCCW(LPCWSTR sz, UINT uFlags)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000832{
833 LPSTR szA = HEAP_strdupWtoA(GetProcessHeap(),0,sz);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000834 FOURCC ret = mmioStringToFOURCCA(szA,uFlags);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000835
836 HeapFree(GetProcessHeap(),0,szA);
837 return ret;
838}
839
840/**************************************************************************
841 * mmioStringToFOURCC [MMSYSTEM.1220]
842 */
843FOURCC WINAPI mmioStringToFOURCC16(LPCSTR sz, UINT16 uFlags)
844{
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000845 return mmioFOURCC(sz[0],sz[1],sz[2],sz[3]);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000846}
847
848/**************************************************************************
849* mmioInstallIOProc16 [MMSYSTEM.1221]
850*/
851LPMMIOPROC16 WINAPI mmioInstallIOProc16(FOURCC fccIOProc,
852 LPMMIOPROC16 pIOProc, DWORD dwFlags)
853{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000854 TRACE(mmio, "(%ld, %p, %08lX)\n",
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000855 fccIOProc, pIOProc, dwFlags);
856
857 if (dwFlags & MMIO_GLOBALPROC) {
Alexandre Julliard54c27111998-03-29 19:44:57 +0000858 FIXME(mmio, " global procedures not implemented\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000859 }
860
861 /* just handle the known procedures for now */
862 switch(dwFlags & (MMIO_INSTALLPROC|MMIO_REMOVEPROC|MMIO_FINDPROC)) {
863 case MMIO_INSTALLPROC:
864 return NULL;
865 case MMIO_REMOVEPROC:
866 return NULL;
867 case MMIO_FINDPROC:
868 if (fccIOProc == FOURCC_DOS)
869 return (LPMMIOPROC16) mmioDosIOProc;
870 else if (fccIOProc == FOURCC_MEM)
871 return (LPMMIOPROC16) mmioMemIOProc;
872 else
873 return NULL;
874 default:
875 return NULL;
876 }
877}
878
879/**************************************************************************
Eric Pouechb8742931999-03-15 15:16:13 +0000880 * mmioInstallIOProcA [WINMM.120]
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000881 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000882LPMMIOPROC WINAPI mmioInstallIOProcA(FOURCC fccIOProc,
883 LPMMIOPROC pIOProc, DWORD dwFlags)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000884{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000885 FIXME(mmio, "(%c%c%c%c,%p,0x%08lx) -- empty stub \n",
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000886 (char)((fccIOProc&0xff000000)>>24),
887 (char)((fccIOProc&0x00ff0000)>>16),
888 (char)((fccIOProc&0x0000ff00)>> 8),
889 (char)(fccIOProc&0x000000ff),
890 pIOProc, dwFlags );
891 return 0;
892}
893
894/**************************************************************************
895* mmioSendMessage [MMSYSTEM.1222]
896*/
897LRESULT WINAPI mmioSendMessage(HMMIO16 hmmio, UINT16 uMessage,
898 LPARAM lParam1, LPARAM lParam2)
899{
900 LPMMIOINFO16 lpmminfo;
901 LRESULT result;
902 const char *msg = NULL;
903
904#ifdef DEBUG_RUNTIME
905 switch (uMessage) {
906#define msgname(x) case x: msg = #x; break;
907 msgname(MMIOM_OPEN);
908 msgname(MMIOM_CLOSE);
909 msgname(MMIOM_READ);
910 msgname(MMIOM_WRITE);
911 msgname(MMIOM_WRITEFLUSH);
912 msgname(MMIOM_SEEK);
913 msgname(MMIOM_RENAME);
914#undef msgname
915 }
916#endif
917
918 if (msg)
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000919 TRACE(mmio, "(%04X, %s, %ld, %ld)\n",
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000920 hmmio, msg, lParam1, lParam2);
921 else
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000922 TRACE(mmio, "(%04X, %u, %ld, %ld)\n",
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000923 hmmio, uMessage, lParam1, lParam2);
924
925 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
926
927 if (lpmminfo && lpmminfo->pIOProc)
928 result = (*lpmminfo->pIOProc)((LPSTR)lpmminfo, uMessage, lParam1, lParam2);
929 else
930 result = MMSYSERR_INVALPARAM;
931
932 GlobalUnlock16(hmmio);
933
934 return result;
935}
936
937/**************************************************************************
938* mmioDescend [MMSYSTEM.1223]
939*/
940UINT16 WINAPI mmioDescend(HMMIO16 hmmio, MMCKINFO * lpck,
941 const MMCKINFO * lpckParent, UINT16 uFlags)
942{
Marcus Meissner9a73d861999-02-20 16:08:23 +0000943 DWORD dwOldPos;
944 MMCKINFO searchcki;
945 char ckid[5],fcc[5];
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000946
Marcus Meissner9a73d861999-02-20 16:08:23 +0000947 TRACE(mmio,"(%04X, %p, %p, %04X);\n",hmmio,lpck,lpckParent,uFlags);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000948
949 if (lpck == NULL)
950 return 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000951 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000952 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000953
954 if (lpckParent != NULL) {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000955 TRACE(mmio, "seek inside parent at %ld !\n", lpckParent->dwDataOffset);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000956 dwOldPos = mmioSeek(hmmio,lpckParent->dwDataOffset,SEEK_SET);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000957 }
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000958
Marcus Meissner72f12e71999-02-17 16:10:17 +0000959 /* The SDK docu says 'ckid' is used for all cases. Real World
960 * examples disagree -Marcus,990216.
961 */
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000962
Marcus Meissner9a73d861999-02-20 16:08:23 +0000963 searchcki.fccType = 0;
Marcus Meissner72f12e71999-02-17 16:10:17 +0000964 /* find_chunk looks for 'ckid' */
Marcus Meissner9a73d861999-02-20 16:08:23 +0000965 if (uFlags & MMIO_FINDCHUNK)
966 searchcki.ckid = lpck->ckid;
Marcus Meissner72f12e71999-02-17 16:10:17 +0000967 /* find_riff and find_list look for 'fccType' */
Marcus Meissner9a73d861999-02-20 16:08:23 +0000968 if (uFlags & MMIO_FINDLIST) {
969 searchcki.ckid = FOURCC_LIST;
970 searchcki.fccType = lpck->fccType;
Marcus Meissner72f12e71999-02-17 16:10:17 +0000971 }
Marcus Meissner9a73d861999-02-20 16:08:23 +0000972 if (uFlags & MMIO_FINDRIFF) {
973 searchcki.ckid = FOURCC_RIFF;
974 searchcki.fccType = lpck->fccType;
975 }
976 memcpy(&fcc,&(searchcki.fccType),4);fcc[4]=0;
977 memcpy(&ckid,&(searchcki.ckid),4);ckid[4]=0;
978 TRACE(mmio,"searching for %s.%s\n",ckid,searchcki.fccType?fcc:"<any>");
Marcus Meissner72f12e71999-02-17 16:10:17 +0000979
980 if (uFlags & (MMIO_FINDCHUNK|MMIO_FINDLIST|MMIO_FINDRIFF)) {
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000981 while (TRUE) {
982 LONG ix;
983
Alexandre Julliarda3960291999-02-26 11:11:13 +0000984 ix = mmioRead(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD));
Marcus Meissner9a73d861999-02-20 16:08:23 +0000985 if (ix < 2*sizeof(DWORD)) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000986 mmioSeek(hmmio, dwOldPos, SEEK_SET);
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000987 WARN(mmio, "return ChunkNotFound\n");
988 return MMIOERR_CHUNKNOTFOUND;
989 }
990 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000991 if (ix < lpck->dwDataOffset - dwOldPos) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000992 mmioSeek(hmmio, dwOldPos, SEEK_SET);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000993 WARN(mmio, "return ChunkNotFound\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000994 return MMIOERR_CHUNKNOTFOUND;
995 }
Marcus Meissner9a73d861999-02-20 16:08:23 +0000996 memcpy(ckid,&lpck->ckid,4);
997 memcpy(fcc,&lpck->fccType,4);
998 TRACE(mmio, "ckid=%s fcc=%s cksize=%08lX !\n",
999 ckid, searchcki.fccType?fcc:"<unused>",
1000 lpck->cksize
1001 );
1002 if ((searchcki.ckid == lpck->ckid) &&
1003 (!searchcki.fccType ||
1004 (searchcki.fccType == lpck->fccType)
1005 )
1006 )
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001007 break;
1008
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00001009 dwOldPos = lpck->dwDataOffset + lpck->cksize;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001010 mmioSeek(hmmio, dwOldPos, SEEK_SET);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001011 }
Marcus Meissner72f12e71999-02-17 16:10:17 +00001012 /* If we were looking for RIFF/LIST chunks, the final dataptr
1013 * is after the chunkid. If we were just looking for the chunk
1014 * it is after the cksize. So add 4 in RIFF/LIST case.
1015 */
1016 if (uFlags & (MMIO_FINDLIST|MMIO_FINDRIFF))
1017 lpck->dwDataOffset+=sizeof(DWORD);
1018 } else {
1019 /* FIXME: unverified, does it do this? */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001020 if (mmioRead(hmmio, (LPSTR)lpck, sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
1021 mmioSeek(hmmio, dwOldPos, SEEK_SET);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001022 WARN(mmio, "return ChunkNotFound 2nd\n");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001023 return MMIOERR_CHUNKNOTFOUND;
1024 }
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00001025 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
1026 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1027 lpck->dwDataOffset += sizeof(DWORD);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001028 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001029 mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET);
Marcus Meissner9a73d861999-02-20 16:08:23 +00001030 memcpy(ckid,&(lpck->ckid),4);
1031 TRACE(mmio, "lpck->ckid=%s lpck->cksize=%ld !\n", ckid, lpck->cksize);
1032 memcpy(fcc,&(lpck->fccType),4);
1033 TRACE(mmio, "lpck->fccType=%08lX (%s)!\n", lpck->fccType,searchcki.fccType?fcc:"");
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001034 return 0;
1035}
1036
1037/**************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001038 * mmioAscend [WINMM.113]
1039 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001040UINT WINAPI mmioAscend(HMMIO hmmio, MMCKINFO * lpck, UINT uFlags)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001041{
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001042 TRACE(mmio, "(%04X, %p, %04X);\n",
1043 hmmio, lpck, uFlags);
1044 if (lpck->dwFlags&MMIO_DIRTY) {
1045 DWORD dwOldPos, dwNewSize, dwSizePos;
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00001046
1047 TRACE(mmio, "chunk is marked MMIO_DIRTY, correcting chunk size\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +00001048 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001049 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
1050 dwNewSize = dwOldPos - lpck->dwDataOffset;
1051 if (dwNewSize != lpck->cksize) {
1052 TRACE(mmio, "dwNewSize=%ld\n", dwNewSize);
1053 lpck->cksize = dwNewSize;
1054
1055 dwSizePos = lpck->dwDataOffset - sizeof(DWORD);
1056 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1057 dwSizePos -= sizeof(DWORD);
1058 TRACE(mmio, "dwSizePos=%ld\n", dwSizePos);
1059
Alexandre Julliarda3960291999-02-26 11:11:13 +00001060 mmioSeek(hmmio, dwSizePos, SEEK_SET);
1061 mmioWrite(hmmio, (LPSTR)&dwNewSize, sizeof(DWORD));
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001062 }
1063 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001064 mmioSeek(hmmio,lpck->dwDataOffset+lpck->cksize,SEEK_SET);
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001065
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001066 return 0;
1067}
1068
1069/**************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001070 * mmioAscend [MMSYSTEM.1224]
1071 */
1072UINT16 WINAPI mmioAscend16(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
1073{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001074 return mmioAscend(hmmio,lpck,uFlags);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001075}
1076
1077/**************************************************************************
1078 * mmioCreateChunk [MMSYSTEM.1225]
1079 */
Eric Pouechc6d65e01998-11-24 15:27:43 +00001080UINT16 WINAPI mmioCreateChunk16(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001081{
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001082 DWORD dwOldPos;
1083 LONG ix;
1084
1085 TRACE(mmio, "(%04X, %p, %04X);\n",
1086 hmmio, lpck, uFlags);
1087
Alexandre Julliarda3960291999-02-26 11:11:13 +00001088 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001089 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
1090
1091 if (uFlags == MMIO_CREATELIST)
1092 lpck->ckid = FOURCC_LIST;
1093 else if (uFlags == MMIO_CREATERIFF)
1094 lpck->ckid = FOURCC_RIFF;
1095
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00001096 TRACE(mmio, "ckid=%08lX\n", lpck->ckid);
1097
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001098 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
1099 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1100 lpck->dwDataOffset += sizeof(DWORD);
1101 lpck->dwFlags = MMIO_DIRTY;
1102
Alexandre Julliarda3960291999-02-26 11:11:13 +00001103 ix = mmioWrite(hmmio, (LPSTR)lpck, lpck->dwDataOffset - dwOldPos);
Eric Pouechb8742931999-03-15 15:16:13 +00001104 TRACE(mmio, "after mmioWrite ix = %ld req = %ld, errno = %d\n",ix,lpck->dwDataOffset - dwOldPos,errno);
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001105 if (ix < lpck->dwDataOffset - dwOldPos) {
1106
Alexandre Julliarda3960291999-02-26 11:11:13 +00001107 mmioSeek(hmmio, dwOldPos, SEEK_SET);
Alexandre Julliard767e6f61998-08-09 12:47:43 +00001108 WARN(mmio, "return CannotWrite\n");
1109 return MMIOERR_CANNOTWRITE;
1110 }
1111
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001112 return 0;
1113}
1114
Eric Pouechc6d65e01998-11-24 15:27:43 +00001115/**************************************************************************
1116 * mmioCreateChunk [WINMM.115]
1117 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001118UINT WINAPI mmioCreateChunk(HMMIO hmmio, MMCKINFO * lpck, UINT uFlags)
Eric Pouechc6d65e01998-11-24 15:27:43 +00001119{
1120 return mmioCreateChunk16(hmmio, lpck, uFlags);
1121}
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001122
1123/**************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001124 * mmioRename [MMSYSTEM.1226]
1125 */
Eric Pouechc6d65e01998-11-24 15:27:43 +00001126UINT16 WINAPI mmioRename16(LPCSTR szFileName, LPCSTR szNewFileName,
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001127 MMIOINFO16 * lpmmioinfo, DWORD dwRenameFlags)
1128{
1129 UINT16 result;
1130 LPMMIOINFO16 lpmminfo;
1131 HMMIO16 hmmio;
1132
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001133 TRACE(mmio, "('%s', '%s', %p, %08lX);\n",
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001134 szFileName, szNewFileName, lpmmioinfo, dwRenameFlags);
1135
1136 hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
1137 lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
1138
1139 if (lpmmioinfo)
1140 memcpy(lpmminfo, lpmmioinfo, sizeof(MMIOINFO16));
1141
1142 /* assume DOS file if not otherwise specified */
1143 if (lpmminfo->fccIOProc == 0 && lpmminfo->pIOProc == NULL) {
1144
1145 lpmminfo->fccIOProc = mmioFOURCC('D', 'O', 'S', ' ');
1146 lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
1147
1148 }
1149 /* if just the four character code is present, look up IO proc */
1150 else if (lpmminfo->pIOProc == NULL) {
1151
1152 lpmminfo->pIOProc = mmioInstallIOProc16(lpmminfo->fccIOProc, NULL, MMIO_FINDPROC);
1153
1154 }
1155 /* (if IO proc specified, use it and specified four character code) */
1156
1157 result = (UINT16) mmioSendMessage(hmmio, MMIOM_RENAME, (LPARAM) szFileName, (LPARAM) szNewFileName);
1158
1159 GlobalUnlock16(hmmio);
1160 GlobalFree16(hmmio);
1161
1162 return result;
1163}
1164
Eric Pouechc6d65e01998-11-24 15:27:43 +00001165/**************************************************************************
1166 * mmioRenameA [WINMM.125]
1167 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001168UINT WINAPI mmioRenameA(LPCSTR szFileName, LPCSTR szNewFileName,
1169 MMIOINFO* lpmmioinfo, DWORD dwRenameFlags)
Eric Pouechc6d65e01998-11-24 15:27:43 +00001170{
1171 FIXME(mmio, "This may fail\n");
1172 return mmioRename16(szFileName, szNewFileName, (MMIOINFO16*)lpmmioinfo, dwRenameFlags);
1173}
1174
1175/**************************************************************************
1176 * mmioRenameW [WINMM.126]
1177 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001178UINT WINAPI mmioRenameW(LPCWSTR szFileName, LPCWSTR szNewFileName,
1179 MMIOINFO* lpmmioinfo, DWORD dwRenameFlags)
Eric Pouechc6d65e01998-11-24 15:27:43 +00001180{
1181 LPSTR szFn = HEAP_strdupWtoA(GetProcessHeap(), 0, szFileName);
1182 LPSTR sznFn = HEAP_strdupWtoA(GetProcessHeap(), 0, szNewFileName);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001183 UINT ret = mmioRenameA(szFn, sznFn, lpmmioinfo, dwRenameFlags);
Eric Pouechc6d65e01998-11-24 15:27:43 +00001184
1185 HeapFree(GetProcessHeap(),0,szFn);
1186 HeapFree(GetProcessHeap(),0,sznFn);
1187 return ret;
1188}