Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

336 lines
8.3 KiB

  1. #include <windows.h>
  2. #include <windowsx.h>
  3. #include <mmsystem.h>
  4. #include "debug.h"
  5. #include "fileshar.h"
  6. #define MAXTASKS 10
  7. #ifdef WIN32
  8. #define CurrentProcess() ((HANDLE) GetCurrentProcess())
  9. #else
  10. #define CurrentProcess() ((HANDLE) GetCurrentPDB())
  11. #endif
  12. typedef struct {
  13. char szFile[256];
  14. DWORD dwOpenFlags;
  15. MMIOINFO mmioinfo;
  16. HANDLE htask;
  17. HMMIO hmmio;
  18. int i;
  19. LONG lOffset;
  20. HANDLE ahtask[MAXTASKS];
  21. HMMIO ahmmio[MAXTASKS];
  22. ULONG ulRef[MAXTASKS];
  23. } SHFILE, FAR * PSHFILE;
  24. BOOL GetProperTask(PSHFILE psh)
  25. {
  26. HANDLE htask = CurrentProcess();
  27. int i;
  28. if (htask == psh->htask)
  29. return (psh->hmmio != 0) && (psh->hmmio != (HMMIO) -1);
  30. for (i = 0; i < MAXTASKS; i++) {
  31. if (psh->ahtask[i] == htask) {
  32. Success:
  33. psh->hmmio = psh->ahmmio[i];
  34. psh->htask = htask;
  35. psh->i = i;
  36. mmioSeek(psh->hmmio, psh->lOffset, SEEK_SET);
  37. return (psh->hmmio != 0) && (psh->hmmio != (HMMIO) -1);
  38. }
  39. }
  40. for (i = 0; i < MAXTASKS; i++) {
  41. if (psh->ahtask[i] == 0) {
  42. DPF("Re-opening handle %lx in task %x\n", psh, htask);
  43. psh->ahmmio[i] = mmioOpen(psh->szFile, NULL, psh->dwOpenFlags);
  44. psh->ahtask[i] = htask;
  45. if (psh->ahmmio[i] == 0) {
  46. DPF("mmioOpen failed in GetProperTask!\n");
  47. return FALSE;
  48. }
  49. goto Success;
  50. }
  51. }
  52. DPF("File handle open in too many tasks!\n");
  53. return FALSE;
  54. }
  55. HSHFILE WINAPI shfileOpen(LPSTR szFileName, MMIOINFO FAR* lpmmioinfo,
  56. DWORD dwOpenFlags)
  57. {
  58. PSHFILE psh = (PSHFILE) GlobalAllocPtr(GHND | GMEM_SHARE, sizeof(SHFILE));
  59. if (!psh)
  60. return NULL;
  61. lstrcpy(psh->szFile, szFileName);
  62. psh->dwOpenFlags = dwOpenFlags;
  63. psh->hmmio = mmioOpen(szFileName, lpmmioinfo, dwOpenFlags);
  64. DPF("Opening handle %lx ('%s') in task %x, mode = %lx\n", psh, szFileName, CurrentProcess(), psh->dwOpenFlags);
  65. if (psh->hmmio == 0) {
  66. DPF("mmioOpen failed!\n");
  67. GlobalFreePtr(psh);
  68. return NULL;
  69. }
  70. psh->ahmmio[0] = psh->hmmio;
  71. psh->ahtask[0] = psh->htask = CurrentProcess();
  72. psh->ulRef[0] = 1; // !!! 0?
  73. return (HSHFILE) GlobalPtrHandle(psh);
  74. }
  75. UINT WINAPI shfileClose(HSHFILE hsh, UINT uFlags)
  76. {
  77. PSHFILE psh = (PSHFILE) GlobalLock((HGLOBAL) hsh);
  78. int i;
  79. for (i = 0; i < MAXTASKS; i++) {
  80. if (psh->ahtask[i] && psh->ahmmio[i]) {
  81. DPF("Handle %lx closed with ref count %ld in task %x\n", psh, psh->ulRef[i], psh->ahtask[i]);
  82. mmioClose(psh->ahmmio[i], 0);
  83. }
  84. }
  85. GlobalFreePtr(psh);
  86. return 0;
  87. }
  88. LONG WINAPI shfileRead(HSHFILE hsh, HPSTR pch, LONG cch)
  89. {
  90. PSHFILE psh = (PSHFILE) GlobalLock((HGLOBAL) hsh);
  91. if (!GetProperTask(psh))
  92. return -1;
  93. return mmioRead(psh->hmmio, pch, cch);
  94. }
  95. LONG WINAPI shfileWrite(HSHFILE hsh, const char _huge* pch, LONG cch)
  96. {
  97. PSHFILE psh = (PSHFILE) GlobalLock((HGLOBAL) hsh);
  98. if (!GetProperTask(psh))
  99. return -1;
  100. return mmioWrite(psh->hmmio, pch, cch);
  101. }
  102. LONG WINAPI shfileSeek(HSHFILE hsh, LONG lOffset, int iOrigin)
  103. {
  104. PSHFILE psh = (PSHFILE) GlobalLock((HGLOBAL) hsh);
  105. if (!GetProperTask(psh))
  106. return -1;
  107. psh->lOffset = mmioSeek(psh->hmmio, lOffset, iOrigin);
  108. return psh->lOffset;
  109. }
  110. LONG WINAPI shfileFlush(HSHFILE hsh, UINT uFlags)
  111. {
  112. PSHFILE psh = (PSHFILE) GlobalLock((HGLOBAL) hsh);
  113. return 0;
  114. }
  115. LONG WINAPI shfileAddRef(HSHFILE hsh)
  116. {
  117. PSHFILE psh = (PSHFILE) GlobalLock((HGLOBAL) hsh);
  118. if (!GetProperTask(psh))
  119. return -1;
  120. ++psh->ulRef[psh->i];
  121. // DPF("Handle %lx in task %x: ref++ == %ld\n", psh, psh->htask, psh->ulRef[psh->i]);
  122. return 0;
  123. }
  124. LONG WINAPI shfileRelease(HSHFILE hsh)
  125. {
  126. PSHFILE psh = (PSHFILE) GlobalLock((HGLOBAL) hsh);
  127. if (!GetProperTask(psh))
  128. return -1;
  129. if (--psh->ulRef[psh->i] <= 0) {
  130. DPF("Closing handle %lx in task %x\n", psh, psh->htask);
  131. psh->ahmmio[psh->i] = 0;
  132. psh->ahtask[psh->i] = 0;
  133. psh->ulRef[psh->i] = 0;
  134. mmioClose(psh->hmmio, 0);
  135. psh->hmmio = 0;
  136. psh->htask = 0;
  137. } else {
  138. // DPF("Handle %lx in task %x: ref-- == %ld\n", psh, psh->htask, psh->ulRef[psh->i]);
  139. }
  140. return 0;
  141. }
  142. static BYTE bPad;
  143. MMRESULT WINAPI
  144. shfileDescend(HSHFILE hshfile, LPMMCKINFO lpck, const LPMMCKINFO lpckParent, UINT wFlags)
  145. {
  146. FOURCC ckidFind; // chunk ID to find (or NULL)
  147. FOURCC fccTypeFind; // form/list type to find (or NULL)
  148. /* figure out what chunk id and form/list type to search for */
  149. if (wFlags & MMIO_FINDCHUNK)
  150. ckidFind = lpck->ckid, fccTypeFind = NULL;
  151. else
  152. if (wFlags & MMIO_FINDRIFF)
  153. ckidFind = FOURCC_RIFF, fccTypeFind = lpck->fccType;
  154. else
  155. if (wFlags & MMIO_FINDLIST)
  156. ckidFind = FOURCC_LIST, fccTypeFind = lpck->fccType;
  157. else
  158. ckidFind = fccTypeFind = NULL;
  159. lpck->dwFlags = 0L;
  160. while (TRUE)
  161. {
  162. UINT w;
  163. /* read the chunk header */
  164. if (shfileRead(hshfile, (HPSTR) lpck, 2 * sizeof(DWORD)) !=
  165. 2 * sizeof(DWORD))
  166. return MMIOERR_CHUNKNOTFOUND;
  167. /* store the offset of the data part of the chunk */
  168. if ((lpck->dwDataOffset = shfileSeek(hshfile, 0L, SEEK_CUR)) == -1)
  169. return MMIOERR_CANNOTSEEK;
  170. /* check for unreasonable chunk size */
  171. /* see if the chunk is within the parent chunk (if given) */
  172. if ((lpckParent != NULL) && (( lpck->dwDataOffset - 8L) >=
  173. (lpckParent->dwDataOffset + lpckParent->cksize)))
  174. return MMIOERR_CHUNKNOTFOUND;
  175. /* if the chunk if a 'RIFF' or 'LIST' chunk, read the
  176. * form type or list type
  177. */
  178. if ((lpck->ckid == FOURCC_RIFF) || (lpck->ckid == FOURCC_LIST))
  179. {
  180. if (shfileRead(hshfile, (HPSTR) &lpck->fccType,
  181. sizeof(DWORD)) != sizeof(DWORD))
  182. return MMIOERR_CHUNKNOTFOUND;
  183. }
  184. else
  185. lpck->fccType = NULL;
  186. /* if this is the chunk we're looking for, stop looking */
  187. if ( ((ckidFind == NULL) || (ckidFind == lpck->ckid)) &&
  188. ((fccTypeFind == NULL) || (fccTypeFind == lpck->fccType)) )
  189. break;
  190. /* ascend out of the chunk and try again */
  191. if ((w = shfileAscend(hshfile, lpck, 0)) != 0)
  192. return w;
  193. }
  194. return 0;
  195. }
  196. MMRESULT WINAPI
  197. shfileAscend(HSHFILE hshfile, LPMMCKINFO lpck, UINT wFlags)
  198. {
  199. if (lpck->dwFlags & MMIO_DIRTY)
  200. {
  201. /* <lpck> refers to a chunk created by shfileCreateChunk();
  202. * check that the chunk size that was written when
  203. * shfileCreateChunk() was called is the real chunk size;
  204. * if not, fix it
  205. */
  206. LONG lOffset; // current offset in file
  207. LONG lActualSize; // actual size of chunk data
  208. if ((lOffset = shfileSeek(hshfile, 0L, SEEK_CUR)) == -1)
  209. return MMIOERR_CANNOTSEEK;
  210. if ((lActualSize = lOffset - lpck->dwDataOffset) < 0)
  211. return MMIOERR_CANNOTWRITE;
  212. if (LOWORD(lActualSize) & 1)
  213. {
  214. /* chunk size is odd -- write a null pad byte */
  215. if (shfileWrite(hshfile, (HPSTR) &bPad, sizeof(bPad))
  216. != sizeof(bPad))
  217. return MMIOERR_CANNOTWRITE;
  218. }
  219. if (lpck->cksize == (DWORD)lActualSize)
  220. return 0;
  221. /* fix the chunk header */
  222. lpck->cksize = lActualSize;
  223. if (shfileSeek(hshfile, lpck->dwDataOffset
  224. - sizeof(DWORD), SEEK_SET) == -1)
  225. return MMIOERR_CANNOTSEEK;
  226. if (shfileWrite(hshfile, (HPSTR) &lpck->cksize,
  227. sizeof(DWORD)) != sizeof(DWORD))
  228. return MMIOERR_CANNOTWRITE;
  229. }
  230. /* seek to the end of the chunk, past the null pad byte
  231. * (which is only there if chunk size is odd)
  232. */
  233. if (shfileSeek(hshfile, lpck->dwDataOffset + lpck->cksize
  234. + (lpck->cksize & 1L), SEEK_SET) == -1)
  235. return MMIOERR_CANNOTSEEK;
  236. return 0;
  237. }
  238. MMRESULT WINAPI
  239. shfileCreateChunk(HSHFILE hshfile, LPMMCKINFO lpck, UINT wFlags)
  240. {
  241. int iBytes; // bytes to write
  242. LONG lOffset; // current offset in file
  243. /* store the offset of the data part of the chunk */
  244. if ((lOffset = shfileSeek(hshfile, 0L, SEEK_CUR)) == -1)
  245. return MMIOERR_CANNOTSEEK;
  246. lpck->dwDataOffset = lOffset + 2 * sizeof(DWORD);
  247. /* figure out if a form/list type needs to be written */
  248. if (wFlags & MMIO_CREATERIFF)
  249. lpck->ckid = FOURCC_RIFF, iBytes = 3 * sizeof(DWORD);
  250. else
  251. if (wFlags & MMIO_CREATELIST)
  252. lpck->ckid = FOURCC_LIST, iBytes = 3 * sizeof(DWORD);
  253. else
  254. iBytes = 2 * sizeof(DWORD);
  255. /* write the chunk header */
  256. if (shfileWrite(hshfile, (HPSTR) lpck, (LONG) iBytes) != (LONG) iBytes)
  257. return MMIOERR_CANNOTWRITE;
  258. lpck->dwFlags = MMIO_DIRTY;
  259. return 0;
  260. }