00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00033 #include "pipe/p_config.h"
00034
00035 #if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
00036
00037 #include <windows.h>
00038 #include <winddi.h>
00039
00040 #include "util/u_memory.h"
00041 #include "util/u_string.h"
00042
00043 #include "u_stream.h"
00044
00045
00046 #define MAP_FILE_SIZE (4*1024*1024)
00047
00048
00049 struct util_stream
00050 {
00051 char filename[MAX_PATH + 1];
00052 WCHAR wFileName[MAX_PATH + 1];
00053 boolean growable;
00054 size_t map_size;
00055 ULONG_PTR iFile;
00056 char *pMap;
00057 size_t written;
00058 unsigned suffix;
00059 };
00060
00061
00062 static INLINE boolean
00063 util_stream_map(struct util_stream *stream)
00064 {
00065 ULONG BytesInUnicodeString;
00066 static char filename[MAX_PATH + 1];
00067 unsigned filename_len;
00068
00069 if(stream->growable)
00070 filename_len = util_snprintf(filename,
00071 sizeof(filename),
00072 "%s.%04x",
00073 stream->filename,
00074 stream->suffix++);
00075 else
00076 filename_len = util_snprintf(filename,
00077 sizeof(filename),
00078 "%s",
00079 stream->filename);
00080
00081 EngMultiByteToUnicodeN(
00082 stream->wFileName,
00083 sizeof(stream->wFileName),
00084 &BytesInUnicodeString,
00085 filename,
00086 filename_len);
00087
00088 stream->pMap = EngMapFile(stream->wFileName, stream->map_size, &stream->iFile);
00089 if(!stream->pMap)
00090 return FALSE;
00091
00092 memset(stream->pMap, 0, stream->map_size);
00093 stream->written = 0;
00094
00095 return TRUE;
00096 }
00097
00098
00099 static INLINE void
00100 util_stream_unmap(struct util_stream *stream)
00101 {
00102 EngUnmapFile(stream->iFile);
00103 if(stream->written < stream->map_size) {
00104
00105 stream->pMap = EngMapFile(stream->wFileName, stream->written, &stream->iFile);
00106 if(stream->pMap)
00107 EngUnmapFile(stream->iFile);
00108 }
00109
00110 stream->pMap = NULL;
00111 }
00112
00113
00114 static INLINE void
00115 util_stream_full_qualified_filename(char *dst, size_t size, const char *src)
00116 {
00117 boolean need_drive, need_root;
00118
00119 if((('A' <= src[0] && src[0] <= 'Z') || ('a' <= src[0] && src[0] <= 'z')) && src[1] == ':') {
00120 need_drive = FALSE;
00121 need_root = src[2] == '\\' ? FALSE : TRUE;
00122 }
00123 else {
00124 need_drive = TRUE;
00125 need_root = src[0] == '\\' ? FALSE : TRUE;
00126 }
00127
00128 util_snprintf(dst, size,
00129 "\\??\\%s%s%s",
00130 need_drive ? "C:" : "",
00131 need_root ? "\\" : "",
00132 src);
00133 }
00134
00135
00136 struct util_stream *
00137 util_stream_create(const char *filename, size_t max_size)
00138 {
00139 struct util_stream *stream;
00140
00141 stream = CALLOC_STRUCT(util_stream);
00142 if(!stream)
00143 goto error1;
00144
00145 util_stream_full_qualified_filename(stream->filename,
00146 sizeof(stream->filename),
00147 filename);
00148
00149 if(max_size) {
00150 stream->growable = FALSE;
00151 stream->map_size = max_size;
00152 }
00153 else {
00154 stream->growable = TRUE;
00155 stream->map_size = MAP_FILE_SIZE;
00156 }
00157
00158 if(!util_stream_map(stream))
00159 goto error2;
00160
00161 return stream;
00162
00163 error2:
00164 FREE(stream);
00165 error1:
00166 return NULL;
00167 }
00168
00169
00170 static INLINE void
00171 util_stream_copy(struct util_stream *stream, const char *data, size_t size)
00172 {
00173 assert(stream->written + size <= stream->map_size);
00174 memcpy(stream->pMap + stream->written, data, size);
00175 stream->written += size;
00176 }
00177
00178
00179 boolean
00180 util_stream_write(struct util_stream *stream, const void *data, size_t size)
00181 {
00182 if(!stream)
00183 return FALSE;
00184
00185 if(!stream->pMap)
00186 return FALSE;
00187
00188 while(stream->written + size > stream->map_size) {
00189 size_t step = stream->map_size - stream->written;
00190 util_stream_copy(stream, data, step);
00191 data = (const char *)data + step;
00192 size -= step;
00193
00194 util_stream_unmap(stream);
00195 if(!stream->growable || !util_stream_map(stream))
00196 return FALSE;
00197 }
00198
00199 util_stream_copy(stream, data, size);
00200
00201 return TRUE;
00202 }
00203
00204
00205 void
00206 util_stream_flush(struct util_stream *stream)
00207 {
00208 (void)stream;
00209 }
00210
00211
00212 void
00213 util_stream_close(struct util_stream *stream)
00214 {
00215 if(!stream)
00216 return;
00217
00218 util_stream_unmap(stream);
00219
00220 FREE(stream);
00221 }
00222
00223
00224 #endif