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.

1384 lines
32 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. Utils.C
  5. Abstract:
  6. a collection of utility functions used by other routines.
  7. Author:
  8. Bob Watson (a-robw)
  9. Revision History:
  10. 24 Aug 1994 Written
  11. --*/
  12. #include <windows.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include <io.h>
  17. #include <fcntl.h>
  18. #include <sys\stat.h>
  19. #include "c2inc.h"
  20. #include "c2utils.h"
  21. #include "strings.h"
  22. #define NUM_BUFS 4
  23. //
  24. // local "helper" functions
  25. //
  26. static
  27. BOOL
  28. MediaPresent (
  29. IN LPCTSTR szPath,
  30. IN BOOL bPresentAndValid
  31. )
  32. /*++
  33. Routine Description:
  34. determines if the specified path is present and available
  35. Arguments:
  36. IN LPCTSTR szPath
  37. path to examine (Must be a DOS path)
  38. Return Value:
  39. TRUE: path is available
  40. FALSE: unable to find/open path
  41. --*/
  42. {
  43. BOOL bMediaPresent = FALSE;
  44. TCHAR szDev[8];
  45. DWORD dwBytes = 0;
  46. DWORD dwAttrib;
  47. DWORD dwLastError = ERROR_SUCCESS;
  48. UINT nErrorMode;
  49. if (!IsUncPath(szPath)) {
  50. // build device name string
  51. szDev[0] = szPath[0];
  52. szDev[1] = cColon;
  53. szDev[2] = cBackslash;
  54. szDev[3] = 0;
  55. // disable windows error message popup
  56. nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  57. dwAttrib = QuietGetFileAttributes (szDev);
  58. if ((dwAttrib != 0xFFFFFFFF) && ((dwAttrib & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) {
  59. // if the root dir is a dir, then it must be present and formatted
  60. bMediaPresent = TRUE;
  61. } else {
  62. // otherwise see if it's present and not formatted or not present
  63. dwLastError = GetMyLastError();
  64. if (dwLastError == ERROR_NOT_READY) {
  65. // then no disk in drive
  66. bMediaPresent = FALSE;
  67. } else if ((dwLastError == ERROR_FILE_NOT_FOUND) ||
  68. (dwLastError == ERROR_UNRECOGNIZED_MEDIA)) {
  69. // then and UNFORMATTED disk is in drive
  70. if (bPresentAndValid) {
  71. // this isn't good enough if it's supposed to be formatted
  72. bMediaPresent = FALSE;
  73. } else {
  74. // we're just looking for a disk so this is OK
  75. bMediaPresent = TRUE;
  76. }
  77. }
  78. }
  79. SetErrorMode (nErrorMode); // restore old error mode
  80. } else {
  81. // assume UNC path devices are present
  82. bMediaPresent = TRUE;
  83. }
  84. return bMediaPresent;
  85. }
  86. //
  87. // Global functions
  88. //
  89. DWORD
  90. QuietGetFileAttributes (
  91. IN LPCTSTR lpszFileName
  92. )
  93. /*++
  94. Routine Description:
  95. Reads the attributes of the path in lpzsFileName without triggering
  96. any Windows error dialog if there's an OS error (e.g. drive not
  97. ready)
  98. Arguments:
  99. IN LPCTSTR lpszFileName
  100. path to retrieve attributes from
  101. Return Value:
  102. file attributes DWORD returned from GetFileAttributes or
  103. 0xFFFFFFFF if unable to open path.
  104. --*/
  105. {
  106. DWORD dwReturn;
  107. UINT nErrorMode;
  108. unsigned uAttrib; // used in WIN 16 builds only
  109. // disable windows error message popup
  110. nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  111. #ifdef WIN32
  112. dwReturn = GetFileAttributes (lpszFileName);
  113. uAttrib = 0; // to prevent unused var error in WIN32 build
  114. #else // WIN16
  115. if (_dos_getfileattr (lpszFileName, &uAttrib) == 0) {
  116. dwReturn = uAttrib;
  117. } else {
  118. dwReturn = 0xFFFFFFFF;
  119. SetLastError (ERROR_FILE_NOT_FOUND);
  120. }
  121. #endif
  122. SetErrorMode (nErrorMode); // restore old error mode
  123. return dwReturn;
  124. }
  125. BOOL
  126. EnableSecurityPriv (
  127. )
  128. {
  129. HANDLE hToken;
  130. LUID SeSecurityNameValue;
  131. TOKEN_PRIVILEGES tkp;
  132. /* Retrieve a handle of the access token. */
  133. if (!OpenProcessToken(GetCurrentProcess(),
  134. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  135. &hToken)) {
  136. return FALSE;
  137. }
  138. /*
  139. * Enable the SE_SECURITY_NAME privilege
  140. */
  141. if (!LookupPrivilegeValue((LPCTSTR) NULL,
  142. SE_SECURITY_NAME,
  143. &SeSecurityNameValue)) {
  144. return FALSE;
  145. }
  146. tkp.PrivilegeCount = 1;
  147. tkp.Privileges[0].Luid = SeSecurityNameValue;
  148. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  149. AdjustTokenPrivileges(hToken,
  150. FALSE,
  151. &tkp,
  152. sizeof(TOKEN_PRIVILEGES),
  153. (PTOKEN_PRIVILEGES) NULL,
  154. (PDWORD) NULL);
  155. if (GetLastError() != ERROR_SUCCESS) {
  156. return FALSE;
  157. } else {
  158. return TRUE;
  159. }
  160. }
  161. BOOL
  162. EnableAllPriv (
  163. )
  164. /*++
  165. Routine Description:
  166. This routine enables all privileges in the token.
  167. Arguments:
  168. None.
  169. Return Value:
  170. None.
  171. --*/
  172. {
  173. HANDLE Token;
  174. ULONG ReturnLength, Index;
  175. PTOKEN_PRIVILEGES NewState;
  176. BOOL Result;
  177. Token = NULL;
  178. NewState = NULL;
  179. Result = OpenProcessToken( GetCurrentProcess(),
  180. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  181. &Token
  182. );
  183. if (Result) {
  184. ReturnLength = 4096;
  185. NewState = malloc( ReturnLength );
  186. Result = (BOOL)(NewState != NULL);
  187. if (Result) {
  188. Result = GetTokenInformation( Token, // TokenHandle
  189. TokenPrivileges, // TokenInformationClass
  190. NewState, // TokenInformation
  191. ReturnLength, // TokenInformationLength
  192. &ReturnLength // ReturnLength
  193. );
  194. if (Result) {
  195. //
  196. // Set the state settings so that all privileges are enabled...
  197. //
  198. if (NewState->PrivilegeCount > 0) {
  199. for (Index = 0; Index < NewState->PrivilegeCount; Index++ ) {
  200. NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
  201. }
  202. }
  203. Result = AdjustTokenPrivileges( Token, // TokenHandle
  204. FALSE, // DisableAllPrivileges
  205. NewState, // NewState (OPTIONAL)
  206. ReturnLength, // BufferLength
  207. NULL, // PreviousState (OPTIONAL)
  208. &ReturnLength // ReturnLength
  209. );
  210. }
  211. }
  212. }
  213. if (NewState != NULL) {
  214. free( NewState );
  215. }
  216. if (Token != NULL) {
  217. CloseHandle( Token );
  218. }
  219. return( Result );
  220. }
  221. #ifdef _UNICODE
  222. FARPROC
  223. GetProcAddressW (
  224. IN HMODULE hModule,
  225. IN LPCWSTR lpwszProc
  226. )
  227. {
  228. LPSTR szProc;
  229. LONG lProcLen;
  230. LONG lAnsiLen;
  231. FARPROC lpReturn;
  232. lProcLen = lstrlen(lpwszProc);
  233. szProc = GLOBAL_ALLOC (lProcLen + 1);
  234. if (szProc != NULL) {
  235. lAnsiLen = wcstombs (szProc, lpwszProc, lProcLen);
  236. if (lAnsiLen == lProcLen) {
  237. lpReturn = GetProcAddress (
  238. hModule,
  239. szProc);
  240. } else {
  241. lpReturn = NULL;
  242. }
  243. // free allocated string buffer
  244. GLOBAL_FREE_IF_ALLOC (szProc);
  245. } else {
  246. lpReturn = NULL;
  247. }
  248. return lpReturn;
  249. }
  250. #endif
  251. #ifdef _UNICODE
  252. HFILE
  253. OpenFileW(
  254. LPCTSTR lpwszFile,
  255. LPWOFSTRUCT lpWOpenBuff,
  256. UINT fuMode
  257. )
  258. {
  259. LPSTR szFileName;
  260. OFSTRUCT ofStruct;
  261. HFILE hReturn;
  262. LONG lFileNameLen;
  263. LONG lAnsiNameLen;
  264. // check arguments
  265. if ((lpwszFile == NULL) || (lpWOpenBuff == NULL)) {
  266. SetLastError (ERROR_INVALID_PARAMETER);
  267. hReturn = HFILE_ERROR;
  268. } else {
  269. lFileNameLen = lstrlen(lpwszFile);
  270. szFileName = GLOBAL_ALLOC (lFileNameLen + 1);
  271. if (szFileName != NULL) {
  272. lAnsiNameLen = wcstombs (szFileName, lpwszFile, lFileNameLen);
  273. if (lAnsiNameLen == lFileNameLen) {
  274. hReturn = OpenFile (
  275. szFileName,
  276. &ofStruct,
  277. fuMode);
  278. if (hReturn != HFILE_ERROR){
  279. lpWOpenBuff->cBytes = ofStruct.cBytes;
  280. lpWOpenBuff->fFixedDisk = ofStruct.fFixedDisk;
  281. lpWOpenBuff->nErrCode = ofStruct.nErrCode;
  282. lpWOpenBuff->Reserved1 = ofStruct.Reserved1;
  283. lpWOpenBuff->Reserved2 = ofStruct.Reserved2;
  284. lAnsiNameLen = strlen (ofStruct.szPathName);
  285. mbstowcs (lpWOpenBuff->szPathName,
  286. ofStruct.szPathName, lAnsiNameLen);
  287. }
  288. }
  289. GLOBAL_FREE_IF_ALLOC (szFileName);
  290. } else {
  291. SetLastError (ERROR_OUTOFMEMORY);
  292. hReturn = HFILE_ERROR;
  293. }
  294. }
  295. return hReturn;
  296. }
  297. #endif
  298. BOOL
  299. TrimSpaces (
  300. IN OUT LPTSTR szString
  301. )
  302. /*++
  303. Routine Description:
  304. Trims leading and trailing spaces from szString argument, modifying
  305. the buffer passed in
  306. Arguments:
  307. IN OUT LPTSTR szString
  308. buffer to process
  309. Return Value:
  310. TRUE if string was modified
  311. FALSE if not
  312. --*/
  313. {
  314. LPTSTR szSource;
  315. LPTSTR szDest;
  316. LPTSTR szLast;
  317. BOOL bChars;
  318. szLast = szSource = szDest = szString;
  319. bChars = FALSE;
  320. while (*szSource != 0) {
  321. // skip leading non-space chars
  322. if (*szSource > cSpace) {
  323. szLast = szDest;
  324. bChars = TRUE;
  325. }
  326. if (bChars) {
  327. // remember last non-space character
  328. // copy source to destination & increment both
  329. *szDest++ = *szSource++;
  330. } else {
  331. szSource++;
  332. }
  333. }
  334. if (bChars) {
  335. *++szLast = 0; // terminate after last non-space char
  336. } else {
  337. // string was all spaces so return an empty (0-len) string
  338. *szString = 0;
  339. }
  340. return (szLast != szSource);
  341. }
  342. BOOL
  343. IsUncPath (
  344. IN LPCTSTR szPath
  345. )
  346. /*++
  347. Routine Description:
  348. examines path as a string looking for "tell-tale" double
  349. backslash indicating the machine name syntax of a UNC path
  350. Arguments:
  351. IN LPCTSTR szPath
  352. path to examine
  353. Return Value:
  354. TRUE if \\ found at start of string
  355. FALSE if not
  356. --*/
  357. {
  358. LPTSTR szPtChar;
  359. szPtChar = (LPTSTR)szPath;
  360. if (*szPtChar == cBackslash) {
  361. if (*++szPtChar == cBackslash) {
  362. return TRUE;
  363. }
  364. }
  365. return FALSE;
  366. }
  367. LPTSTR
  368. GetFileNameFromPath (
  369. IN LPCTSTR szPath
  370. )
  371. {
  372. LPTSTR szLastBs;
  373. LPTSTR szThisChar;
  374. szLastBs = (LPTSTR)szPath;
  375. for (szThisChar = (LPTSTR)szPath; *szThisChar != 0; szThisChar++) {
  376. if (*szThisChar == cBackslash) {
  377. szLastBs = szThisChar;
  378. }
  379. }
  380. if (*szLastBs == cBackslash) {
  381. szLastBs++;
  382. }
  383. return szLastBs;
  384. }
  385. BOOL
  386. CenterWindow (
  387. HWND hwndChild,
  388. HWND hwndParent
  389. )
  390. /*++
  391. Routine Description:
  392. Centers the child window in the Parent window
  393. Arguments:
  394. HWND hwndChild,
  395. handle of child window to center
  396. HWND hwndParent
  397. handle of parent window to center child window in
  398. ReturnValue:
  399. Return value of SetWindowPos
  400. --*/
  401. {
  402. RECT rChild, rParent;
  403. LONG wChild, hChild, wParent, hParent;
  404. LONG wScreen, hScreen, xNew, yNew;
  405. HDC hdc;
  406. // Get the Height and Width of the child window
  407. GetWindowRect (hwndChild, &rChild);
  408. wChild = rChild.right - rChild.left;
  409. hChild = rChild.bottom - rChild.top;
  410. // Get the Height and Width of the parent window
  411. GetWindowRect (hwndParent, &rParent);
  412. wParent = rParent.right - rParent.left;
  413. hParent = rParent.bottom - rParent.top;
  414. // Get the display limits
  415. hdc = GetDC (hwndChild);
  416. wScreen = GetDeviceCaps (hdc, HORZRES);
  417. hScreen = GetDeviceCaps (hdc, VERTRES);
  418. ReleaseDC (hwndChild, hdc);
  419. // Calculate new X position, then adjust for screen
  420. xNew = rParent.left + ((wParent - wChild) /2);
  421. if (xNew < 0) {
  422. xNew = 0;
  423. } else if ((xNew+wChild) > wScreen) {
  424. xNew = wScreen - wChild;
  425. }
  426. // Calculate new Y position, then adjust for screen
  427. yNew = rParent.top + ((hParent - hChild) /2);
  428. if (yNew < 0) {
  429. yNew = 0;
  430. } else if ((yNew+hChild) > hScreen) {
  431. yNew = hScreen - hChild;
  432. }
  433. // Set it, and return
  434. return SetWindowPos (hwndChild, NULL,
  435. (int)xNew, (int)yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  436. }
  437. UINT
  438. GetDriveTypeFromDosPath (
  439. IN LPCTSTR szDosPath
  440. )
  441. /*++
  442. Routine Description:
  443. Strips the filename and path from the path in the argument and returns
  444. the drive type as returned by the GetDriveType Win32 API fn.
  445. Arguments:
  446. IN LPCTSTR szDosPath
  447. dos path in the format: <Drive>:\path... This format is NOT checked
  448. by the function!
  449. Return Value:
  450. DRIVE TYPE value returned by the GetDriveType API.
  451. --*/
  452. {
  453. #ifdef WIN32
  454. TCHAR szRootDir[4];
  455. szRootDir[0] = szDosPath[0];
  456. szRootDir[1] = cColon;
  457. szRootDir[2] = cBackslash;
  458. szRootDir[3] = 0;
  459. #else // win16 version isn't as robust
  460. int szRootDir; // not really an SZ, but it keeps the call compatible
  461. TCHAR szLocalPath[4];
  462. szLocalPath[0] = szDosPath[0];
  463. szLocalPath[1] = 0;
  464. _strupr(szLocalPath);
  465. szRootDir = szLocalPath[0] - cA;
  466. #endif
  467. return (GetDriveType(szRootDir));
  468. }
  469. LPCTSTR
  470. GetItemFromIniEntry (
  471. IN LPCTSTR szEntry,
  472. IN DWORD dwItem
  473. )
  474. /*++
  475. Routine Description:
  476. returns nth item from comma separated list returned from
  477. inf file. leaves (double)quoted strings intact.
  478. Arguments:
  479. IN LPCTSTR szEntry
  480. entry string returned from INF file
  481. IN DWORD dwItem
  482. 1-based index indicating which item to return. (i.e. 1= first item
  483. in list, 2= second, etc.)
  484. Return Value:
  485. pointer to buffer containing desired entry in string. Note, this
  486. routine may only be called 4 times before the string
  487. buffer is re-used. (i.e. don't use this function more than
  488. 4 times in single function call!!)
  489. --*/
  490. {
  491. static TCHAR szReturnBuffer[4][MAX_PATH];
  492. static LONG dwBuff;
  493. LPTSTR szSource, szDest;
  494. DWORD dwThisItem;
  495. dwBuff = ++dwBuff % 4; // wrap buffer index
  496. szSource = (LPTSTR)szEntry;
  497. szDest = &szReturnBuffer[dwBuff][0];
  498. // clear previous contents
  499. memset (szDest, 0, (MAX_PATH * sizeof(TCHAR)));
  500. // go past ini key
  501. while ((*szSource != cEqual) && (*szSource != 0)) szSource++;
  502. if (*szSource == 0){
  503. // no equals found so start at beginning
  504. // presumably this is just the "value"
  505. szSource = (LPTSTR)szEntry;
  506. } else {
  507. szSource++;
  508. }
  509. dwThisItem = 1;
  510. while (dwThisItem < dwItem) {
  511. if (*szSource != 0) {
  512. while ((*szSource != cComma) && (*szSource != 0)) {
  513. if (*szSource == cDoubleQuote) {
  514. // if this is a quote, then go to the close quote
  515. szSource++;
  516. while ((*szSource != cDoubleQuote) && (*szSource != 0)) szSource++;
  517. }
  518. if (*szSource != 0) szSource++;
  519. }
  520. }
  521. dwThisItem++;
  522. if (*szSource != 0) szSource++;
  523. }
  524. // copy this entry to the return buffer
  525. if (*szSource != 0) {
  526. while ((*szSource != cComma) && (*szSource != 0)) {
  527. if (*szSource == cDoubleQuote) {
  528. // if this is a quote, then go to the close quote
  529. // don't copy quotes!
  530. szSource++;
  531. while ((*szSource != cDoubleQuote) && (*szSource != 0)) {
  532. *szDest++ = *szSource++;
  533. }
  534. if (*szSource != 0) szSource++;
  535. } else {
  536. *szDest++ = *szSource++;
  537. }
  538. }
  539. *szDest = 0;
  540. }
  541. // remove any leading and/or trailing spaces
  542. TrimSpaces (&szReturnBuffer[dwBuff][0]);
  543. return &szReturnBuffer[dwBuff][0];
  544. }
  545. LPCTSTR
  546. GetStringResource (
  547. IN HANDLE hInstance,
  548. IN UINT nId
  549. )
  550. /*++
  551. Routine Description:
  552. look up string resource and return string
  553. Arguments:
  554. IN UINT nId
  555. Resource ID of string to look up
  556. Return Value:
  557. pointer to string referenced by ID in arg list
  558. --*/
  559. {
  560. static TCHAR szBufArray[NUM_BUFS][SMALL_BUFFER_SIZE];
  561. static DWORD dwIndex;
  562. LPTSTR szBuffer;
  563. DWORD dwLength;
  564. HANDLE hMod;
  565. if (hInstance != NULL) {
  566. hMod = hInstance;
  567. } else {
  568. hMod = GetModuleHandle(NULL);
  569. }
  570. dwIndex++;
  571. dwIndex %= NUM_BUFS;
  572. szBuffer = &szBufArray[dwIndex][0];
  573. // clear previous contents
  574. memset (szBuffer, 0, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
  575. dwLength = LoadString (
  576. hMod,
  577. nId,
  578. szBuffer,
  579. SMALL_BUFFER_SIZE);
  580. return (LPCTSTR)szBuffer;
  581. }
  582. LPCTSTR
  583. GetQuotedStringResource (
  584. IN HANDLE hInstance,
  585. IN UINT nId
  586. )
  587. /*++
  588. Routine Description:
  589. look up string resource and return string inside double quotes
  590. Arguments:
  591. IN HANDLE hInstance
  592. handle to application instance
  593. IN UINT nId
  594. Resource ID of string to look up
  595. Return Value:
  596. pointer to string referenced by ID in arg list
  597. --*/
  598. {
  599. static TCHAR szBufArray[NUM_BUFS][SMALL_BUFFER_SIZE];
  600. static DWORD dwIndex;
  601. LPTSTR szBuffer;
  602. DWORD dwLength;
  603. HANDLE hMod;
  604. if (hInstance != NULL) {
  605. hMod = hInstance;
  606. } else {
  607. hMod = GetModuleHandle(NULL);
  608. }
  609. dwIndex++;
  610. dwIndex %= NUM_BUFS;
  611. szBuffer = &szBufArray[dwIndex][0];
  612. // clear previous contents
  613. memset (szBuffer, 0, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
  614. szBuffer[0] = cSpace;
  615. szBuffer[1] = cSpace;
  616. szBuffer[2] = cDoubleQuote;
  617. dwLength = LoadString (
  618. hMod,
  619. nId,
  620. &szBuffer[3],
  621. SMALL_BUFFER_SIZE);
  622. lstrcat(szBuffer, cszDoubleQuote);
  623. return (LPCTSTR)szBuffer;
  624. }
  625. LPCTSTR
  626. EnquoteString (
  627. IN LPCTSTR szInString
  628. )
  629. /*++
  630. Routine Description:
  631. return the input string wrapped in double quotes
  632. Arguments:
  633. IN LPCTSTR szInString
  634. Return Value:
  635. pointer to string buffer containing a copy of szInString enclosed
  636. in double quotes
  637. --*/
  638. {
  639. static TCHAR szBufArray[NUM_BUFS][SMALL_BUFFER_SIZE];
  640. static DWORD dwIndex;
  641. LPTSTR szBuffer;
  642. dwIndex++;
  643. dwIndex %= NUM_BUFS;
  644. szBuffer = &szBufArray[dwIndex][0];
  645. // clear previous contents
  646. memset (szBuffer, 0, (SMALL_BUFFER_SIZE * sizeof(TCHAR)));
  647. szBuffer[0] = cSpace;
  648. szBuffer[1] = cSpace;
  649. szBuffer[2] = cDoubleQuote;
  650. lstrcpy (&szBuffer[3], szInString);
  651. lstrcat (szBuffer, cszDoubleQuote);
  652. return (LPCTSTR)szBuffer;
  653. }
  654. LONG
  655. GetExpandedFileName (
  656. IN LPTSTR szInFileName,
  657. IN DWORD dwMaxExpandedSize,
  658. OUT LPTSTR szExpandedFileName,
  659. OUT LPTSTR *pFileNamePart
  660. )
  661. /*++
  662. Routine Description:
  663. expands any environment variables in InFileName, then gets the
  664. fully qualified pathname of the result and returns that in the
  665. buffer provided by the caller
  666. Arguments:
  667. IN LPTSTR szInFileName input file string to expand
  668. IN DWORD dwMaxExpandedSize size of output Buffer
  669. OUT LPTSTR szExpandedFileName buffer to recieve expanded name
  670. OUT LPTSTR *pFileNamePart pointer to filename in output buffer
  671. ReturnValue:
  672. WIN32 error status of procedure
  673. --*/
  674. {
  675. LPTSTR szEnvBuffer;
  676. LPTSTR szPathReturn;
  677. LONG lStatus;
  678. DWORD dwSize;
  679. // validate arguments
  680. if ((szInFileName != NULL) &&
  681. (dwMaxExpandedSize != 0)) {
  682. #ifdef WIN32
  683. // allocate working buffers
  684. szEnvBuffer = (LPTSTR)GLOBAL_ALLOC (((dwMaxExpandedSize + 1) * sizeof(TCHAR)));
  685. if (szEnvBuffer != NULL) {
  686. // expand env. strings if any
  687. dwSize = ExpandEnvironmentStrings (
  688. szInFileName,
  689. szEnvBuffer,
  690. (GlobalSize(szEnvBuffer) / sizeof(TCHAR)));
  691. if (dwSize != 0) {
  692. // get full pathname
  693. CLEAR_FIRST_FOUR_BYTES(szExpandedFileName);
  694. if (GetFullPathName (
  695. szEnvBuffer,
  696. dwMaxExpandedSize,
  697. szExpandedFileName,
  698. &szPathReturn) > 0) {
  699. if (pFileNamePart != NULL) {
  700. *pFileNamePart = szPathReturn;
  701. }
  702. lStatus = ERROR_SUCCESS;
  703. } else {
  704. // unable to get full path name
  705. lStatus = ERROR_BAD_PATHNAME;
  706. }
  707. } else {
  708. // error expanding env strings
  709. lStatus = GetMyLastError();
  710. }
  711. } else {
  712. lStatus == ERROR_OUTOFMEMORY;
  713. }
  714. GLOBAL_FREE_IF_ALLOC (szEnvBuffer);
  715. #else // if WIN16
  716. strncpy (szExpandedFileName, szInFileName, (size_t)dwMaxExpandedSize);
  717. lStatus = ERROR_SUCCESS;
  718. // unreferenced vars in WIN 16 mode
  719. dwSize = dwSize;
  720. szEnvBuffer = szEnvBuffer;
  721. szPathReturn = szPathReturn;
  722. #endif
  723. } else {
  724. lStatus = ERROR_INVALID_PARAMETER; // bad argument
  725. }
  726. return lStatus;
  727. }
  728. LONG
  729. CreateDirectoryFromPath (
  730. IN LPCTSTR szPath,
  731. IN LPSECURITY_ATTRIBUTES lpSA
  732. )
  733. /*++
  734. Routine Description:
  735. Creates the directory specified in szPath and any other "higher"
  736. directories in the specified path that don't exist.
  737. Arguments:
  738. IN LPCTSTR szPath
  739. directory path to create (assumed to be a DOS path, not a UNC)
  740. IN LPSECURITY_ATTRIBUTES lpSA
  741. pointer to security attributes argument used by CreateDirectory
  742. Return Value:
  743. TRUE (non-zero) if directory(ies) created
  744. FALSE if error (GetMyLastError to find out why)
  745. --*/
  746. {
  747. LPTSTR szLocalPath;
  748. LPTSTR szEnd;
  749. LONG lReturn = 0L;
  750. szLocalPath = (LPTSTR)GLOBAL_ALLOC (MAX_PATH_BYTES);
  751. if (szLocalPath == NULL) {
  752. SetLastError (ERROR_OUTOFMEMORY);
  753. return 0;
  754. } else {
  755. // so far so good...
  756. SetLastError (ERROR_SUCCESS); // initialize error value to SUCCESS
  757. }
  758. GetExpandedFileName (
  759. (LPTSTR)szPath,
  760. MAX_PATH,
  761. szLocalPath,
  762. NULL);
  763. szEnd = &szLocalPath[3];
  764. if (*szEnd != 0) {
  765. // then there are sub dirs to create
  766. while (*szEnd != 0) {
  767. // go to next backslash
  768. while ((*szEnd != cBackslash) && (*szEnd != 0)) szEnd++;
  769. if (*szEnd == cBackslash) {
  770. // terminate path here and create directory
  771. *szEnd = 0;
  772. if (!CreateDirectory (szLocalPath, lpSA)) {
  773. // see what the error was and "adjust" it if necessary
  774. if (GetMyLastError() == ERROR_ALREADY_EXISTS) {
  775. // this is OK
  776. SetLastError (ERROR_SUCCESS);
  777. } else {
  778. lReturn = 0;
  779. }
  780. } else {
  781. // directory created successfully so update count
  782. lReturn++;
  783. }
  784. // replace backslash and go to next dir
  785. *szEnd++ = cBackslash;
  786. }
  787. }
  788. // create last dir in path now
  789. if (!CreateDirectory (szLocalPath, lpSA)) {
  790. // see what the error was and "adjust" it if necessary
  791. if (GetMyLastError() == ERROR_ALREADY_EXISTS) {
  792. // this is OK
  793. SetLastError (ERROR_SUCCESS);
  794. lReturn++;
  795. } else {
  796. lReturn = 0;
  797. }
  798. } else {
  799. // directory created successfully
  800. lReturn++;
  801. }
  802. } else {
  803. // else this is a root dir only so return success.
  804. lReturn = 1;
  805. }
  806. GLOBAL_FREE_IF_ALLOC (szLocalPath);
  807. return lReturn;
  808. }
  809. BOOL
  810. FileExists (
  811. IN LPCTSTR szPath
  812. )
  813. /*++
  814. Routine Description:
  815. returns TRUE if the file in the path argument exists (NOTE: that
  816. the file is not actually opened to save time, rather the
  817. directory entry is read in order to determine existence)
  818. Arguments:
  819. szPath pointer to filename to look up
  820. Return Value:
  821. TRUE if file exists
  822. FALSE if file not found
  823. --*/
  824. {
  825. BOOL bMediaPresent;
  826. UINT nDriveType;
  827. DWORD dwAttr;
  828. nDriveType = GetDriveTypeFromDosPath((LPTSTR)szPath);
  829. if ((nDriveType == DRIVE_REMOVABLE) || (nDriveType == DRIVE_CDROM)) {
  830. // see if a formatted drive is really there
  831. bMediaPresent = MediaPresent(szPath, TRUE);
  832. } else {
  833. // if drive is not removable, then assume it's there
  834. bMediaPresent = TRUE;
  835. }
  836. // try to get inforation on the file
  837. dwAttr = QuietGetFileAttributes ((LPTSTR)szPath);
  838. if (dwAttr == 0xFFFFFFFF) {
  839. // unable to obtain attributes, so assume it's not there
  840. // or we can't access it
  841. return FALSE;
  842. } else {
  843. // found, so close it and return TRUE
  844. return TRUE;
  845. }
  846. }
  847. LPCTSTR
  848. GetKeyFromIniEntry (
  849. IN LPCTSTR szEntry
  850. )
  851. /*++
  852. Routine Description:
  853. Arguments:
  854. Return Value:
  855. --*/
  856. {
  857. static TCHAR szReturnBuffer[MAX_PATH];
  858. LPTSTR szSource, szDest;
  859. szSource = (LPTSTR)szEntry;
  860. szDest = &szReturnBuffer[0];
  861. // clear previous contents
  862. memset (szDest, 0, (MAX_PATH * sizeof(TCHAR)));
  863. *szDest = 0;
  864. if (*szSource != 0) {
  865. while ((*szSource != cEqual) && (*szSource != 0)) {
  866. *szDest++ = *szSource++;
  867. }
  868. *szDest = 0;
  869. }
  870. TrimSpaces(szReturnBuffer);
  871. return szReturnBuffer;
  872. }
  873. DWORD
  874. StripQuotes (
  875. IN OUT LPSTR szBuff
  876. )
  877. /*++
  878. Routine Description:
  879. removes all double quote characters (") from the string in the argument.
  880. this function modifies the contents of the buffer passed in the argument
  881. list.
  882. Arguments:
  883. IN OUT LPSTR szBuff
  884. string to removed quote characters from
  885. Return Value:
  886. length of new string in characters
  887. --*/
  888. {
  889. LPSTR szSrcChar;
  890. LPSTR szDestChar;
  891. DWORD dwCharCount;
  892. szSrcChar = szBuff;
  893. szDestChar = szBuff;
  894. dwCharCount = 0;
  895. while (*szSrcChar != '\0') {
  896. if (*szSrcChar != '\"') {
  897. *szDestChar = *szSrcChar;
  898. szDestChar++;
  899. dwCharCount++;
  900. }
  901. szSrcChar++;
  902. }
  903. *szDestChar = '\0';
  904. return dwCharCount;
  905. }
  906. BOOL
  907. GetFilePath (
  908. IN LPCTSTR szFileName,
  909. OUT LPTSTR szPathBuffer
  910. )
  911. /*++
  912. Routine Description:
  913. Scans for the file specified in the argument list.
  914. The OpenFile function looks in the following directories in
  915. the following order for the INF.
  916. 1 The current directory.
  917. 2 The Windows directory (the directory containing WIN.COM),
  918. whose path the GetWindowsDirectory function retrieves.
  919. 3 The Windows system directory (the directory containing
  920. such system files as GDI.EXE), whose path the GetSystemDirectory
  921. function retrieves.
  922. 4 The directory containing the executable file for the
  923. current task; the GetModuleFileName function obtains the
  924. path of this directory.
  925. 5 The directories listed in the PATH environment variable.
  926. 6 The list of directories mapped in a network.
  927. Arguments:
  928. szFileName base filename of file to find
  929. szPathBuffer buffer that application inf file path is written to.
  930. Return Value:
  931. TRUE if a file path is written to szPathBuffer
  932. FALSE if no file is found and szPathBuffer is empty
  933. --*/
  934. {
  935. TOFSTRUCT ofFile;
  936. HFILE hFile;
  937. hFile = OpenFileT (
  938. szFileName,
  939. &ofFile,
  940. OF_SEARCH);
  941. if (hFile != HFILE_ERROR) {
  942. // file found (and opened!) successfully
  943. lstrcpy (szPathBuffer, ofFile.szPathName);
  944. _lclose(hFile); // close file handle for now.
  945. return TRUE;
  946. } else {
  947. *szPathBuffer = 0;
  948. return FALSE;
  949. }
  950. }
  951. BOOL
  952. GetInfPath (
  953. IN HWND hWnd,
  954. IN UINT nFileNameId,
  955. OUT LPTSTR szPathBuffer
  956. )
  957. /*++
  958. Routine Description:
  959. Scans for the INF file described by the string resource ID in the arg
  960. list. The OpenFile function looks in the following directories in
  961. the following order for the INF.
  962. 1 The current directory.
  963. 2 The Windows directory (the directory containing WIN.COM),
  964. whose path the GetWindowsDirectory function retrieves.
  965. 3 The Windows system directory (the directory containing
  966. such system files as GDI.EXE), whose path the GetSystemDirectory
  967. function retrieves.
  968. 4 The directory containing the executable file for the
  969. current task; the GetModuleFileName function obtains the
  970. path of this directory.
  971. 5 The directories listed in the PATH environment variable.
  972. 6 The list of directories mapped in a network.
  973. Arguments:
  974. hWnd Window handle of application main window
  975. nFileNameId ID of string resource containing filename to locate
  976. szPathBuffer buffer that application inf file path is written to.
  977. Return Value:
  978. TRUE if a file path is written to szPathBuffer
  979. FALSE if no file is found and szPathBuffer is empty
  980. --*/
  981. {
  982. return GetFilePath(
  983. GetStringResource (GET_INSTANCE(hWnd), nFileNameId),
  984. szPathBuffer);
  985. }
  986. BOOL
  987. DrawRaisedShading (
  988. IN LPRECT prShadeWnd,
  989. IN LPPAINTSTRUCT ps,
  990. IN LONG lDepth,
  991. IN HPEN hpenHighlight,
  992. IN HPEN hpenShadow
  993. )
  994. {
  995. LONG lLineDepth;
  996. RECT rWnd; // local window rectangle dimensions
  997. rWnd = *prShadeWnd; // make local copy of rectangle
  998. // adjust rectangle to fit within client area
  999. rWnd.right -= 1;
  1000. rWnd.bottom -= 1;
  1001. if ((lDepth > 0) &&
  1002. (lDepth < (rWnd.bottom / 2)) &&
  1003. (lDepth < (rWnd.right / 2))) {
  1004. // draw shading line
  1005. for (lLineDepth = 0; lLineDepth < lDepth; lLineDepth++) {
  1006. // start at bottom left corner and draw highlight
  1007. SelectObject (ps->hdc, hpenHighlight);
  1008. MoveToEx (ps->hdc, rWnd.left, rWnd.bottom, NULL);
  1009. LineTo (ps->hdc, rWnd.left, rWnd.top);
  1010. LineTo (ps->hdc, rWnd.right, rWnd.top);
  1011. // draw shadow lines
  1012. SelectObject (ps->hdc, hpenShadow);
  1013. LineTo (ps->hdc, rWnd.right, rWnd.bottom);
  1014. LineTo (ps->hdc, rWnd.left-1, rWnd.bottom);
  1015. // shrink rectangle for next iteration
  1016. rWnd.top += 1;
  1017. rWnd.left += 1;
  1018. if (rWnd.left < rWnd.right) rWnd.right -= 1;
  1019. if (rWnd.top < rWnd.bottom) rWnd.bottom -= 1;
  1020. }
  1021. return TRUE;
  1022. } else {
  1023. // depth is bigger than window
  1024. return FALSE;
  1025. }
  1026. }
  1027. BOOL
  1028. DrawSeparatorLine (
  1029. IN LPRECT lprLine,
  1030. IN LPPAINTSTRUCT ps,
  1031. IN HPEN hpenLine
  1032. )
  1033. {
  1034. SelectObject (ps->hdc, hpenLine);
  1035. return Rectangle (ps->hdc,
  1036. lprLine->left,
  1037. lprLine->top,
  1038. lprLine->right,
  1039. lprLine->bottom);
  1040. }
  1041. DWORD
  1042. GetFileSizeFromPath (
  1043. LPCTSTR szPath
  1044. )
  1045. /*++
  1046. Routine Description:
  1047. returns the size of the file specified in szPath (if it exists)
  1048. (up to 4 GB)
  1049. returns 0 byte size if:
  1050. the file could not be found
  1051. the file is 0 bytes long
  1052. Arguments:
  1053. szPath path and name of file to query
  1054. Return Value:
  1055. see description
  1056. --*/
  1057. {
  1058. HANDLE hFile;
  1059. DWORD dwSize, dwHiSize;
  1060. if (FileExists(szPath)) {
  1061. hFile = CreateFile(szPath,
  1062. GENERIC_READ,
  1063. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1064. NULL,
  1065. OPEN_EXISTING,
  1066. FILE_ATTRIBUTE_NORMAL,
  1067. NULL);
  1068. if (hFile != INVALID_HANDLE_VALUE) {
  1069. dwSize = GetFileSize (hFile, &dwHiSize);
  1070. if (dwSize == 0xFFFFFFFF) {
  1071. // an error so return 0
  1072. dwSize = 0;
  1073. } else if (dwHiSize > 0) {
  1074. // file is > 4GB so return Max Int
  1075. dwSize = 0xFFFFFFFF;
  1076. } else {
  1077. // file size was returned and <= 4GB so return size
  1078. }
  1079. CloseHandle (hFile);
  1080. return dwSize;
  1081. } else {
  1082. return 0; // unable to open file
  1083. }
  1084. } else {
  1085. return 0; // file not found
  1086. }
  1087. }