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.

441 lines
13 KiB

  1. //-----------------------------------------------------------------------------
  2. //
  3. //
  4. // File: dsnbuff.cpp
  5. //
  6. // Description: Implementation of CDSNBuffer... class that abstracts writes
  7. // of DSN information to P2 file.
  8. //
  9. // Author: Mike Swafford (MikeSwa)
  10. //
  11. // History:
  12. // 7/3/98 - MikeSwa Created
  13. //
  14. // Copyright (C) 1998 Microsoft Corporation
  15. //
  16. //-----------------------------------------------------------------------------
  17. #include "precomp.h"
  18. //---[ CDSNBuffer::~CDSNBuffer ]-----------------------------------------------
  19. //
  20. //
  21. // Description:
  22. // Destructor for CDSNBuffer. Does NOT close file handle (caller is
  23. // responisble for that).
  24. // Parameters:
  25. // -
  26. // Returns:
  27. // -
  28. // History:
  29. // 7/3/98 - MikeSwa Created
  30. //
  31. //-----------------------------------------------------------------------------
  32. CDSNBuffer::~CDSNBuffer()
  33. {
  34. TraceFunctEnterEx((LPARAM) this, "CDSNBuffer::~CDSNBuffer");
  35. DebugTrace((LPARAM) this, "INFO: %d File writes needed by CDSNBuffer", m_cFileWrites);
  36. //make sure we don't pass in 1 bit
  37. if (m_overlapped.hEvent)
  38. {
  39. _VERIFY(CloseHandle((HANDLE) (((DWORD_PTR) m_overlapped.hEvent) & -2)));
  40. }
  41. TraceFunctLeave();
  42. }
  43. //---[ CDSNBuffer::HrInitialize ]----------------------------------------------
  44. //
  45. //
  46. // Description:
  47. // Initialize CDSNBuffer object.
  48. // - Associates destination file handle with object (will not close it)
  49. // - Creates an event for synchronizing file operations
  50. // Parameters:
  51. // hDestFile - Destination File Handle (must be opend with FILE_FLAG_OVERLAPPED)
  52. // Returns:
  53. // S_OK on success
  54. // E_INVALIDARG if handle invalid is passed in
  55. // E_FAIL if CreateEvent fails for an unknown reason
  56. // History:
  57. // 7/3/98 - MikeSwa Created
  58. //
  59. //-----------------------------------------------------------------------------
  60. HRESULT CDSNBuffer::HrInitialize(PFIO_CONTEXT pDestFile)
  61. {
  62. TraceFunctEnterEx((LPARAM) this, "CDSNBuffer::HrInitialize");
  63. HRESULT hr = S_OK;
  64. _ASSERT(pDestFile);
  65. if (!pDestFile)
  66. {
  67. hr = E_INVALIDARG;
  68. goto Exit;
  69. }
  70. m_pDestFile = pDestFile;
  71. //allow this to act as reset
  72. m_overlapped.Offset = 0;
  73. m_overlapped.OffsetHigh = 0;
  74. m_cbOffset = 0;
  75. m_cbFileSize = 0;
  76. m_cFileWrites = 0;
  77. m_overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  78. if (!m_overlapped.hEvent)
  79. {
  80. hr = HRESULT_FROM_WIN32(GetLastError());
  81. ErrorTrace((LPARAM) this, "ERROR: Unable to create DSNBuffer event - hr 0x%08X", hr);
  82. goto Exit;
  83. }
  84. //Set low bit stop ATQ completion routine from being called
  85. m_overlapped.hEvent = ((HANDLE) (((DWORD_PTR) m_overlapped.hEvent) | 0x00000001));
  86. Exit:
  87. TraceFunctLeave();
  88. return hr;
  89. }
  90. //---[ CDSNBuffer::HrWriteBuffer ]---------------------------------------------
  91. //
  92. //
  93. // Description:
  94. // Writes the given buffer, will call write file if needed
  95. // Parameters:
  96. // pbInputBuffer Buffer to write
  97. // cbInputBuffer Number of bytes to write
  98. // Returns:
  99. // S_OK on success
  100. // History:
  101. // 7/3/98 - MikeSwa Created
  102. // 10/21/98 - MikeSwa Updated to support resource conversion
  103. //
  104. //-----------------------------------------------------------------------------
  105. HRESULT CDSNBuffer::HrWriteBuffer(BYTE *pbInputBuffer, DWORD cbInputBuffer)
  106. {
  107. return HrPrivWriteBuffer(TRUE, pbInputBuffer, cbInputBuffer);
  108. }
  109. //---[ CDSNBuffer::HrWriteModifiedUnicodeString ]------------------------------
  110. //
  111. //
  112. // IMPORTANT NOTE:
  113. // This function replaces any whitespace characters in the input string
  114. // with unicode whitespace (0x0020). Becaase fUTF7EncodeBuffer treats
  115. // whitespace characters such as 0x3000 (Japanese whitespace) as a UTF7
  116. // "separator", it will encode strings with such characters embedded as
  117. // 2 separate UTF7 strings. By replacing these characters with 0x0020 we
  118. // guarantee that the output UTF7 string is a single encoded string.
  119. // Description:
  120. // Writes a given NULL terminated Unicode string, and will call write file
  121. // if needed. Converts to UTF7 encoding.
  122. // Parameters:
  123. // pwszString String to write
  124. // Returns:
  125. // S_OK on success
  126. //
  127. //-----------------------------------------------------------------------------
  128. HRESULT CDSNBuffer::HrWriteModifiedUnicodeString(LPWSTR pwszString)
  129. {
  130. DWORD i = 0;
  131. DWORD cbLength = lstrlenW(pwszString);
  132. _ASSERT(pwszString != NULL);
  133. //Replace whitespace characters with
  134. for(i = 0; i < cbLength; i++) {
  135. if(iswspace(pwszString[i]))
  136. pwszString[i] = L' ';
  137. }
  138. return HrPrivWriteBuffer(FALSE, (PBYTE) pwszString, cbLength * sizeof(WCHAR));
  139. }
  140. //---[ CDSNBuffer::HrPrivWriteBuffer ]-----------------------------------------
  141. //
  142. //
  143. // Description:
  144. // Private function to handle writing UNICODE and ASCII buffers
  145. // Parameters:
  146. // fASCII TRUE if buffer is ASCII
  147. // pbInputBuffer Buffer to write
  148. // cbInputBuffer #of bytes to write
  149. // Returns:
  150. // S_OK on success
  151. // Any errors returned from flushing buffer to disk
  152. // History:
  153. // 10/21/98 - MikeSwa Created
  154. //
  155. //-----------------------------------------------------------------------------
  156. HRESULT CDSNBuffer::HrPrivWriteBuffer(BOOL fASCII, BYTE *pbInputBuffer,
  157. DWORD cbInputBuffer)
  158. {
  159. HRESULT hr = S_OK;
  160. BOOL fDone = FALSE;
  161. BYTE *pbCurrentInput = pbInputBuffer;
  162. DWORD cbInputRead = 0;
  163. DWORD cbTotalInputRead = 0;
  164. DWORD cbOutputWritten = 0;
  165. DWORD cTimesThruLoop = 0;
  166. _ASSERT(NULL != m_pDestFile);
  167. while (!fDone)
  168. {
  169. cTimesThruLoop++;
  170. //the buffer can't be *that* large... this will hopfully catch infinite loops
  171. _ASSERT(cTimesThruLoop < 100);
  172. fDone = m_presconv->fConvertBuffer(fASCII, pbCurrentInput,
  173. cbInputBuffer-cbTotalInputRead, m_pbFileBuffer+m_cbOffset,
  174. DSN_BUFFER_SIZE - m_cbOffset, &cbOutputWritten,
  175. &cbInputRead);
  176. m_cbOffset += cbOutputWritten;
  177. _ASSERT(m_cbOffset <= DSN_BUFFER_SIZE);
  178. if (!fDone)
  179. {
  180. //Update vars passed to fConvertBuffer
  181. cbTotalInputRead += cbInputRead;
  182. pbCurrentInput += cbInputRead;
  183. _ASSERT(cbTotalInputRead <= cbInputBuffer);
  184. hr = HrWriteBufferToFile();
  185. if (FAILED(hr))
  186. goto Exit;
  187. }
  188. }
  189. Exit:
  190. return hr;
  191. }
  192. //---[ CDSNBuffer::HrWriteBufferToFile ]---------------------------------------
  193. //
  194. //
  195. // Description:
  196. // Write the current buffer contents to the fils
  197. // Parameters:
  198. // -
  199. // Returns:
  200. // S_OK on success
  201. // History:
  202. // 7/3/98 - MikeSwa Created
  203. //
  204. //-----------------------------------------------------------------------------
  205. HRESULT CDSNBuffer::HrWriteBufferToFile()
  206. {
  207. TraceFunctEnterEx((LPARAM) this, "CDSNBuffer::HrWriteBufferToFile");
  208. HRESULT hr = S_OK;
  209. DWORD cbWritten = 0;
  210. DWORD dwError = 0;
  211. if (m_cbOffset) //there is stuff to write
  212. {
  213. //fix up overlapped
  214. if (!WriteFile(m_pDestFile->m_hFile, m_pbFileBuffer, m_cbOffset, &cbWritten, &m_overlapped))
  215. {
  216. dwError = GetLastError();
  217. if (ERROR_IO_PENDING != dwError)
  218. {
  219. hr = HRESULT_FROM_WIN32(dwError);
  220. goto Exit;
  221. }
  222. //Wait for result, so we don't overwrite buffer and overlapped
  223. if (!GetOverlappedResult(m_pDestFile->m_hFile, &m_overlapped, &cbWritten, TRUE))
  224. {
  225. hr = HRESULT_FROM_WIN32(GetLastError());
  226. goto Exit;
  227. }
  228. DebugTrace((LPARAM) this, "INFO: Async write pending for FIOContext 0x%08X", m_pDestFile);
  229. }
  230. _ASSERT(m_cbOffset == cbWritten);
  231. m_cbOffset = 0;
  232. m_cbFileSize += cbWritten;
  233. m_overlapped.Offset += cbWritten;
  234. m_cFileWrites++;
  235. }
  236. Exit:
  237. TraceFunctLeave();
  238. return hr;
  239. }
  240. //---[ CDSNBuffer::SeekForward ]-----------------------------------------------
  241. //
  242. //
  243. // Description:
  244. // Seeks buffers place in file forward specified number of bytes. Flushes
  245. // Buffer in process of doing so.
  246. // Parameters:
  247. // cbBytesToSeek Number of bytes to seek forward
  248. // pcbFileSize Returns old file size
  249. // Returns:
  250. // S_OK on succedd
  251. // History:
  252. // 7/6/98 - MikeSwa Created
  253. //
  254. //-----------------------------------------------------------------------------
  255. HRESULT CDSNBuffer::HrSeekForward(IN DWORD cbBytesToSeek,OUT DWORD *pcbFileSize)
  256. {
  257. _ASSERT(pcbFileSize);
  258. HRESULT hr = HrWriteBufferToFile();
  259. if (FAILED(hr))
  260. return hr;
  261. *pcbFileSize = m_cbFileSize;
  262. m_cbFileSize += cbBytesToSeek;
  263. m_overlapped.Offset += cbBytesToSeek;
  264. return S_OK;
  265. }
  266. //---[ CDSNBuffer::HrLoadResourceString ]--------------------------------------
  267. //
  268. //
  269. // Description:
  270. // Encapsulates the functionality of LoadString... but allows you to
  271. // specify a LangId, returns read only data
  272. // Parameters:
  273. // IN wResourceId ID of the resource
  274. // IN LangId LangID to get resource for
  275. // OUT pwszResource Read-only UNICODE resource (not NULL terminated)
  276. // OUT pcbResource Size (in bytes) of UNICODE String
  277. // Returns:
  278. // S_OK on success
  279. // HRESULTS from errors trying to get load resources
  280. // History:
  281. // 10/22/98 - MikeSwa Created
  282. //
  283. //-----------------------------------------------------------------------------
  284. HRESULT CDSNBuffer::HrLoadResourceString(WORD wResourceId, LANGID LangId,
  285. LPWSTR *pwszResource, DWORD *pcbResource)
  286. {
  287. HRESULT hr = S_OK;
  288. HINSTANCE hModule = GetModuleHandle(DSN_RESOUCE_MODULE_NAME);
  289. HRSRC hResInfo = NULL;
  290. HGLOBAL hResData = NULL;
  291. WORD wStringIndex = wResourceId & 0x000F;
  292. LPWSTR wszResData = NULL;
  293. WCHAR wchLength = 0; //character representing current length
  294. _ASSERT(pwszResource);
  295. _ASSERT(pcbResource);
  296. *pwszResource = NULL;
  297. *pcbResource = NULL;
  298. if (NULL == hModule)
  299. {
  300. hr = HRESULT_FROM_WIN32(GetLastError());
  301. _ASSERT(0 && "Unable to load resource DLL");
  302. goto Exit;
  303. }
  304. //Find handle to string table segment
  305. hResInfo = FindResourceEx(hModule, RT_STRING,
  306. MAKEINTRESOURCE(((WORD)((USHORT)wResourceId >> 4) + 1)),
  307. LangId);
  308. if (NULL == hResInfo)
  309. {
  310. hr = HRESULT_FROM_WIN32(GetLastError());
  311. _ASSERT(0 && "Failed to find resource for requested LangId");
  312. goto Exit;
  313. }
  314. hResData = LoadResource(hModule, hResInfo);
  315. if (NULL == hResData)
  316. {
  317. hr = HRESULT_FROM_WIN32(GetLastError());
  318. goto Exit;
  319. }
  320. //Get pointer to string table segement data
  321. wszResData = (LPWSTR) LockResource(hResData);
  322. if (NULL == wszResData)
  323. {
  324. hr = HRESULT_FROM_WIN32(GetLastError());
  325. goto Exit;
  326. }
  327. //OK Now we have a pointer to the string table segment
  328. //Lets use some code from LoadStringOrError to handle this
  329. //There are 16 strings in a segment, which means we can look at
  330. //The low 4 bits of the wResourceId (wStringIndex)
  331. //String Table segment format
  332. //PASCAL like string count first UTCHAR is count if TCHARs
  333. //A zero length string (ie resource 0) is simply the WORD 0x0000...
  334. //This loop handles both the same... when loop is done.
  335. // wszResData - Ptr to UNICODE string
  336. // wchLenght - Length of that string (in WCHARS)
  337. while (TRUE)
  338. {
  339. wchLength = *((WCHAR *)wszResData++);
  340. if (0 == wStringIndex--)
  341. break;
  342. // Step to start if next string...
  343. wszResData += wchLength;
  344. }
  345. *pwszResource = wszResData;
  346. *pcbResource = (DWORD) wchLength*sizeof(WCHAR);
  347. Exit:
  348. return hr;
  349. }
  350. //---[ CDSNBuffer::HrWriteResource ]-------------------------------------------
  351. //
  352. //
  353. // Description:
  354. // Gets resource for specified language ID, and dumps UNICODE to DSN
  355. // content using current conversion context.
  356. //
  357. // It will assert if the resource cannot be found for the given language
  358. // ID.
  359. // Parameters:
  360. // dwResourceID The resouce ID of the resource to get
  361. // LandId The language ID to use
  362. // Returns:
  363. // S_OK on success
  364. // History:
  365. // 10/21/98 - MikeSwa Created
  366. //
  367. //-----------------------------------------------------------------------------
  368. HRESULT CDSNBuffer::HrWriteResource(WORD wResourceId, LANGID LangId)
  369. {
  370. HRESULT hr = S_OK;
  371. LPWSTR wszResource = NULL;
  372. DWORD cbResource = NULL;
  373. hr = HrLoadResourceString(wResourceId, LangId, &wszResource, &cbResource);
  374. if (FAILED(hr))
  375. {
  376. _ASSERT(0 && "Unable to load resources");
  377. //Fail silently in retail
  378. hr = S_OK;
  379. }
  380. //OK... now we have everything we need to write the buffer
  381. hr = HrPrivWriteBuffer(FALSE /*not ASCII */,
  382. (BYTE *) wszResource, cbResource);
  383. //$$REVIEW: Do we need to do any special cleanup here?
  384. return hr;
  385. }