source: cprs/branches/tmg-cprs/TMG_Extra/tntUniCode/Source/TntWindows.pas@ 1591

Last change on this file since 1591 was 672, checked in by Kevin Toppenberg, 15 years ago

Adding source to tntControls for compilation

File size: 51.6 KB
Line 
1
2{*****************************************************************************}
3{ }
4{ Tnt Delphi Unicode Controls }
5{ http://www.tntware.com/delphicontrols/unicode/ }
6{ Version: 2.3.0 }
7{ }
8{ Copyright (c) 2002-2007, Troy Wolbrink (troy.wolbrink@tntware.com) }
9{ }
10{*****************************************************************************}
11
12unit TntWindows;
13
14{$INCLUDE TntCompilers.inc}
15
16interface
17
18uses
19 Windows, ShellApi, ShlObj;
20
21// ......... compatibility
22
23const
24 DT_NOFULLWIDTHCHARBREAK = $00080000;
25
26const
27 INVALID_FILE_ATTRIBUTES = DWORD(-1);
28
29// ................ ANSI TYPES ................
30{TNT-WARN LPSTR}
31{TNT-WARN PLPSTR}
32{TNT-WARN LPCSTR}
33{TNT-WARN LPCTSTR}
34{TNT-WARN LPTSTR}
35
36// ........ EnumResourceTypesW, EnumResourceNamesW and EnumResourceLanguagesW are supposed ....
37// ........ to work on Win95/98/ME but have caused access violations in testing on Win95 ......
38// .. TNT--WARN EnumResourceTypes ..
39// .. TNT--WARN EnumResourceTypesA ..
40// .. TNT--WARN EnumResourceNames ..
41// .. TNT--WARN EnumResourceNamesA ..
42// .. TNT--WARN EnumResourceLanguages ..
43// .. TNT--WARN EnumResourceLanguagesA ..
44
45//------------------------------------------------------------------------------------------
46
47// ......... The Unicode form of these functions are supported on Windows 95/98/ME .........
48{TNT-WARN ExtTextOut}
49{TNT-WARN ExtTextOutA}
50{TNT-WARN Tnt_ExtTextOutW}
51
52{TNT-WARN FindResource}
53{TNT-WARN FindResourceA}
54{TNT-WARN Tnt_FindResourceW}
55
56{TNT-WARN FindResourceEx}
57{TNT-WARN FindResourceExA}
58{TNT-WARN Tnt_FindResourceExW}
59
60{TNT-WARN GetCharWidth}
61{TNT-WARN GetCharWidthA}
62{TNT-WARN Tnt_GetCharWidthW}
63
64{TNT-WARN GetCommandLine}
65{TNT-WARN GetCommandLineA}
66{TNT-WARN Tnt_GetCommandLineW}
67
68{TNT-WARN GetTextExtentPoint}
69{TNT-WARN GetTextExtentPointA}
70{TNT-WARN Tnt_GetTextExtentPointW}
71
72{TNT-WARN GetTextExtentPoint32}
73{TNT-WARN GetTextExtentPoint32A}
74{TNT-WARN Tnt_GetTextExtentPoint32W}
75
76{TNT-WARN lstrcat}
77{TNT-WARN lstrcatA}
78{TNT-WARN Tnt_lstrcatW}
79
80{TNT-WARN lstrcpy}
81{TNT-WARN lstrcpyA}
82{TNT-WARN Tnt_lstrcpyW}
83
84{TNT-WARN lstrlen}
85{TNT-WARN lstrlenA}
86{TNT-WARN Tnt_lstrlenW}
87
88{TNT-WARN MessageBox}
89{TNT-WARN MessageBoxA}
90{TNT-WARN Tnt_MessageBoxW}
91
92{TNT-WARN MessageBoxEx}
93{TNT-WARN MessageBoxExA}
94{TNT-WARN Tnt_MessageBoxExA}
95
96{TNT-WARN TextOut}
97{TNT-WARN TextOutA}
98{TNT-WARN Tnt_TextOutW}
99
100//------------------------------------------------------------------------------------------
101
102{TNT-WARN LOCALE_USER_DEFAULT} // <-- use GetThreadLocale
103{TNT-WARN LOCALE_SYSTEM_DEFAULT} // <-- use GetThreadLocale
104
105//------------------------------------------------------------------------------------------
106// compatiblity
107//------------------------------------------------------------------------------------------
108{$IFNDEF COMPILER_9_UP}
109type
110 TStartupInfoA = _STARTUPINFOA;
111 TStartupInfoW = record
112 cb: DWORD;
113 lpReserved: PWideChar;
114 lpDesktop: PWideChar;
115 lpTitle: PWideChar;
116 dwX: DWORD;
117 dwY: DWORD;
118 dwXSize: DWORD;
119 dwYSize: DWORD;
120 dwXCountChars: DWORD;
121 dwYCountChars: DWORD;
122 dwFillAttribute: DWORD;
123 dwFlags: DWORD;
124 wShowWindow: Word;
125 cbReserved2: Word;
126 lpReserved2: PByte;
127 hStdInput: THandle;
128 hStdOutput: THandle;
129 hStdError: THandle;
130 end;
131
132function CreateProcessW{TNT-ALLOW CreateProcessW}(lpApplicationName: PWideChar; lpCommandLine: PWideChar;
133 lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
134 bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
135 lpCurrentDirectory: PWideChar; const lpStartupInfo: TStartupInfoW;
136 var lpProcessInformation: TProcessInformation): BOOL; stdcall; external kernel32 name 'CreateProcessW';
137
138{$ENDIF}
139//------------------------------------------------------------------------------------------
140
141{TNT-WARN SetWindowText}
142{TNT-WARN SetWindowTextA}
143{TNT-WARN SetWindowTextW}
144function Tnt_SetWindowTextW(hWnd: HWND; lpString: PWideChar): BOOL;
145
146{TNT-WARN RemoveDirectory}
147{TNT-WARN RemoveDirectoryA}
148{TNT-WARN RemoveDirectoryW}
149function Tnt_RemoveDirectoryW(lpPathName: PWideChar): BOOL;
150
151{TNT-WARN GetShortPathName}
152{TNT-WARN GetShortPathNameA}
153{TNT-WARN GetShortPathNameW}
154function Tnt_GetShortPathNameW(lpszLongPath: PWideChar; lpszShortPath: PWideChar;
155 cchBuffer: DWORD): DWORD;
156
157{TNT-WARN GetFullPathName}
158{TNT-WARN GetFullPathNameA}
159{TNT-WARN GetFullPathNameW}
160function Tnt_GetFullPathNameW(lpFileName: PWideChar; nBufferLength: DWORD;
161 lpBuffer: PWideChar; var lpFilePart: PWideChar): DWORD;
162
163{TNT-WARN CreateFile}
164{TNT-WARN CreateFileA}
165{TNT-WARN CreateFileW}
166function Tnt_CreateFileW(lpFileName: PWideChar; dwDesiredAccess, dwShareMode: DWORD;
167 lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD;
168 hTemplateFile: THandle): THandle;
169
170{TNT-WARN FindFirstFile}
171{TNT-WARN FindFirstFileA}
172{TNT-WARN FindFirstFileW}
173function Tnt_FindFirstFileW(lpFileName: PWideChar; var lpFindFileData: TWIN32FindDataW): THandle;
174
175{TNT-WARN FindNextFile}
176{TNT-WARN FindNextFileA}
177{TNT-WARN FindNextFileW}
178function Tnt_FindNextFileW(hFindFile: THandle; var lpFindFileData: TWIN32FindDataW): BOOL;
179
180{TNT-WARN GetFileAttributes}
181{TNT-WARN GetFileAttributesA}
182{TNT-WARN GetFileAttributesW}
183function Tnt_GetFileAttributesW(lpFileName: PWideChar): DWORD;
184
185{TNT-WARN SetFileAttributes}
186{TNT-WARN SetFileAttributesA}
187{TNT-WARN SetFileAttributesW}
188function Tnt_SetFileAttributesW(lpFileName: PWideChar; dwFileAttributes: DWORD): BOOL;
189
190{TNT-WARN CreateDirectory}
191{TNT-WARN CreateDirectoryA}
192{TNT-WARN CreateDirectoryW}
193function Tnt_CreateDirectoryW(lpPathName: PWideChar;
194 lpSecurityAttributes: PSecurityAttributes): BOOL;
195
196{TNT-WARN MoveFile}
197{TNT-WARN MoveFileA}
198{TNT-WARN MoveFileW}
199function Tnt_MoveFileW(lpExistingFileName, lpNewFileName: PWideChar): BOOL;
200
201{TNT-WARN CopyFile}
202{TNT-WARN CopyFileA}
203{TNT-WARN CopyFileW}
204function Tnt_CopyFileW(lpExistingFileName, lpNewFileName: PWideChar; bFailIfExists: BOOL): BOOL;
205
206{TNT-WARN DeleteFile}
207{TNT-WARN DeleteFileA}
208{TNT-WARN DeleteFileW}
209function Tnt_DeleteFileW(lpFileName: PWideChar): BOOL;
210
211{TNT-WARN DrawText}
212{TNT-WARN DrawTextA}
213{TNT-WARN DrawTextW}
214function Tnt_DrawTextW(hDC: HDC; lpString: PWideChar; nCount: Integer;
215 var lpRect: TRect; uFormat: UINT): Integer;
216
217{TNT-WARN GetDiskFreeSpace}
218{TNT-WARN GetDiskFreeSpaceA}
219{TNT-WARN GetDiskFreeSpaceW}
220function Tnt_GetDiskFreeSpaceW(lpRootPathName: PWideChar; var lpSectorsPerCluster,
221 lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters: DWORD): BOOL;
222
223{TNT-WARN GetVolumeInformation}
224{TNT-WARN GetVolumeInformationA}
225{TNT-WARN GetVolumeInformationW}
226function Tnt_GetVolumeInformationW(lpRootPathName: PWideChar; lpVolumeNameBuffer: PWideChar;
227 nVolumeNameSize: DWORD; lpVolumeSerialNumber: PDWORD;
228 var lpMaximumComponentLength, lpFileSystemFlags: DWORD; lpFileSystemNameBuffer: PWideChar;
229 nFileSystemNameSize: DWORD): BOOL;
230
231{TNT-WARN GetModuleFileName}
232{TNT-WARN GetModuleFileNameA}
233{TNT-WARN GetModuleFileNameW}
234function Tnt_GetModuleFileNameW(hModule: HINST; lpFilename: PWideChar; nSize: DWORD): DWORD;
235
236{TNT-WARN GetTempPath}
237{TNT-WARN GetTempPathA}
238{TNT-WARN GetTempPathW}
239function Tnt_GetTempPathW(nBufferLength: DWORD; lpBuffer: PWideChar): DWORD;
240
241{TNT-WARN GetTempFileName}
242{TNT-WARN GetTempFileNameA}
243{TNT-WARN GetTempFileNameW}
244function Tnt_GetTempFileNameW(lpPathName, lpPrefixString: PWideChar; uUnique: UINT;
245 lpTempFileName: PWideChar): UINT;
246
247{TNT-WARN GetWindowsDirectory}
248{TNT-WARN GetWindowsDirectoryA}
249{TNT-WARN GetWindowsDirectoryW}
250function Tnt_GetWindowsDirectoryW(lpBuffer: PWideChar; uSize: UINT): UINT;
251
252{TNT-WARN GetSystemDirectory}
253{TNT-WARN GetSystemDirectoryA}
254{TNT-WARN GetSystemDirectoryW}
255function Tnt_GetSystemDirectoryW(lpBuffer: PWideChar; uSize: UINT): UINT;
256
257{TNT-WARN GetCurrentDirectory}
258{TNT-WARN GetCurrentDirectoryA}
259{TNT-WARN GetCurrentDirectoryW}
260function Tnt_GetCurrentDirectoryW(nBufferLength: DWORD; lpBuffer: PWideChar): DWORD;
261
262{TNT-WARN SetCurrentDirectory}
263{TNT-WARN SetCurrentDirectoryA}
264{TNT-WARN SetCurrentDirectoryW}
265function Tnt_SetCurrentDirectoryW(lpPathName: PWideChar): BOOL;
266
267{TNT-WARN GetComputerName}
268{TNT-WARN GetComputerNameA}
269{TNT-WARN GetComputerNameW}
270function Tnt_GetComputerNameW(lpBuffer: PWideChar; var nSize: DWORD): BOOL;
271
272{TNT-WARN GetUserName}
273{TNT-WARN GetUserNameA}
274{TNT-WARN GetUserNameW}
275function Tnt_GetUserNameW(lpBuffer: PWideChar; var nSize: DWORD): BOOL;
276
277{TNT-WARN ShellExecute}
278{TNT-WARN ShellExecuteA}
279{TNT-WARN ShellExecuteW}
280function Tnt_ShellExecuteW(hWnd: HWND; Operation, FileName, Parameters,
281 Directory: PWideChar; ShowCmd: Integer): HINST;
282
283{TNT-WARN LoadLibrary}
284{TNT-WARN LoadLibraryA}
285{TNT-WARN LoadLibraryW}
286function Tnt_LoadLibraryW(lpLibFileName: PWideChar): HMODULE;
287
288{TNT-WARN LoadLibraryEx}
289{TNT-WARN LoadLibraryExA}
290{TNT-WARN LoadLibraryExW}
291function Tnt_LoadLibraryExW(lpLibFileName: PWideChar; hFile: THandle; dwFlags: DWORD): HMODULE;
292
293{TNT-WARN CreateProcess}
294{TNT-WARN CreateProcessA}
295{TNT-WARN CreateProcessW}
296function Tnt_CreateProcessW(lpApplicationName: PWideChar; lpCommandLine: PWideChar;
297 lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
298 bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
299 lpCurrentDirectory: PWideChar; const lpStartupInfo: TStartupInfoW;
300 var lpProcessInformation: TProcessInformation): BOOL;
301
302{TNT-WARN GetCurrencyFormat}
303{TNT-WARN GetCurrencyFormatA}
304{TNT-WARN GetCurrencyFormatW}
305function Tnt_GetCurrencyFormatW(Locale: LCID; dwFlags: DWORD; lpValue: PWideChar;
306 lpFormat: PCurrencyFmtW; lpCurrencyStr: PWideChar; cchCurrency: Integer): Integer;
307
308{TNT-WARN CompareString}
309{TNT-WARN CompareStringA}
310{TNT-WARN CompareStringW}
311function Tnt_CompareStringW(Locale: LCID; dwCmpFlags: DWORD; lpString1: PWideChar;
312 cchCount1: Integer; lpString2: PWideChar; cchCount2: Integer): Integer;
313
314{TNT-WARN CharUpper}
315{TNT-WARN CharUpperA}
316{TNT-WARN CharUpperW}
317function Tnt_CharUpperW(lpsz: PWideChar): PWideChar;
318
319{TNT-WARN CharUpperBuff}
320{TNT-WARN CharUpperBuffA}
321{TNT-WARN CharUpperBuffW}
322function Tnt_CharUpperBuffW(lpsz: PWideChar; cchLength: DWORD): DWORD;
323
324{TNT-WARN CharLower}
325{TNT-WARN CharLowerA}
326{TNT-WARN CharLowerW}
327function Tnt_CharLowerW(lpsz: PWideChar): PWideChar;
328
329{TNT-WARN CharLowerBuff}
330{TNT-WARN CharLowerBuffA}
331{TNT-WARN CharLowerBuffW}
332function Tnt_CharLowerBuffW(lpsz: PWideChar; cchLength: DWORD): DWORD;
333
334{TNT-WARN GetStringTypeEx}
335{TNT-WARN GetStringTypeExA}
336{TNT-WARN GetStringTypeExW}
337function Tnt_GetStringTypeExW(Locale: LCID; dwInfoType: DWORD;
338 lpSrcStr: PWideChar; cchSrc: Integer; var lpCharType): BOOL;
339
340{TNT-WARN LoadString}
341{TNT-WARN LoadStringA}
342{TNT-WARN LoadStringW}
343function Tnt_LoadStringW(hInstance: HINST; uID: UINT; lpBuffer: PWideChar; nBufferMax: Integer): Integer;
344
345{TNT-WARN InsertMenuItem}
346{TNT-WARN InsertMenuItemA}
347{TNT-WARN InsertMenuItemW}
348function Tnt_InsertMenuItemW(hMenu: HMENU; uItem: DWORD; fByPosition: BOOL; lpmii: tagMenuItemINFOW): BOOL;
349
350{TNT-WARN ExtractIconEx}
351{TNT-WARN ExtractIconExA}
352{TNT-WARN ExtractIconExW}
353function Tnt_ExtractIconExW(lpszFile: PWideChar; nIconIndex: Integer;
354 var phiconLarge, phiconSmall: HICON; nIcons: UINT): UINT;
355
356{TNT-WARN ExtractAssociatedIcon}
357{TNT-WARN ExtractAssociatedIconA}
358{TNT-WARN ExtractAssociatedIconW}
359function Tnt_ExtractAssociatedIconW(hInst: HINST; lpIconPath: PWideChar;
360 var lpiIcon: Word): HICON;
361
362{TNT-WARN GetFileVersionInfoSize}
363{TNT-WARN GetFileVersionInfoSizeA}
364{TNT-WARN GetFileVersionInfoSizeW}
365function Tnt_GetFileVersionInfoSizeW(lptstrFilename: PWideChar; var lpdwHandle: DWORD): DWORD;
366
367{TNT-WARN GetFileVersionInfo}
368{TNT-WARN GetFileVersionInfoA}
369{TNT-WARN GetFileVersionInfoW}
370function Tnt_GetFileVersionInfoW(lptstrFilename: PWideChar; dwHandle, dwLen: DWORD;
371 lpData: Pointer): BOOL;
372
373const
374 VQV_FIXEDFILEINFO = '\';
375 VQV_VARFILEINFO_TRANSLATION = '\VarFileInfo\Translation';
376 VQV_STRINGFILEINFO = '\StringFileInfo';
377
378 VER_COMMENTS = 'Comments';
379 VER_INTERNALNAME = 'InternalName';
380 VER_PRODUCTNAME = 'ProductName';
381 VER_COMPANYNAME = 'CompanyName';
382 VER_LEGALCOPYRIGHT = 'LegalCopyright';
383 VER_PRODUCTVERSION = 'ProductVersion';
384 VER_FILEDESCRIPTION = 'FileDescription';
385 VER_LEGALTRADEMARKS = 'LegalTrademarks';
386 VER_PRIVATEBUILD = 'PrivateBuild';
387 VER_FILEVERSION = 'FileVersion';
388 VER_ORIGINALFILENAME = 'OriginalFilename';
389 VER_SPECIALBUILD = 'SpecialBuild';
390
391{TNT-WARN VerQueryValue}
392{TNT-WARN VerQueryValueA}
393{TNT-WARN VerQueryValueW}
394function Tnt_VerQueryValueW(pBlock: Pointer; lpSubBlock: PWideChar;
395 var lplpBuffer: Pointer; var puLen: UINT): BOOL;
396
397type
398 TSHNameMappingHeaderA = record
399 cNumOfMappings: Cardinal;
400 lpNM: PSHNAMEMAPPINGA;
401 end;
402 PSHNameMappingHeaderA = ^TSHNameMappingHeaderA;
403
404 TSHNameMappingHeaderW = record
405 cNumOfMappings: Cardinal;
406 lpNM: PSHNAMEMAPPINGW;
407 end;
408 PSHNameMappingHeaderW = ^TSHNameMappingHeaderW;
409
410{TNT-WARN SHFileOperation}
411{TNT-WARN SHFileOperationA}
412{TNT-WARN SHFileOperationW} // <-- no stub on early Windows 95
413function Tnt_SHFileOperationW(var lpFileOp: TSHFileOpStructW): Integer;
414
415{TNT-WARN SHFreeNameMappings}
416procedure Tnt_SHFreeNameMappings(hNameMappings: THandle);
417
418{TNT-WARN SHBrowseForFolder}
419{TNT-WARN SHBrowseForFolderA}
420{TNT-WARN SHBrowseForFolderW} // <-- no stub on early Windows 95
421function Tnt_SHBrowseForFolderW(var lpbi: TBrowseInfoW): PItemIDList;
422
423{TNT-WARN SHGetPathFromIDList}
424{TNT-WARN SHGetPathFromIDListA}
425{TNT-WARN SHGetPathFromIDListW} // <-- no stub on early Windows 95
426function Tnt_SHGetPathFromIDListW(pidl: PItemIDList; pszPath: PWideChar): BOOL;
427
428{TNT-WARN SHGetFileInfo}
429{TNT-WARN SHGetFileInfoA}
430{TNT-WARN SHGetFileInfoW} // <-- no stub on early Windows 95
431function Tnt_SHGetFileInfoW(pszPath: PWideChar; dwFileAttributes: DWORD;
432 var psfi: TSHFileInfoW; cbFileInfo, uFlags: UINT): DWORD;
433
434// ......... introduced .........
435function Tnt_Is_IntResource(ResStr: LPCWSTR): Boolean;
436
437function LANGIDFROMLCID(lcid: LCID): WORD;
438function MAKELANGID(usPrimaryLanguage, usSubLanguage: WORD): WORD;
439function MAKELCID(wLanguageID: WORD; wSortID: WORD = SORT_DEFAULT): LCID;
440function PRIMARYLANGID(lgid: WORD): WORD;
441function SORTIDFROMLCID(lcid: LCID): WORD;
442function SUBLANGID(lgid: WORD): WORD;
443
444implementation
445
446uses
447 SysUtils, Math, TntSysUtils,
448 {$IFDEF COMPILER_9_UP} WideStrUtils, {$ENDIF} TntWideStrUtils;
449
450function _PAnsiCharWithNil(const S: AnsiString): PAnsiChar;
451begin
452 if S = '' then
453 Result := nil {Win9x needs nil for some parameters instead of empty strings}
454 else
455 Result := PAnsiChar(S);
456end;
457
458function _PWideCharWithNil(const S: WideString): PWideChar;
459begin
460 if S = '' then
461 Result := nil {Win9x needs nil for some parameters instead of empty strings}
462 else
463 Result := PWideChar(S);
464end;
465
466function _WStr(lpString: PWideChar; cchCount: Integer): WideString;
467begin
468 if cchCount = -1 then
469 Result := lpString
470 else
471 Result := Copy(WideString(lpString), 1, cchCount);
472end;
473
474procedure _MakeWideWin32FindData(var WideFindData: TWIN32FindDataW; AnsiFindData: TWIN32FindDataA);
475begin
476 CopyMemory(@WideFindData, @AnsiFindData,
477 Integer(@WideFindData.cFileName) - Integer(@WideFindData));
478 WStrPCopy(WideFindData.cFileName, AnsiFindData.cFileName);
479 WStrPCopy(WideFindData.cAlternateFileName, AnsiFindData.cAlternateFileName);
480end;
481
482function Tnt_SetWindowTextW(hWnd: HWND; lpString: PWideChar): BOOL;
483begin
484 if Win32PlatformIsUnicode then
485 Result := SetWindowTextW{TNT-ALLOW SetWindowTextW}(hWnd, lpString)
486 else
487 Result := SetWindowTextA{TNT-ALLOW SetWindowTextA}(hWnd, PAnsiChar(AnsiString(lpString)));
488end;
489
490//-----------------------------
491
492type
493 TPathLengthResultOption = (poAllowDirectoryMode, poZeroSmallBuff, poExactCopy, poExactCopySubPaths);
494 TPathLengthResultOptions = set of TPathLengthResultOption;
495
496procedure _ExactStrCopyW(pDest, pSource: PWideChar; Count: Integer);
497var
498 i: integer;
499begin
500 for i := 1 to Count do begin
501 pDest^ := pSource^;
502 Inc(PSource);
503 Inc(pDest);
504 end;
505end;
506
507procedure _ExactCopySubPaths(pDest, pSource: PWideChar; Count: Integer);
508var
509 i: integer;
510 OriginalSource: PWideChar;
511 PNextSlash: PWideChar;
512begin
513 if Count >= 4 then begin
514 OriginalSource := pSource;
515 PNextSlash := WStrScan(pSource, '\');
516 for i := 1 to Count - 1 do begin
517 // determine next path delimiter
518 if pSource > pNextSlash then begin
519 PNextSlash := WStrScan(pSource, '\');
520 end;
521 // leave if no more sub paths
522 if (PNextSlash = nil)
523 or ((pNextSlash - OriginalSource) >= Count) then begin
524 exit;
525 end;
526 // copy char
527 pDest^ := pSource^;
528 Inc(PSource);
529 Inc(pDest);
530 end;
531 end;
532end;
533
534function _HandlePathLengthResult(nBufferLength: DWORD; lpBuffer: PWideChar; const AnsiBuff: AnsiString; Options: TPathLengthResultOptions): Integer;
535var
536 WideBuff: WideString;
537begin
538 WideBuff := AnsiBuff;
539 if nBufferLength > Cardinal(Length(WideBuff)) then begin
540 // normal
541 Result := Length(WideBuff);
542 WStrLCopy(lpBuffer, PWideChar(WideBuff), nBufferLength);
543 end else if (poExactCopy in Options) then begin
544 // exact
545 Result := nBufferLength;
546 _ExactStrCopyW(lpBuffer, PWideChar(WideBuff), nBufferLength);
547 end else begin
548 // other
549 if (poAllowDirectoryMode in Options)
550 and (nBufferLength = Cardinal(Length(WideBuff))) then begin
551 Result := Length(WideBuff) + 1;
552 WStrLCopy(lpBuffer, PWideChar(WideBuff), nBufferLength - 1);
553 end else begin
554 Result := Length(WideBuff) + 1;
555 if (nBufferLength > 0) then begin
556 if (poZeroSmallBuff in Options) then
557 lpBuffer^ := #0
558 else if (poExactCopySubPaths in Options) then
559 _ExactCopySubPaths(lpBuffer, PWideChar(WideBuff), nBufferLength);
560 end;
561 end;
562 end;
563end;
564
565function _HandleStringLengthResult(nBufferLength: DWORD; lpBuffer: PWideChar; const AnsiBuff: AnsiString; Options: TPathLengthResultOptions): Integer;
566var
567 WideBuff: WideString;
568begin
569 WideBuff := AnsiBuff;
570 if nBufferLength >= Cardinal(Length(WideBuff)) then begin
571 // normal
572 Result := Length(WideBuff);
573 WStrLCopy(lpBuffer, PWideChar(WideBuff), nBufferLength);
574 end else if nBufferLength = 0 then
575 Result := Length(WideBuff)
576 else
577 Result := 0;
578end;
579
580//-------------------------------------------
581
582function Tnt_RemoveDirectoryW(lpPathName: PWideChar): BOOL;
583begin
584 if Win32PlatformIsUnicode then
585 Result := RemoveDirectoryW{TNT-ALLOW RemoveDirectoryW}(PWideChar(lpPathName))
586 else
587 Result := RemoveDirectoryA{TNT-ALLOW RemoveDirectoryA}(PAnsiChar(AnsiString(lpPathName)));
588end;
589
590function Tnt_GetShortPathNameW(lpszLongPath: PWideChar; lpszShortPath: PWideChar;
591 cchBuffer: DWORD): DWORD;
592var
593 AnsiBuff: AnsiString;
594begin
595 if Win32PlatformIsUnicode then
596 Result := GetShortPathNameW{TNT-ALLOW GetShortPathNameW}(lpszLongPath, lpszShortPath, cchBuffer)
597 else begin
598 SetLength(AnsiBuff, MAX_PATH * 2);
599 SetLength(AnsiBuff, GetShortPathNameA{TNT-ALLOW GetShortPathNameA}(PAnsiChar(AnsiString(lpszLongPath)),
600 PAnsiChar(AnsiBuff), Length(AnsiBuff)));
601 Result := _HandlePathLengthResult(cchBuffer, lpszShortPath, AnsiBuff, [poExactCopySubPaths]);
602 end;
603end;
604
605function Tnt_GetFullPathNameW(lpFileName: PWideChar; nBufferLength: DWORD;
606 lpBuffer: PWideChar; var lpFilePart: PWideChar): DWORD;
607var
608 AnsiBuff: AnsiString;
609 AnsiFilePart: PAnsiChar;
610 AnsiLeadingChars: Integer;
611 WideLeadingChars: Integer;
612begin
613 if Win32PlatformIsUnicode then
614 Result := GetFullPathNameW{TNT-ALLOW GetFullPathNameW}(lpFileName, nBufferLength, lpBuffer, lpFilePart)
615 else begin
616 SetLength(AnsiBuff, MAX_PATH * 2);
617 SetLength(AnsiBuff, GetFullPathNameA{TNT-ALLOW GetFullPathNameA}(PAnsiChar(AnsiString(lpFileName)),
618 Length(AnsiBuff), PAnsiChar(AnsiBuff), AnsiFilePart));
619 Result := _HandlePathLengthResult(nBufferLength, lpBuffer, AnsiBuff, [poZeroSmallBuff]);
620 // deal w/ lpFilePart
621 if (AnsiFilePart = nil) or (nBufferLength < Result) then
622 lpFilePart := nil
623 else begin
624 AnsiLeadingChars := AnsiFilePart - PAnsiChar(AnsiBuff);
625 WideLeadingChars := Length(WideString(Copy(AnsiBuff, 1, AnsiLeadingChars)));
626 lpFilePart := lpBuffer + WideLeadingChars;
627 end;
628 end;
629end;
630
631function Tnt_CreateFileW(lpFileName: PWideChar; dwDesiredAccess, dwShareMode: DWORD;
632 lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD;
633 hTemplateFile: THandle): THandle;
634begin
635 if Win32PlatformIsUnicode then
636 Result := CreateFileW{TNT-ALLOW CreateFileW}(lpFileName, dwDesiredAccess, dwShareMode,
637 lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)
638 else
639 Result := CreateFileA{TNT-ALLOW CreateFileA}(PAnsiChar(AnsiString(lpFileName)), dwDesiredAccess, dwShareMode,
640 lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile)
641end;
642
643function Tnt_FindFirstFileW(lpFileName: PWideChar; var lpFindFileData: TWIN32FindDataW): THandle;
644var
645 Ansi_lpFindFileData: TWIN32FindDataA;
646begin
647 if Win32PlatformIsUnicode then
648 Result := FindFirstFileW{TNT-ALLOW FindFirstFileW}(lpFileName, lpFindFileData)
649 else begin
650 Result := FindFirstFileA{TNT-ALLOW FindFirstFileA}(PAnsiChar(AnsiString(lpFileName)),
651 Ansi_lpFindFileData);
652 if Result <> INVALID_HANDLE_VALUE then
653 _MakeWideWin32FindData(lpFindFileData, Ansi_lpFindFileData);
654 end;
655end;
656
657function Tnt_FindNextFileW(hFindFile: THandle; var lpFindFileData: TWIN32FindDataW): BOOL;
658var
659 Ansi_lpFindFileData: TWIN32FindDataA;
660begin
661 if Win32PlatformIsUnicode then
662 Result := FindNextFileW{TNT-ALLOW FindNextFileW}(hFindFile, lpFindFileData)
663 else begin
664 Result := FindNextFileA{TNT-ALLOW FindNextFileA}(hFindFile, Ansi_lpFindFileData);
665 if Result then
666 _MakeWideWin32FindData(lpFindFileData, Ansi_lpFindFileData);
667 end;
668end;
669
670function Tnt_GetFileAttributesW(lpFileName: PWideChar): DWORD;
671begin
672 if Win32PlatformIsUnicode then
673 Result := GetFileAttributesW{TNT-ALLOW GetFileAttributesW}(lpFileName)
674 else
675 Result := GetFileAttributesA{TNT-ALLOW GetFileAttributesA}(PAnsiChar(AnsiString(lpFileName)));
676end;
677
678function Tnt_SetFileAttributesW(lpFileName: PWideChar; dwFileAttributes: DWORD): BOOL;
679begin
680 if Win32PlatformIsUnicode then
681 Result := SetFileAttributesW{TNT-ALLOW SetFileAttributesW}(lpFileName, dwFileAttributes)
682 else
683 Result := SetFileAttributesA{TNT-ALLOW SetFileAttributesA}(PAnsiChar(AnsiString(lpFileName)), dwFileAttributes);
684end;
685
686function Tnt_CreateDirectoryW(lpPathName: PWideChar;
687 lpSecurityAttributes: PSecurityAttributes): BOOL;
688begin
689 if Win32PlatformIsUnicode then
690 Result := CreateDirectoryW{TNT-ALLOW CreateDirectoryW}(lpPathName, lpSecurityAttributes)
691 else
692 Result := CreateDirectoryA{TNT-ALLOW CreateDirectoryA}(PAnsiChar(AnsiString(lpPathName)), lpSecurityAttributes);
693end;
694
695function Tnt_MoveFileW(lpExistingFileName, lpNewFileName: PWideChar): BOOL;
696begin
697 if Win32PlatformIsUnicode then
698 Result := MoveFileW{TNT-ALLOW MoveFileW}(lpExistingFileName, lpNewFileName)
699 else
700 Result := MoveFileA{TNT-ALLOW MoveFileA}(PAnsiChar(AnsiString(lpExistingFileName)), PAnsiChar(AnsiString(lpNewFileName)));
701end;
702
703function Tnt_CopyFileW(lpExistingFileName, lpNewFileName: PWideChar; bFailIfExists: BOOL): BOOL;
704begin
705 if Win32PlatformIsUnicode then
706 Result := CopyFileW{TNT-ALLOW CopyFileW}(lpExistingFileName, lpNewFileName, bFailIfExists)
707 else
708 Result := CopyFileA{TNT-ALLOW CopyFileA}(PAnsiChar(AnsiString(lpExistingFileName)),
709 PAnsiChar(AnsiString(lpNewFileName)), bFailIfExists);
710end;
711
712function Tnt_DeleteFileW(lpFileName: PWideChar): BOOL;
713begin
714 if Win32PlatformIsUnicode then
715 Result := DeleteFileW{TNT-ALLOW DeleteFileW}(lpFileName)
716 else
717 Result := DeleteFileA{TNT-ALLOW DeleteFileA}(PAnsiChar(AnsiString(lpFileName)));
718end;
719
720function Tnt_DrawTextW(hDC: HDC; lpString: PWideChar; nCount: Integer;
721 var lpRect: TRect; uFormat: UINT): Integer;
722begin
723 if Win32PlatformIsUnicode then
724 Result := DrawTextW{TNT-ALLOW DrawTextW}(hDC, lpString, nCount, lpRect, uFormat)
725 else
726 Result := DrawTextA{TNT-ALLOW DrawTextA}(hDC,
727 PAnsiChar(AnsiString(_WStr(lpString, nCount))), -1, lpRect, uFormat);
728end;
729
730function Tnt_GetDiskFreeSpaceW(lpRootPathName: PWideChar; var lpSectorsPerCluster,
731 lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters: DWORD): BOOL;
732begin
733 if Win32PlatformIsUnicode then
734 Result := GetDiskFreeSpaceW{TNT-ALLOW GetDiskFreeSpaceW}(lpRootPathName,
735 lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters)
736 else
737 Result := GetDiskFreeSpaceA{TNT-ALLOW GetDiskFreeSpaceA}(PAnsiChar(AnsiString(lpRootPathName)),
738 lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters)
739end;
740
741function Tnt_GetVolumeInformationW(lpRootPathName: PWideChar; lpVolumeNameBuffer: PWideChar;
742 nVolumeNameSize: DWORD; lpVolumeSerialNumber: PDWORD;
743 var lpMaximumComponentLength, lpFileSystemFlags: DWORD; lpFileSystemNameBuffer: PWideChar;
744 nFileSystemNameSize: DWORD): BOOL;
745var
746 AnsiFileSystemNameBuffer: AnsiString;
747 AnsiVolumeNameBuffer: AnsiString;
748 AnsiBuffLen: DWORD;
749begin
750 if Win32PlatformIsUnicode then
751 Result := GetVolumeInformationW{TNT-ALLOW GetVolumeInformationW}(lpRootPathName, lpVolumeNameBuffer, nVolumeNameSize, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, lpFileSystemNameBuffer, nFileSystemNameSize)
752 else begin
753 SetLength(AnsiVolumeNameBuffer, MAX_COMPUTERNAME_LENGTH + 1);
754 SetLength(AnsiFileSystemNameBuffer, MAX_COMPUTERNAME_LENGTH + 1);
755 AnsiBuffLen := Length(AnsiFileSystemNameBuffer);
756 Result := GetVolumeInformationA{TNT-ALLOW GetVolumeInformationA}(PAnsiChar(AnsiString(lpRootPathName)), PAnsiChar(AnsiVolumeNameBuffer), AnsiBuffLen, lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags, PAnsiChar(AnsiFileSystemNameBuffer), AnsiBuffLen);
757 if Result then begin
758 SetLength(AnsiFileSystemNameBuffer, AnsiBuffLen);
759 if (nFileSystemNameSize <= AnsiBuffLen) or (Length(AnsiFileSystemNameBuffer) = 0) then
760 Result := False
761 else begin
762 WStrPLCopy(lpFileSystemNameBuffer, AnsiFileSystemNameBuffer, nFileSystemNameSize);
763 WStrPLCopy(lpVolumeNameBuffer, AnsiVolumeNameBuffer, nVolumeNameSize);
764 end;
765 end;
766 end;
767end;
768
769function Tnt_GetModuleFileNameW(hModule: HINST; lpFilename: PWideChar; nSize: DWORD): DWORD;
770var
771 AnsiBuff: AnsiString;
772begin
773 if Win32PlatformIsUnicode then
774 Result := GetModuleFileNameW{TNT-ALLOW GetModuleFileNameW}(hModule, lpFilename, nSize)
775 else begin
776 SetLength(AnsiBuff, MAX_PATH);
777 SetLength(AnsiBuff, GetModuleFileNameA{TNT-ALLOW GetModuleFileNameA}(hModule, PAnsiChar(AnsiBuff), Length(AnsiBuff)));
778 Result := _HandlePathLengthResult(nSize, lpFilename, AnsiBuff, [poExactCopy]);
779 end;
780end;
781
782function Tnt_GetTempPathW(nBufferLength: DWORD; lpBuffer: PWideChar): DWORD;
783var
784 AnsiBuff: AnsiString;
785begin
786 if Win32PlatformIsUnicode then
787 Result := GetTempPathW{TNT-ALLOW GetTempPathW}(nBufferLength, lpBuffer)
788 else begin
789 SetLength(AnsiBuff, MAX_PATH);
790 SetLength(AnsiBuff, GetTempPathA{TNT-ALLOW GetTempPathA}(Length(AnsiBuff), PAnsiChar(AnsiBuff)));
791 Result := _HandlePathLengthResult(nBufferLength, lpBuffer, AnsiBuff, [poAllowDirectoryMode, poZeroSmallBuff]);
792 end;
793end;
794
795function Tnt_GetTempFileNameW(lpPathName, lpPrefixString: PWideChar; uUnique: UINT;
796 lpTempFileName: PWideChar): UINT;
797var
798 AnsiBuff: AnsiString;
799begin
800 if Win32PlatformIsUnicode then
801 Result := GetTempFileNameW{TNT-ALLOW GetTempFileNameW}(lpPathName, lpPrefixString, uUnique, lpTempFileName)
802 else begin
803 SetLength(AnsiBuff, MAX_PATH);
804 Result := GetTempFileNameA{TNT-ALLOW GetTempFileNameA}(PAnsiChar(AnsiString(lpPathName)), PAnsiChar(lpPrefixString), uUnique, PAnsiChar(AnsiBuff));
805 AnsiBuff := PAnsiChar(AnsiBuff);
806 _HandlePathLengthResult(MAX_PATH, lpTempFileName, AnsiBuff, [poZeroSmallBuff]);
807 end;
808end;
809
810function Tnt_GetWindowsDirectoryW(lpBuffer: PWideChar; uSize: UINT): UINT;
811var
812 AnsiBuff: AnsiString;
813begin
814 if Win32PlatformIsUnicode then
815 Result := GetWindowsDirectoryW{TNT-ALLOW GetWindowsDirectoryW}(lpBuffer, uSize)
816 else begin
817 SetLength(AnsiBuff, MAX_PATH);
818 SetLength(AnsiBuff, GetWindowsDirectoryA{TNT-ALLOW GetWindowsDirectoryA}(PAnsiChar(AnsiBuff), Length(AnsiBuff)));
819 Result := _HandlePathLengthResult(uSize, lpBuffer, AnsiBuff, []);
820 end;
821end;
822
823function Tnt_GetSystemDirectoryW(lpBuffer: PWideChar; uSize: UINT): UINT;
824var
825 AnsiBuff: AnsiString;
826begin
827 if Win32PlatformIsUnicode then
828 Result := GetSystemDirectoryW{TNT-ALLOW GetSystemDirectoryW}(lpBuffer, uSize)
829 else begin
830 SetLength(AnsiBuff, MAX_PATH);
831 SetLength(AnsiBuff, GetSystemDirectoryA{TNT-ALLOW GetSystemDirectoryA}(PAnsiChar(AnsiBuff), Length(AnsiBuff)));
832 Result := _HandlePathLengthResult(uSize, lpBuffer, AnsiBuff, []);
833 end;
834end;
835
836function Tnt_GetCurrentDirectoryW(nBufferLength: DWORD; lpBuffer: PWideChar): DWORD;
837var
838 AnsiBuff: AnsiString;
839begin
840 if Win32PlatformIsUnicode then
841 Result := GetCurrentDirectoryW{TNT-ALLOW GetCurrentDirectoryW}(nBufferLength, lpBuffer)
842 else begin
843 SetLength(AnsiBuff, MAX_PATH);
844 SetLength(AnsiBuff, GetCurrentDirectoryA{TNT-ALLOW GetCurrentDirectoryA}(Length(AnsiBuff), PAnsiChar(AnsiBuff)));
845 Result := _HandlePathLengthResult(nBufferLength, lpBuffer, AnsiBuff, [poAllowDirectoryMode, poZeroSmallBuff]);
846 end;
847end;
848
849function Tnt_SetCurrentDirectoryW(lpPathName: PWideChar): BOOL;
850begin
851 if Win32PlatformIsUnicode then
852 Result := SetCurrentDirectoryW{TNT-ALLOW SetCurrentDirectoryW}(lpPathName)
853 else
854 Result := SetCurrentDirectoryA{TNT-ALLOW SetCurrentDirectoryA}(PAnsiChar(AnsiString(lpPathName)));
855end;
856
857function Tnt_GetComputerNameW(lpBuffer: PWideChar; var nSize: DWORD): BOOL;
858var
859 AnsiBuff: AnsiString;
860 AnsiBuffLen: DWORD;
861begin
862 if Win32PlatformIsUnicode then
863 Result := GetComputerNameW{TNT-ALLOW GetComputerNameW}(lpBuffer, nSize)
864 else begin
865 SetLength(AnsiBuff, MAX_COMPUTERNAME_LENGTH + 1);
866 AnsiBuffLen := Length(AnsiBuff);
867 Result := GetComputerNameA{TNT-ALLOW GetComputerNameA}(PAnsiChar(AnsiBuff), AnsiBuffLen);
868 if Result then begin
869 SetLength(AnsiBuff, AnsiBuffLen);
870 if (nSize <= AnsiBuffLen) or (Length(AnsiBuff) = 0) then begin
871 nSize := AnsiBuffLen + 1;
872 Result := False;
873 end else begin
874 WStrPLCopy(lpBuffer, AnsiBuff, nSize);
875 nSize := WStrLen(lpBuffer);
876 end;
877 end;
878 end;
879end;
880
881function Tnt_GetUserNameW(lpBuffer: PWideChar; var nSize: DWORD): BOOL;
882var
883 AnsiBuff: AnsiString;
884 AnsiBuffLen: DWORD;
885begin
886 if Win32PlatformIsUnicode then
887 Result := GetUserNameW{TNT-ALLOW GetUserNameW}(lpBuffer, nSize)
888 else begin
889 SetLength(AnsiBuff, 255);
890 AnsiBuffLen := Length(AnsiBuff);
891 Result := GetUserNameA{TNT-ALLOW GetUserNameA}(PAnsiChar(AnsiBuff), AnsiBuffLen);
892 if Result then begin
893 SetLength(AnsiBuff, AnsiBuffLen);
894 if (nSize <= AnsiBuffLen) or (Length(AnsiBuff) = 0) then begin
895 nSize := AnsiBuffLen + 1;
896 Result := False;
897 end else begin
898 WStrPLCopy(lpBuffer, AnsiBuff, nSize);
899 nSize := WStrLen(lpBuffer);
900 end;
901 end;
902 end;
903end;
904
905function Tnt_ShellExecuteW(hWnd: HWND; Operation, FileName, Parameters,
906 Directory: PWideChar; ShowCmd: Integer): HINST;
907begin
908 if Win32PlatformIsUnicode then
909 Result := ShellExecuteW{TNT-ALLOW ShellExecuteW}(hWnd, _PWideCharWithNil(WideString(Operation)),
910 FileName, Parameters,
911 Directory, ShowCmd)
912 else begin
913 Result := ShellExecuteA{TNT-ALLOW ShellExecuteA}(hWnd, _PAnsiCharWithNil(AnsiString(Operation)),
914 _PAnsiCharWithNil(AnsiString(FileName)), _PAnsiCharWithNil(AnsiString(Parameters)),
915 _PAnsiCharWithNil(AnsiString(Directory)), ShowCmd)
916 end;
917end;
918
919function Tnt_LoadLibraryW(lpLibFileName: PWideChar): HMODULE;
920begin
921 if Win32PlatformIsUnicode then
922 Result := LoadLibraryW{TNT-ALLOW LoadLibraryW}(lpLibFileName)
923 else
924 Result := LoadLibraryA{TNT-ALLOW LoadLibraryA}(PAnsiChar(AnsiString(lpLibFileName)));
925end;
926
927function Tnt_LoadLibraryExW(lpLibFileName: PWideChar; hFile: THandle; dwFlags: DWORD): HMODULE;
928begin
929 if Win32PlatformIsUnicode then
930 Result := LoadLibraryExW{TNT-ALLOW LoadLibraryExW}(lpLibFileName, hFile, dwFlags)
931 else
932 Result := LoadLibraryExA{TNT-ALLOW LoadLibraryExA}(PAnsiChar(AnsiString(lpLibFileName)), hFile, dwFlags);
933end;
934
935function Tnt_CreateProcessW(lpApplicationName: PWideChar; lpCommandLine: PWideChar;
936 lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
937 bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
938 lpCurrentDirectory: PWideChar; const lpStartupInfo: TStartupInfoW;
939 var lpProcessInformation: TProcessInformation): BOOL;
940var
941 AnsiStartupInfo: TStartupInfoA;
942begin
943 if Win32PlatformIsUnicode then begin
944 Result := CreateProcessW{TNT-ALLOW CreateProcessW}(lpApplicationName, lpCommandLine,
945 lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
946 lpCurrentDirectory, lpStartupInfo, lpProcessInformation)
947 end else begin
948 CopyMemory(@AnsiStartupInfo, @lpStartupInfo, SizeOf(TStartupInfo));
949 AnsiStartupInfo.lpReserved := _PAnsiCharWithNil(AnsiString(lpStartupInfo.lpReserved));
950 AnsiStartupInfo.lpDesktop := _PAnsiCharWithNil(AnsiString(lpStartupInfo.lpDesktop));
951 AnsiStartupInfo.lpTitle := _PAnsiCharWithNil(AnsiString(lpStartupInfo.lpTitle));
952 Result := CreateProcessA{TNT-ALLOW CreateProcessA}(_PAnsiCharWithNil(AnsiString(lpApplicationName)),
953 _PAnsiCharWithNil(AnsiString(lpCommandLine)),
954 lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
955 _PAnsiCharWithNil(AnsiString(lpCurrentDirectory)), AnsiStartupInfo, lpProcessInformation);
956 end;
957end;
958
959function Tnt_GetCurrencyFormatW(Locale: LCID; dwFlags: DWORD; lpValue: PWideChar;
960 lpFormat: PCurrencyFmtW; lpCurrencyStr: PWideChar; cchCurrency: Integer): Integer;
961const
962 MAX_ANSI_BUFF_SIZE = 64; // can a currency string actually be larger?
963var
964 AnsiFormat: TCurrencyFmtA;
965 PAnsiFormat: PCurrencyFmtA;
966 AnsiBuff: AnsiString;
967begin
968 if Win32PlatformIsUnicode then
969 Result := GetCurrencyFormatW{TNT-ALLOW GetCurrencyFormatW}(Locale, dwFlags, lpValue, lpFormat, lpCurrencyStr, cchCurrency)
970 else begin
971 if lpFormat = nil then
972 PAnsiFormat := nil
973 else begin
974 ZeroMemory(@AnsiFormat, SizeOf(AnsiFormat));
975 AnsiFormat.NumDigits := lpFormat.NumDigits;
976 AnsiFormat.LeadingZero := lpFormat.LeadingZero;
977 AnsiFormat.Grouping := lpFormat.Grouping;
978 AnsiFormat.lpDecimalSep := PAnsiChar(AnsiString(lpFormat.lpDecimalSep));
979 AnsiFormat.lpThousandSep := PAnsiChar(AnsiString(lpFormat.lpThousandSep));
980 AnsiFormat.NegativeOrder := lpFormat.NegativeOrder;
981 AnsiFormat.PositiveOrder := lpFormat.PositiveOrder;
982 AnsiFormat.lpCurrencySymbol := PAnsiChar(AnsiString(lpFormat.lpCurrencySymbol));
983 PAnsiFormat := @AnsiFormat;
984 end;
985 SetLength(AnsiBuff, MAX_ANSI_BUFF_SIZE);
986 SetLength(AnsiBuff, GetCurrencyFormatA{TNT-ALLOW GetCurrencyFormatA}(Locale, dwFlags,
987 PAnsiChar(AnsiString(lpValue)), PAnsiFormat, PAnsiChar(AnsiBuff), MAX_ANSI_BUFF_SIZE));
988 Result := _HandleStringLengthResult(cchCurrency, lpCurrencyStr, AnsiBuff, []);
989 end;
990end;
991
992function Tnt_CompareStringW(Locale: LCID; dwCmpFlags: DWORD; lpString1: PWideChar;
993 cchCount1: Integer; lpString2: PWideChar; cchCount2: Integer): Integer;
994var
995 WideStr1, WideStr2: WideString;
996 AnsiStr1, AnsiStr2: AnsiString;
997begin
998 if Win32PlatformIsUnicode then
999 Result := CompareStringW{TNT-ALLOW CompareStringW}(Locale, dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2)
1000 else begin
1001 WideStr1 := _WStr(lpString1, cchCount1);
1002 WideStr2 := _WStr(lpString2, cchCount2);
1003 if (dwCmpFlags = 0) then begin
1004 // binary comparison
1005 if WideStr1 < WideStr2 then
1006 Result := 1
1007 else if WideStr1 = WideStr2 then
1008 Result := 2
1009 else
1010 Result := 3;
1011 end else begin
1012 AnsiStr1 := WideStr1;
1013 AnsiStr2 := WideStr2;
1014 Result := CompareStringA{TNT-ALLOW CompareStringA}(Locale, dwCmpFlags,
1015 PAnsiChar(AnsiStr1), -1, PAnsiChar(AnsiStr2), -1);
1016 end;
1017 end;
1018end;
1019
1020function Tnt_CharUpperW(lpsz: PWideChar): PWideChar;
1021var
1022 AStr: AnsiString;
1023 WStr: WideString;
1024begin
1025 if Win32PlatformIsUnicode then
1026 Result := CharUpperW{TNT-ALLOW CharUpperW}(lpsz)
1027 else begin
1028 if HiWord(Cardinal(lpsz)) = 0 then begin
1029 // literal char mode
1030 Result := lpsz;
1031 if IsWideCharMappableToAnsi(WideChar(lpsz)) then begin
1032 AStr := WideChar(lpsz); // single character may be more than one byte
1033 CharUpperA{TNT-ALLOW CharUpperA}(PAnsiChar(AStr));
1034 WStr := AStr; // should always be single wide char
1035 if Length(WStr) = 1 then
1036 Result := PWideChar(WStr[1]);
1037 end
1038 end else begin
1039 // null-terminated string mode
1040 Result := lpsz;
1041 while lpsz^ <> #0 do begin
1042 lpsz^ := WideChar(Tnt_CharUpperW(PWideChar(lpsz^)));
1043 Inc(lpsz);
1044 end;
1045 end;
1046 end;
1047end;
1048
1049function Tnt_CharUpperBuffW(lpsz: PWideChar; cchLength: DWORD): DWORD;
1050var
1051 i: integer;
1052begin
1053 if Win32PlatformIsUnicode then
1054 Result := CharUpperBuffW{TNT-ALLOW CharUpperBuffW}(lpsz, cchLength)
1055 else begin
1056 Result := cchLength;
1057 for i := 1 to cchLength do begin
1058 lpsz^ := WideChar(Tnt_CharUpperW(PWideChar(lpsz^)));
1059 Inc(lpsz);
1060 end;
1061 end;
1062end;
1063
1064function Tnt_CharLowerW(lpsz: PWideChar): PWideChar;
1065var
1066 AStr: AnsiString;
1067 WStr: WideString;
1068begin
1069 if Win32PlatformIsUnicode then
1070 Result := CharLowerW{TNT-ALLOW CharLowerW}(lpsz)
1071 else begin
1072 if HiWord(Cardinal(lpsz)) = 0 then begin
1073 // literal char mode
1074 Result := lpsz;
1075 if IsWideCharMappableToAnsi(WideChar(lpsz)) then begin
1076 AStr := WideChar(lpsz); // single character may be more than one byte
1077 CharLowerA{TNT-ALLOW CharLowerA}(PAnsiChar(AStr));
1078 WStr := AStr; // should always be single wide char
1079 if Length(WStr) = 1 then
1080 Result := PWideChar(WStr[1]);
1081 end
1082 end else begin
1083 // null-terminated string mode
1084 Result := lpsz;
1085 while lpsz^ <> #0 do begin
1086 lpsz^ := WideChar(Tnt_CharLowerW(PWideChar(lpsz^)));
1087 Inc(lpsz);
1088 end;
1089 end;
1090 end;
1091end;
1092
1093function Tnt_CharLowerBuffW(lpsz: PWideChar; cchLength: DWORD): DWORD;
1094var
1095 i: integer;
1096begin
1097 if Win32PlatformIsUnicode then
1098 Result := CharLowerBuffW{TNT-ALLOW CharLowerBuffW}(lpsz, cchLength)
1099 else begin
1100 Result := cchLength;
1101 for i := 1 to cchLength do begin
1102 lpsz^ := WideChar(Tnt_CharLowerW(PWideChar(lpsz^)));
1103 Inc(lpsz);
1104 end;
1105 end;
1106end;
1107
1108function Tnt_GetStringTypeExW(Locale: LCID; dwInfoType: DWORD;
1109 lpSrcStr: PWideChar; cchSrc: Integer; var lpCharType): BOOL;
1110var
1111 AStr: AnsiString;
1112begin
1113 if Win32PlatformIsUnicode then
1114 Result := GetStringTypeExW{TNT-ALLOW GetStringTypeExW}(Locale, dwInfoType, lpSrcStr, cchSrc, lpCharType)
1115 else begin
1116 AStr := _WStr(lpSrcStr, cchSrc);
1117 Result := GetStringTypeExA{TNT-ALLOW GetStringTypeExA}(Locale, dwInfoType,
1118 PAnsiChar(AStr), -1, lpCharType);
1119 end;
1120end;
1121
1122function Win9x_LoadStringW(hInstance: HINST; uID: UINT; lpBuffer: PWideChar; nBufferMax: Integer): Integer;
1123// This function originated by the WINE Project.
1124// It was translated to Pascal by Francisco Leong.
1125// It was further modified by Troy Wolbrink.
1126var
1127 hmem: HGLOBAL;
1128 hrsrc: THandle;
1129 p: PWideChar;
1130 string_num, i: Integer;
1131 block: Integer;
1132begin
1133 Result := 0;
1134 // Netscape v3 fix...
1135 if (HIWORD(uID) = $FFFF) then begin
1136 uID := UINT(-(Integer(uID)));
1137 end;
1138 // figure block, string_num
1139 block := ((uID shr 4) and $FFFF) + 1; // bits 4 - 19, mask out bits 20 - 31, inc by 1
1140 string_num := uID and $000F;
1141 // get handle & pointer to string block
1142 hrsrc := FindResource{TNT-ALLOW FindResource}(hInstance, MAKEINTRESOURCE(block), RT_STRING);
1143 if (hrsrc <> 0) then
1144 begin
1145 hmem := LoadResource(hInstance, hrsrc);
1146 if (hmem <> 0) then
1147 begin
1148 p := LockResource(hmem);
1149 // walk the block to the requested string
1150 for i := 0 to string_num - 1 do begin
1151 p := p + Integer(p^) + 1;
1152 end;
1153 Result := Integer(p^); { p points to the length of string }
1154 Inc(p); { p now points to the actual string }
1155 if (lpBuffer <> nil) and (nBufferMax > 0) then
1156 begin
1157 Result := min(nBufferMax - 1, Result); { max length to copy }
1158 if (Result > 0) then begin
1159 CopyMemory(lpBuffer, p, Result * sizeof(WideChar));
1160 end;
1161 lpBuffer[Result] := WideChar(0); { null terminate }
1162 end;
1163 end;
1164 end;
1165end;
1166
1167function Tnt_LoadStringW(hInstance: HINST; uID: UINT; lpBuffer: PWideChar; nBufferMax: Integer): Integer;
1168begin
1169 if Win32PlatformIsUnicode then
1170 Result := Windows.LoadStringW{TNT-ALLOW LoadStringW}(hInstance, uID, lpBuffer, nBufferMax)
1171 else
1172 Result := Win9x_LoadStringW(hInstance, uID, lpBuffer, nBufferMax);
1173end;
1174
1175function Tnt_InsertMenuItemW(hMenu: HMENU; uItem: DWORD; fByPosition: BOOL; lpmii: TMenuItemInfoW): BOOL;
1176begin
1177 if Win32PlatformIsUnicode then
1178 Result := InsertMenuItemW{TNT-ALLOW InsertMenuItemW}(hMenu, uItem, fByPosition, lpmii)
1179 else begin
1180 TMenuItemInfoA(lpmii).dwTypeData := PAnsiChar(AnsiString(lpmii.dwTypeData));
1181 Result := InsertMenuItemA{TNT-ALLOW InsertMenuItemA}(hMenu, uItem, fByPosition, TMenuItemInfoA(lpmii));
1182 end;
1183end;
1184
1185function Tnt_ExtractIconExW(lpszFile: PWideChar; nIconIndex: Integer;
1186 var phiconLarge, phiconSmall: HICON; nIcons: UINT): UINT;
1187begin
1188 if Win32PlatformIsUnicode then
1189 Result := ExtractIconExW{TNT-ALLOW ExtractIconExW}(lpszFile,
1190 nIconIndex, phiconLarge, phiconSmall, nIcons)
1191 else
1192 Result := ExtractIconExA{TNT-ALLOW ExtractIconExA}(PAnsiChar(AnsiString(lpszFile)),
1193 nIconIndex, phiconLarge, phiconSmall, nIcons);
1194end;
1195
1196function Tnt_ExtractAssociatedIconW(hInst: HINST; lpIconPath: PWideChar;
1197 var lpiIcon: Word): HICON;
1198begin
1199 if Win32PlatformIsUnicode then
1200 Result := ExtractAssociatedIconW{TNT-ALLOW ExtractAssociatedIconW}(hInst, lpIconPath, lpiIcon)
1201 else
1202 Result := ExtractAssociatedIconA{TNT-ALLOW ExtractAssociatedIconA}(hInst,
1203 PAnsiChar(AnsiString(lpIconPath)), lpiIcon)
1204end;
1205
1206function Tnt_GetFileVersionInfoSizeW(lptstrFilename: PWideChar; var lpdwHandle: DWORD): DWORD;
1207begin
1208 if Win32PlatformIsUnicode then
1209 Result := GetFileVersionInfoSizeW{TNT-ALLOW GetFileVersionInfoSizeW}(lptstrFilename, lpdwHandle)
1210 else
1211 Result := GetFileVersionInfoSizeA{TNT-ALLOW GetFileVersionInfoSizeA}(PAnsiChar(AnsiString(lptstrFilename)), lpdwHandle);
1212end;
1213
1214function Tnt_GetFileVersionInfoW(lptstrFilename: PWideChar; dwHandle, dwLen: DWORD;
1215 lpData: Pointer): BOOL;
1216begin
1217 if Win32PlatformIsUnicode then
1218 Result := GetFileVersionInfoW{TNT-ALLOW GetFileVersionInfoW}(lptstrFilename, dwHandle, dwLen, lpData)
1219 else
1220 Result := GetFileVersionInfoA{TNT-ALLOW GetFileVersionInfoA}(PAnsiChar(AnsiString(lptstrFilename)), dwHandle, dwLen, lpData);
1221end;
1222
1223var
1224 Last_VerQueryValue_String: WideString;
1225
1226function Tnt_VerQueryValueW(pBlock: Pointer; lpSubBlock: PWideChar;
1227 var lplpBuffer: Pointer; var puLen: UINT): BOOL;
1228var
1229 AnsiBuff: AnsiString;
1230begin
1231 if Win32PlatformIsUnicode then
1232 Result := VerQueryValueW{TNT-ALLOW VerQueryValueW}(pBlock, lpSubBlock, lplpBuffer, puLen)
1233 else begin
1234 Result := VerQueryValueA{TNT-ALLOW VerQueryValueA}(pBlock, PAnsiChar(AnsiString(lpSubBlock)), lplpBuffer, puLen);
1235 if WideTextPos(VQV_STRINGFILEINFO, lpSubBlock) <> 1 then
1236 else begin
1237 { /StringFileInfo, convert ansi result to unicode }
1238 SetString(AnsiBuff, PAnsiChar(lplpBuffer), puLen);
1239 Last_VerQueryValue_String := AnsiBuff;
1240 lplpBuffer := PWideChar(Last_VerQueryValue_String);
1241 puLen := Length(Last_VerQueryValue_String);
1242 end;
1243 end;
1244end;
1245
1246//---------------------------------------------------------------------------------------
1247// Wide functions from Shell32.dll should be loaded dynamically (no stub on early Win95)
1248//---------------------------------------------------------------------------------------
1249
1250type
1251 TSHFileOperationW = function(var lpFileOp: TSHFileOpStructW): Integer; stdcall;
1252 TSHBrowseForFolderW = function(var lpbi: TBrowseInfoW): PItemIDList; stdcall;
1253 TSHGetPathFromIDListW = function(pidl: PItemIDList; pszPath: PWideChar): BOOL; stdcall;
1254 TSHGetFileInfoW = function(pszPath: PWideChar; dwFileAttributes: DWORD;
1255 var psfi: TSHFileInfoW; cbFileInfo, uFlags: UINT): DWORD; stdcall;
1256
1257var
1258 Safe_SHFileOperationW: TSHFileOperationW = nil;
1259 Safe_SHBrowseForFolderW: TSHBrowseForFolderW = nil;
1260 Safe_SHGetPathFromIDListW: TSHGetPathFromIDListW = nil;
1261 Safe_SHGetFileInfoW: TSHGetFileInfoW = nil;
1262
1263var Shell32DLL: HModule = 0;
1264
1265procedure LoadWideShell32Procs;
1266begin
1267 if Shell32DLL = 0 then begin
1268 Shell32DLL := WinCheckH(Tnt_LoadLibraryW('shell32.dll'));
1269 Safe_SHFileOperationW := WinCheckP(GetProcAddress(Shell32DLL, 'SHFileOperationW'));
1270 Safe_SHBrowseForFolderW := WinCheckP(GetProcAddress(Shell32DLL, 'SHBrowseForFolderW'));
1271 Safe_SHGetPathFromIDListW := WinCheckP(GetProcAddress(Shell32DLL, 'SHGetPathFromIDListW'));
1272 Safe_SHGetFileInfoW := WinCheckP(GetProcAddress(Shell32DLL, 'SHGetFileInfoW'));
1273 end;
1274end;
1275
1276function Tnt_SHFileOperationW(var lpFileOp: TSHFileOpStructW): Integer;
1277var
1278 AnsiFileOp: TSHFileOpStructA;
1279 MapCount: Integer;
1280 PAnsiMap: PSHNameMappingA;
1281 PWideMap: PSHNameMappingW;
1282 OldPath: WideString;
1283 NewPath: WideString;
1284 i: integer;
1285begin
1286 if Win32PlatformIsUnicode then begin
1287 LoadWideShell32Procs;
1288 Result := Safe_SHFileOperationW(lpFileOp);
1289 end else begin
1290 AnsiFileOp := TSHFileOpStructA(lpFileOp);
1291 // convert PChar -> PWideChar
1292 if lpFileOp.pFrom = nil then
1293 AnsiFileOp.pFrom := nil
1294 else
1295 AnsiFileOp.pFrom := PAnsiChar(AnsiString(ExtractStringArrayStr(lpFileOp.pFrom)));
1296 if lpFileOp.pTo = nil then
1297 AnsiFileOp.pTo := nil
1298 else
1299 AnsiFileOp.pTo := PAnsiChar(AnsiString(ExtractStringArrayStr(lpFileOp.pTo)));
1300 AnsiFileOp.lpszProgressTitle := PAnsiChar(AnsiString(lpFileOp.lpszProgressTitle));
1301 Result := SHFileOperationA{TNT-ALLOW SHFileOperationA}(AnsiFileOp);
1302 // return struct results
1303 lpFileOp.fAnyOperationsAborted := AnsiFileOp.fAnyOperationsAborted;
1304 lpFileOp.hNameMappings := nil;
1305 if (AnsiFileOp.hNameMappings <> nil)
1306 and ((FOF_WANTMAPPINGHANDLE and AnsiFileOp.fFlags) <> 0) then begin
1307 // alloc mem
1308 MapCount := PSHNameMappingHeaderA(AnsiFileOp.hNameMappings).cNumOfMappings;
1309 lpFileOp.hNameMappings :=
1310 AllocMem(SizeOf({hNameMappings}Cardinal) + SizeOf(TSHNameMappingW) * MapCount);
1311 PSHNameMappingHeaderW(lpFileOp.hNameMappings).cNumOfMappings := MapCount;
1312 // init pointers
1313 PAnsiMap := PSHNameMappingHeaderA(AnsiFileOp.hNameMappings).lpNM;
1314 PWideMap := PSHNameMappingHeaderW(lpFileOp.hNameMappings).lpNM;
1315 for i := 1 to MapCount do begin
1316 // old path
1317 OldPath := Copy(PAnsiMap.pszOldPath, 1, PAnsiMap.cchOldPath);
1318 PWideMap.pszOldPath := WStrNew(PWideChar(OldPath));
1319 PWideMap.cchOldPath := WStrLen(PWideMap.pszOldPath);
1320 // new path
1321 NewPath := Copy(PAnsiMap.pszNewPath, 1, PAnsiMap.cchNewPath);
1322 PWideMap.pszNewPath := WStrNew(PWideChar(NewPath));
1323 PWideMap.cchNewPath := WStrLen(PWideMap.pszNewPath);
1324 // next record
1325 Inc(PAnsiMap);
1326 Inc(PWideMap);
1327 end;
1328 end;
1329 end;
1330end;
1331
1332procedure Tnt_SHFreeNameMappings(hNameMappings: THandle);
1333var
1334 i: integer;
1335 MapCount: Integer;
1336 PWideMap: PSHNameMappingW;
1337begin
1338 if Win32PlatformIsUnicode then
1339 SHFreeNameMappings{TNT-ALLOW SHFreeNameMappings}(hNameMappings)
1340 else begin
1341 // free strings
1342 MapCount := PSHNameMappingHeaderW(hNameMappings).cNumOfMappings;
1343 PWideMap := PSHNameMappingHeaderW(hNameMappings).lpNM;
1344 for i := 1 to MapCount do begin
1345 WStrDispose(PWideMap.pszOldPath);
1346 WStrDispose(PWideMap.pszNewPath);
1347 Inc(PWideMap);
1348 end;
1349 // free struct
1350 FreeMem(Pointer(hNameMappings));
1351 end;
1352end;
1353
1354function Tnt_SHBrowseForFolderW(var lpbi: TBrowseInfoW): PItemIDList;
1355var
1356 AnsiInfo: TBrowseInfoA;
1357 AnsiBuffer: array[0..MAX_PATH] of AnsiChar;
1358begin
1359 if Win32PlatformIsUnicode then begin
1360 LoadWideShell32Procs;
1361 Result := Safe_SHBrowseForFolderW(lpbi);
1362 end else begin
1363 AnsiInfo := TBrowseInfoA(lpbi);
1364 AnsiInfo.lpszTitle := PAnsiChar(AnsiString(lpbi.lpszTitle));
1365 if lpbi.pszDisplayName <> nil then
1366 AnsiInfo.pszDisplayName := AnsiBuffer;
1367 Result := SHBrowseForFolderA{TNT-ALLOW SHBrowseForFolderA}(AnsiInfo);
1368 if lpbi.pszDisplayName <> nil then
1369 WStrPCopy(lpbi.pszDisplayName, AnsiInfo.pszDisplayName);
1370 lpbi.iImage := AnsiInfo.iImage;
1371 end;
1372end;
1373
1374function Tnt_SHGetPathFromIDListW(pidl: PItemIDList; pszPath: PWideChar): BOOL;
1375var
1376 AnsiPath: AnsiString;
1377begin
1378 if Win32PlatformIsUnicode then begin
1379 LoadWideShell32Procs;
1380 Result := Safe_SHGetPathFromIDListW(pidl, pszPath);
1381 end else begin
1382 SetLength(AnsiPath, MAX_PATH);
1383 Result := SHGetPathFromIDListA{TNT-ALLOW SHGetPathFromIDListA}(pidl, PAnsiChar(AnsiPath));
1384 if Result then
1385 WStrPCopy(pszPath, PAnsiChar(AnsiPath))
1386 end;
1387end;
1388
1389function Tnt_SHGetFileInfoW(pszPath: PWideChar; dwFileAttributes: DWORD;
1390 var psfi: TSHFileInfoW; cbFileInfo, uFlags: UINT): DWORD;
1391var
1392 SHFileInfoA: TSHFileInfoA;
1393begin
1394 if Win32PlatformIsUnicode then begin
1395 LoadWideShell32Procs;
1396 Result := Safe_SHGetFileInfoW(pszPath, dwFileAttributes, psfi, cbFileInfo, uFlags)
1397 end else begin
1398 Result := SHGetFileInfoA{TNT-ALLOW SHGetFileInfoA}(PAnsiChar(AnsiString(pszPath)),
1399 dwFileAttributes, SHFileInfoA, SizeOf(TSHFileInfoA), uFlags);
1400 // update pfsi...
1401 ZeroMemory(@psfi, SizeOf(TSHFileInfoW));
1402 psfi.hIcon := SHFileInfoA.hIcon;
1403 psfi.iIcon := SHFileInfoA.iIcon;
1404 psfi.dwAttributes := SHFileInfoA.dwAttributes;
1405 WStrPLCopy(psfi.szDisplayName, SHFileInfoA.szDisplayName, MAX_PATH);
1406 WStrPLCopy(psfi.szTypeName, SHFileInfoA.szTypeName, 80);
1407 end;
1408end;
1409
1410
1411function Tnt_Is_IntResource(ResStr: LPCWSTR): Boolean;
1412begin
1413 Result := HiWord(Cardinal(ResStr)) = 0;
1414end;
1415
1416function LANGIDFROMLCID(lcid: LCID): WORD;
1417begin
1418 Result := LoWord(lcid);
1419end;
1420
1421function MAKELANGID(usPrimaryLanguage, usSubLanguage: WORD): WORD;
1422begin
1423 Result := (usSubLanguage shl 10) or usPrimaryLanguage;
1424end;
1425
1426function MAKELCID(wLanguageID: WORD; wSortID: WORD = SORT_DEFAULT): LCID;
1427begin
1428 Result := MakeLong(wLanguageID, wSortID);
1429end;
1430
1431function PRIMARYLANGID(lgid: WORD): WORD;
1432begin
1433 Result := lgid and $03FF;
1434end;
1435
1436function SORTIDFROMLCID(lcid: LCID): WORD;
1437begin
1438 Result := HiWord(lcid);
1439end;
1440
1441function SUBLANGID(lgid: WORD): WORD;
1442begin
1443 Result := lgid shr 10;
1444end;
1445
1446initialization
1447
1448finalization
1449 if Shell32DLL <> 0 then
1450 FreeLibrary(Shell32DLL);
1451
1452end.
Note: See TracBrowser for help on using the repository browser.