Source code of Windows XP (NT5)
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.

251 lines
6.4 KiB

  1. /*
  2. * file.c
  3. *
  4. * send files on request over a named pipe.
  5. *
  6. * supports requests to package up a file and send it over a named pipe.
  7. *
  8. * Geraint Davies, August 92
  9. */
  10. #include <windows.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include "sumserve.h"
  14. #include "errlog.h"
  15. #include "server.h"
  16. BOOL ss_compress(PSTR original, PSTR compressed);
  17. ULONG ss_checksum_block(PSTR block, int size);
  18. extern BOOL bNoCompression; /* imported from sumserve.c Read only here */
  19. /*
  20. * given a pathname to a file, read the file, compress it package it up
  21. * into SSPACKETs and send these via ss_sendblock to the named pipe.
  22. *
  23. *
  24. * each packet has a sequence number. if we can't read the file, we send
  25. * a single packet with sequence -1. otherwise, we carry on until we run out
  26. * of data, then we send a packet with 0 size.
  27. */
  28. void
  29. ss_sendfile(HANDLE hpipe, LPSTR file, LONG lVersion)
  30. {
  31. SSPACKET packet;
  32. HANDLE hfile;
  33. int size;
  34. char szTempname[MAX_PATH];
  35. PSSATTRIBS attribs;
  36. BY_HANDLE_FILE_INFORMATION bhfi;
  37. dprintf1(("getting '%s' for %8x\n", file, hpipe));
  38. /*
  39. * get the file attributes first
  40. */
  41. hfile = CreateFile(file, GENERIC_READ, FILE_SHARE_READ,
  42. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  43. if (hfile == INVALID_HANDLE_VALUE) {
  44. /* report that we could not read the file */
  45. packet.lSequence = -1;
  46. ss_sendblock(hpipe, (PSTR) &packet, sizeof(packet));
  47. DeleteFile(szTempname);
  48. return;
  49. }
  50. /*
  51. * seems to be a bug in GetFileInformationByHandle if the
  52. * file is not on local machine - so avoid it.
  53. */
  54. bhfi.dwFileAttributes = GetFileAttributes(file);
  55. GetFileTime(hfile, &bhfi.ftCreationTime,
  56. &bhfi.ftLastAccessTime, &bhfi.ftLastWriteTime);
  57. CloseHandle(hfile);
  58. /* create temp filename */
  59. GetTempPath(sizeof(szTempname), szTempname);
  60. GetTempFileName(szTempname, "sum", 0, szTempname);
  61. /* compress the file into this temporary file */
  62. if (bNoCompression || (!ss_compress(file, szTempname))) {
  63. /* try to open the original file */
  64. hfile = CreateFile(file, GENERIC_READ, FILE_SHARE_READ,
  65. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  66. dprintf1(("sending original file to %8x\n", hpipe));
  67. } else {
  68. /* open temp (compressed) file and send this */
  69. hfile = CreateFile(szTempname, GENERIC_READ, 0, NULL, OPEN_EXISTING,
  70. FILE_ATTRIBUTE_NORMAL, 0);
  71. dprintf1(("sending compressed file to %8x\n", hpipe));
  72. }
  73. if (hfile == INVALID_HANDLE_VALUE) {
  74. /* report that we could not read the file */
  75. packet.lSequence = -1;
  76. ss_sendblock(hpipe, (PSTR) &packet, sizeof(packet));
  77. DeleteFile(szTempname);
  78. return;
  79. }
  80. /* loop reading blocks of the file */
  81. for (packet.lSequence = 0; ; packet.lSequence++) {
  82. if(!ReadFile(hfile, packet.Data, sizeof(packet.Data), (LPDWORD)(&size), NULL)) {
  83. /* error reading file. send a -1 packet to
  84. * indicate this
  85. */
  86. packet.lSequence = -1;
  87. ss_sendblock(hpipe, (PSTR) &packet, sizeof(packet));
  88. break;
  89. }
  90. packet.ulSize = size;
  91. if (lVersion==0)
  92. packet.ulSum = ss_checksum_block(packet.Data, size);
  93. else
  94. packet.ulSum = 0; /* checksum was compute-bound and overkill */
  95. if (size == 0) {
  96. /*
  97. * in the last block, in the Data[] field,
  98. * we place a SSATTRIBS struct with the file
  99. * times and attribs
  100. */
  101. attribs = (PSSATTRIBS) packet.Data;
  102. attribs->fileattribs = bhfi.dwFileAttributes;
  103. attribs->ft_create = bhfi.ftCreationTime;
  104. attribs->ft_lastaccess = bhfi.ftLastAccessTime;
  105. attribs->ft_lastwrite = bhfi.ftLastWriteTime;
  106. }
  107. if (!ss_sendblock(hpipe, (PSTR) &packet, sizeof(packet))) {
  108. dprintf1(("connection to %8x lost during copy\n", hpipe));
  109. break;
  110. }
  111. if (size == 0) {
  112. /* end of file */
  113. break;
  114. }
  115. }
  116. CloseHandle(hfile);
  117. DeleteFile(szTempname);
  118. return;
  119. }
  120. /*
  121. * compress a file. original is the pathname of the original file,
  122. * compressed is the pathname of the output compressed file.
  123. *
  124. * spawns a copy of compress.exe to compress the file, and waits for
  125. * it to complete successfully.
  126. */
  127. BOOL
  128. ss_compress(PSTR original, PSTR compressed)
  129. {
  130. char szCmdLine[MAX_PATH * 2];
  131. STARTUPINFO si;
  132. PROCESS_INFORMATION pi;
  133. DWORD exitcode;
  134. si.cb = sizeof(STARTUPINFO);
  135. si.lpDesktop = NULL;
  136. si.lpReserved = NULL;
  137. si.lpReserved2 = NULL;
  138. si.cbReserved2 = 0;
  139. si.lpTitle = "Sumserve Compression";
  140. si.dwFlags = STARTF_FORCEOFFFEEDBACK;
  141. sprintf(szCmdLine, "compress %s %s", original, compressed);
  142. if (!CreateProcess(NULL,
  143. szCmdLine,
  144. NULL,
  145. NULL,
  146. FALSE,
  147. DETACHED_PROCESS |
  148. NORMAL_PRIORITY_CLASS, //??? Can't we silence the console?
  149. NULL,
  150. NULL,
  151. &si,
  152. &pi)) {
  153. return(FALSE);
  154. }
  155. /* wait for completion. */
  156. WaitForSingleObject(pi.hProcess, INFINITE);
  157. if (!GetExitCodeProcess(pi.hProcess, &exitcode)) {
  158. return(FALSE);
  159. }
  160. /* close process and thread handles */
  161. CloseHandle(pi.hProcess);
  162. CloseHandle(pi.hThread);
  163. if (exitcode != 0) {
  164. dprintf1(("compress exit code %ld\n", exitcode));
  165. return(FALSE);
  166. } else {
  167. return(TRUE);
  168. }
  169. } /* ss_compress */
  170. /* produce a checksum of a block of data.
  171. *
  172. * This is undoubtedly a good checksum algorithm, but it's also compute bound.
  173. * For version 1 we turn it off. If we decide in version 2 to turn it back
  174. * on again then we will use a faster algorithm (e.g. the one used to checksum
  175. * a whole file.
  176. *
  177. * Generate checksum by the formula
  178. * checksum = SUM( rnd(i)*(1+byte[i]) )
  179. * where byte[i] is the i-th byte in the file, counting from 1
  180. * rnd(x) is a pseudo-random number generated from the seed x.
  181. *
  182. * Adding 1 to byte ensures that all null bytes contribute, rather than
  183. * being ignored. Multiplying each such byte by a pseudo-random
  184. * function of its position ensures that "anagrams" of each other come
  185. * to different sums. The pseudorandom function chosen is successive
  186. * powers of 1664525 modulo 2**32. 1664525 is a magic number taken
  187. * from Donald Knuth's "The Art Of Computer Programming"
  188. */
  189. ULONG
  190. ss_checksum_block(PSTR block, int size)
  191. {
  192. unsigned long lCheckSum = 0; /* grows into the checksum */
  193. const unsigned long lSeed = 1664525; /* seed for random Knuth */
  194. unsigned long lRand = 1; /* seed**n */
  195. unsigned long lIndex = 1; /* byte number in block */
  196. unsigned Byte; /* next byte to process in buffer */
  197. unsigned length; /* unsigned copy of size */
  198. length = size;
  199. for (Byte = 0; Byte < length ;++Byte, ++lIndex) {
  200. lRand = lRand*lSeed;
  201. lCheckSum += lIndex*(1+block[Byte])*lRand;
  202. }
  203. return(lCheckSum);
  204. } /* ss_checksum_block */