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.

598 lines
25 KiB

  1. //***************************************************************************
  2. //* Copyright (c) Microsoft Corporation 1995-1996. All rights reserved. *
  3. //***************************************************************************
  4. //* *
  5. //* NTAPI.C - *
  6. //* *
  7. //***************************************************************************
  8. //***************************************************************************
  9. //* INCLUDE FILES *
  10. //***************************************************************************
  11. #include "ntapi.h"
  12. #include <winnt.h>
  13. #include "advpack.h"
  14. #include "advpub.h"
  15. #include "globals.h"
  16. #include "resource.h"
  17. UINT WINAPI AIFSetupQueueCallback(PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2);
  18. UINT WINAPI AIFQuietSetupQueueCallback(PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2);
  19. UINT WINAPI MyFileQueueCallback2( PVOID Context,UINT Notification,UINT_PTR parm1,UINT_PTR parm2 );
  20. void MakeRootDir(LPSTR pszPath);
  21. //***************************************************************************
  22. //* GLOBAL VARIABLES *
  23. //***************************************************************************
  24. PFSetupDefaultQueueCallback pfSetupDefaultQueueCallback = NULL;
  25. PFSetupInstallFromInfSection pfSetupInstallFromInfSection = NULL;
  26. PFSetupOpenInfFile pfSetupOpenInfFile = NULL;
  27. PFSetupOpenAppendInfFile pfSetupOpenAppendInfFile = NULL;
  28. PFSetupCloseInfFile pfSetupCloseInfFile = NULL;
  29. PFSetupInitDefaultQueueCallbackEx pfSetupInitDefaultQueueCallbackEx = NULL;
  30. PFSetupTermDefaultQueueCallback pfSetupTermDefaultQueueCallback = NULL;
  31. PFSetupSetDirectoryId pfSetupSetDirectoryId = NULL;
  32. PFSetupGetLineText pfSetupGetLineText = NULL;
  33. PFSetupGetLineByIndex pfSetupGetLineByIndex = NULL;
  34. PFSetupFindFirstLine pfSetupFindFirstLine = NULL;
  35. PFSetupFindNextLine pfSetupFindNextLine = NULL;
  36. PFSetupOpenFileQueue pfSetupOpenFileQueue = NULL;
  37. PFSetupCloseFileQueue pfSetupCloseFileQueue = NULL;
  38. PFSetupQueueCopy pfSetupQueueCopy = NULL;
  39. PFSetupCommitFileQueue pfSetupCommitFileQueue = NULL;
  40. PFSetupGetStringField pfSetupGetStringField = NULL;
  41. //***************************************************************************
  42. //* *
  43. //* NAME: *
  44. //* *
  45. //* SYNOPSIS: *
  46. //* *
  47. //* REQUIRES: *
  48. //* *
  49. //* RETURNS: *
  50. //* *
  51. //***************************************************************************
  52. BOOL LoadSetupAPIFuncs( VOID )
  53. {
  54. pfSetupGetStringField = (PFSetupGetStringField) GetProcAddress( ctx.hSetupLibrary, c_szSetupGetStringField );
  55. pfSetupDefaultQueueCallback = (PFSetupDefaultQueueCallback) GetProcAddress( ctx.hSetupLibrary, c_szSetupDefaultQueueCallback );
  56. pfSetupInstallFromInfSection = (PFSetupInstallFromInfSection) GetProcAddress( ctx.hSetupLibrary, c_szSetupInstallFromInfSection );
  57. pfSetupOpenInfFile = (PFSetupOpenInfFile) GetProcAddress( ctx.hSetupLibrary, c_szSetupOpenInfFile );
  58. pfSetupOpenAppendInfFile = (PFSetupOpenAppendInfFile) GetProcAddress( ctx.hSetupLibrary, c_szSetupOpenAppendInfFile );
  59. pfSetupCloseInfFile = (PFSetupCloseInfFile) GetProcAddress( ctx.hSetupLibrary, c_szSetupCloseInfFile );
  60. pfSetupInitDefaultQueueCallbackEx = (PFSetupInitDefaultQueueCallbackEx) GetProcAddress( ctx.hSetupLibrary, c_szSetupInitDefaultQueueCallbackEx );
  61. pfSetupTermDefaultQueueCallback = (PFSetupTermDefaultQueueCallback) GetProcAddress( ctx.hSetupLibrary, c_szSetupTermDefaultQueueCallback );
  62. pfSetupSetDirectoryId = (PFSetupSetDirectoryId) GetProcAddress( ctx.hSetupLibrary, c_szSetupSetDirectoryId );
  63. pfSetupGetLineText = (PFSetupGetLineText) GetProcAddress( ctx.hSetupLibrary, c_szSetupGetLineText );
  64. pfSetupGetLineByIndex = (PFSetupGetLineByIndex) GetProcAddress( ctx.hSetupLibrary, c_szSetupGetLineByIndex );
  65. pfSetupFindFirstLine = (PFSetupFindFirstLine) GetProcAddress( ctx.hSetupLibrary, c_szSetupFindFirstLine );
  66. pfSetupFindNextLine = (PFSetupFindNextLine) GetProcAddress( ctx.hSetupLibrary, c_szSetupFindNextLine );
  67. pfSetupOpenFileQueue = (PFSetupOpenFileQueue) GetProcAddress( ctx.hSetupLibrary, c_szSetupOpenFileQueue );
  68. pfSetupCloseFileQueue = (PFSetupCloseFileQueue) GetProcAddress( ctx.hSetupLibrary, c_szSetupCloseFileQueue );
  69. pfSetupQueueCopy = (PFSetupQueueCopy) GetProcAddress( ctx.hSetupLibrary, c_szSetupQueueCopy );
  70. pfSetupCommitFileQueue = (PFSetupCommitFileQueue) GetProcAddress( ctx.hSetupLibrary, c_szSetupCommitFileQueue );
  71. if (pfSetupDefaultQueueCallback == NULL
  72. || pfSetupInstallFromInfSection == NULL
  73. || pfSetupOpenInfFile == NULL
  74. || pfSetupCloseInfFile == NULL
  75. || pfSetupInitDefaultQueueCallbackEx == NULL
  76. || pfSetupTermDefaultQueueCallback == NULL
  77. || pfSetupSetDirectoryId == NULL
  78. || pfSetupGetLineText == NULL
  79. || pfSetupGetLineByIndex == NULL
  80. || pfSetupFindFirstLine == NULL
  81. || pfSetupFindNextLine == NULL
  82. || pfSetupOpenFileQueue == NULL
  83. || pfSetupCloseFileQueue == NULL
  84. || pfSetupQueueCopy == NULL
  85. || pfSetupCommitFileQueue == NULL
  86. || pfSetupGetStringField == NULL )
  87. {
  88. return FALSE;
  89. }
  90. return TRUE;
  91. }
  92. //***************************************************************************
  93. //* *
  94. //* NAME: InstallOnNT *
  95. //* *
  96. //* SYNOPSIS: This function will make all the calls to WinNT SUR's *
  97. //* SETUPAPI.DLL to do the installation on NT SUR. *
  98. //* *
  99. //* REQUIRES: pszSection: Section to install *
  100. //* pszSourceDir: Directory to CABs or expanded files *
  101. //* *
  102. //* RETURNS: *
  103. //* *
  104. //***************************************************************************
  105. HRESULT InstallOnNT( PSTR pszSection, PSTR pszSourceDir )
  106. {
  107. PVOID pContext = NULL;
  108. HRESULT hReturnCode = S_OK;
  109. HSPFILEQ hFileQueue = NULL;
  110. UINT uFlags;
  111. // Install Files
  112. // Setup Context data structure initialized for us for default UI provided by Setup API.
  113. pContext = pfSetupInitDefaultQueueCallbackEx( NULL, (ctx.wQuietMode) ?
  114. INVALID_HANDLE_VALUE : NULL,
  115. 0, 0, NULL );
  116. if ( pContext == NULL ) {
  117. hReturnCode = HRESULT_FROM_SETUPAPI(GetLastError());
  118. goto done;
  119. }
  120. if ( ! pfSetupInstallFromInfSection( NULL, ctx.hInf, pszSection, SPINST_FILES, NULL,
  121. pszSourceDir, SP_COPY_NEWER,
  122. MyFileQueueCallback2,
  123. pContext, NULL, NULL ) )
  124. {
  125. hReturnCode = HRESULT_FROM_SETUPAPI(GetLastError());
  126. pfSetupTermDefaultQueueCallback( pContext );
  127. goto done;
  128. }
  129. // Free Context Data structure
  130. pfSetupTermDefaultQueueCallback( pContext );
  131. uFlags = SPINST_REGISTRY | SPINST_INIFILES;
  132. if ( ctx.wOSVer >= _OSVER_WINNT50 )
  133. uFlags = uFlags | SPINST_PROFILEITEMS;
  134. // Install registry entries
  135. if ( ! pfSetupInstallFromInfSection( NULL, ctx.hInf, pszSection,
  136. uFlags,
  137. HKEY_LOCAL_MACHINE, NULL, 0, NULL,
  138. NULL, NULL, NULL ) )
  139. {
  140. hReturnCode = HRESULT_FROM_SETUPAPI(GetLastError());
  141. goto done;
  142. }
  143. done:
  144. return hReturnCode;
  145. }
  146. //***************************************************************************
  147. //* *
  148. //* NAME: MySetupOpenInfFile *
  149. //* *
  150. //* SYNOPSIS: This function will map to a function in setupapi.dll which *
  151. //* will open the INF file. *
  152. //* *
  153. //* REQUIRES: pszInfFilename: *
  154. //* *
  155. //* RETURNS: DWORD: Return value - OK means successfull. *
  156. //* *
  157. //***************************************************************************
  158. HRESULT MySetupOpenInfFile( PCSTR pszInfFilename )
  159. {
  160. UINT line;
  161. if ( ctx.hInf == NULL )
  162. {
  163. ctx.hInf = pfSetupOpenInfFile( pszInfFilename, NULL, INF_STYLE_WIN4, NULL );
  164. if ( ctx.hInf == NULL || ctx.hInf == INVALID_HANDLE_VALUE )
  165. {
  166. ctx.hInf = NULL;
  167. return HRESULT_FROM_SETUPAPI(GetLastError());
  168. }
  169. // process LayoutFile line of [version] section if any
  170. pfSetupOpenAppendInfFile( NULL, ctx.hInf, &line );
  171. }
  172. return S_OK;
  173. }
  174. //***************************************************************************
  175. //* *
  176. //* NAME: MySetupCloseInfFile *
  177. //* *
  178. //* SYNOPSIS: This function will map to an API function in setupapi.dll. *
  179. //* *
  180. //* REQUIRES: *
  181. //* *
  182. //* RETURNS: VOID *
  183. //* *
  184. //***************************************************************************
  185. VOID MySetupCloseInfFile( VOID )
  186. {
  187. if ( ctx.hInf )
  188. {
  189. pfSetupCloseInfFile( ctx.hInf );
  190. ctx.hInf = NULL;
  191. }
  192. }
  193. //***************************************************************************
  194. //* *
  195. //* NAME: MySetupSetDirectoryId *
  196. //* *
  197. //* SYNOPSIS: This function will map to a function in setupapi.dll to *
  198. //* set the directory ID's that are used in our INF. *
  199. //* *
  200. //* REQUIRES: dwDirID: Numerical value used to define the DirID *
  201. //* pszPath: DirID will point to this path. *
  202. //* *
  203. //* RETURNS: DWORD: Error value (OK if successfull) *
  204. //* *
  205. //***************************************************************************
  206. HRESULT MySetupSetDirectoryId( DWORD dwDirID, PSTR pszPath )
  207. {
  208. if ( ! pfSetupSetDirectoryId( ctx.hInf, dwDirID, pszPath ) ) {
  209. return HRESULT_FROM_SETUPAPI(GetLastError());
  210. }
  211. return S_OK;
  212. }
  213. //***************************************************************************
  214. //* *
  215. //* NAME: MySetupGetLineText *
  216. //* *
  217. //* SYNOPSIS: *
  218. //* *
  219. //* REQUIRES: *
  220. //* *
  221. //* RETURNS: *
  222. //* *
  223. //***************************************************************************
  224. HRESULT MySetupGetLineText( PCSTR pszSection, PCSTR pszKey, PSTR pszReturnBuffer,
  225. DWORD dwReturnBufferSize, PDWORD pdwRequiredSize )
  226. {
  227. if ( ! pfSetupGetLineText( NULL, ctx.hInf, pszSection, pszKey,
  228. pszReturnBuffer, dwReturnBufferSize,
  229. pdwRequiredSize ) )
  230. {
  231. return HRESULT_FROM_SETUPAPI(GetLastError());
  232. }
  233. return S_OK;
  234. }
  235. //***************************************************************************
  236. //* *
  237. //* NAME: MySetupGetLineByIndex *
  238. //* *
  239. //* SYNOPSIS: *
  240. //* *
  241. //* REQUIRES: *
  242. //* *
  243. //* RETURNS: *
  244. //* *
  245. //***************************************************************************
  246. HRESULT MySetupGetLineByIndex( PCSTR c_pszSection, DWORD dwIndex,
  247. PSTR pszBuffer, DWORD dwBufferSize,
  248. PDWORD pdwRequiredSize )
  249. {
  250. HRESULT hReturnCode = S_OK;
  251. INFCONTEXT InfContext;
  252. DWORD i = 0;
  253. if ( ! pfSetupFindFirstLine( ctx.hInf, c_pszSection, NULL, &InfContext ) ) {
  254. hReturnCode = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
  255. goto done;
  256. }
  257. for ( i = 0; i < dwIndex; i += 1 ) {
  258. if ( !pfSetupFindNextLine( &InfContext, &InfContext ) ) {
  259. hReturnCode = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
  260. goto done;
  261. }
  262. }
  263. #if 0
  264. if ( ! pfSetupGetLineByIndex( ctx.hInf, c_pszSection, dwIndex, &InfContext ) )
  265. {
  266. hReturnCode = HRESULT_FROM_SETUPAPI(GetLastError());
  267. goto done;
  268. }
  269. #endif
  270. if ( ! pfSetupGetLineText( &InfContext, NULL, NULL, NULL,
  271. pszBuffer, dwBufferSize, pdwRequiredSize ) )
  272. {
  273. hReturnCode = HRESULT_FROM_SETUPAPI(GetLastError());
  274. goto done;
  275. }
  276. done:
  277. return hReturnCode;
  278. }
  279. //***************************************************************************
  280. //* *
  281. //* NAME: MySetupGetStringField *
  282. //* *
  283. //* SYNOPSIS: *
  284. //* *
  285. //* REQUIRES: *
  286. //* *
  287. //* RETURNS: *
  288. //* *
  289. //***************************************************************************
  290. HRESULT MySetupGetStringField( PCSTR c_pszSection, DWORD dwLineIndex, DWORD dwFieldIndex,
  291. PSTR pszBuffer, DWORD dwBufferSize, PDWORD pdwRequiredSize )
  292. {
  293. HRESULT hReturnCode = S_OK;
  294. INFCONTEXT InfContext;
  295. DWORD i = 0;
  296. if ( !pfSetupFindFirstLine( ctx.hInf, c_pszSection, NULL, &InfContext ) ) {
  297. hReturnCode = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
  298. goto done;
  299. }
  300. for ( i = 0; i < dwLineIndex; i += 1 )
  301. {
  302. if ( !pfSetupFindNextLine( &InfContext, &InfContext ) )
  303. {
  304. hReturnCode = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
  305. goto done;
  306. }
  307. }
  308. if ( !pfSetupGetStringField( &InfContext, dwFieldIndex,
  309. pszBuffer, dwBufferSize, pdwRequiredSize ) )
  310. {
  311. hReturnCode = HRESULT_FROM_SETUPAPI(GetLastError());
  312. goto done;
  313. }
  314. done:
  315. return hReturnCode;
  316. }
  317. HRESULT WINAPI AdvInstallFile(HWND hwnd, LPCSTR lpszSourceDir, LPCSTR lpszSourceFile,
  318. LPCSTR lpszDestDir, LPCSTR lpszDestFile, DWORD dwFlags, DWORD dwReserved)
  319. {
  320. HRESULT hr = E_FAIL;
  321. HSPFILEQ FileQueue;
  322. char szSrcDrv[MAX_PATH];
  323. LPCSTR lpSrcPath;
  324. LPVOID lpContext;
  325. DWORD dwCopyFlags;
  326. DWORD dwRebootCheck;
  327. if ( (lpszSourceDir == NULL) || (*lpszSourceDir == '\0') ||
  328. (lpszSourceFile == NULL) || (*lpszSourceFile == '\0') ||
  329. (lstrlen(lpszSourceDir) < 3) ||
  330. (lpszDestDir == NULL) )
  331. return E_INVALIDARG;
  332. if (!SaveGlobalContext())
  333. return hr;
  334. ctx.hWnd = hwnd;
  335. if ( !CheckOSVersion() )
  336. {
  337. RestoreGlobalContext();
  338. return HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION);
  339. }
  340. dwRebootCheck = InternalNeedRebootInit( ctx.wOSVer );
  341. // LoadLibrary for setupapi.dll
  342. ctx.hSetupLibrary = MyLoadLibrary( SETUPAPIDLL );
  343. if ( ctx.hSetupLibrary == NULL )
  344. {
  345. ErrorMsg1Param( NULL, IDS_ERR_LOAD_DLL, SETUPAPIDLL );
  346. hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND);
  347. goto Cleanup;
  348. }
  349. if ( ! LoadSetupAPIFuncs() )
  350. {
  351. ErrorMsg( NULL, IDS_ERR_GET_PROC_ADDR );
  352. hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
  353. goto Cleanup;
  354. }
  355. // SetupOpenFileQueue
  356. FileQueue = pfSetupOpenFileQueue();
  357. if (FileQueue == INVALID_HANDLE_VALUE)
  358. {
  359. ErrorMsg1Param( NULL, IDS_ERR_LOAD_DLL, c_szSetupOpenFileQueue );
  360. hr = HRESULT_FROM_SETUPAPI(GetLastError());
  361. goto Cleanup;
  362. }
  363. lstrcpy(szSrcDrv, lpszSourceDir);
  364. MakeRootDir(szSrcDrv);
  365. lpSrcPath = lpszSourceDir + lstrlen(szSrcDrv); // This will point to the first subdir.
  366. dwCopyFlags = SP_COPY_SOURCE_ABSOLUTE |
  367. SP_COPY_IN_USE_NEEDS_REBOOT|
  368. SP_COPY_NEWER |
  369. SP_COPY_LANGUAGEAWARE;
  370. if (dwFlags & AIF_FORCE_FILE_IN_USE)
  371. dwCopyFlags |= SP_COPY_FORCE_IN_USE;
  372. if (dwFlags & AIF_NOVERSIONCHECK)
  373. dwCopyFlags &= ~SP_COPY_NEWER;
  374. if (dwFlags & AIF_NOLANGUAGECHECK)
  375. dwCopyFlags &= ~SP_COPY_LANGUAGEAWARE;
  376. if (dwFlags & AIF_NO_VERSION_DIALOG)
  377. dwCopyFlags |= SP_COPY_FORCE_NEWER;
  378. if (dwFlags & AIF_REPLACEONLY)
  379. dwCopyFlags |= SP_COPY_REPLACEONLY;
  380. if (dwFlags & AIF_NOOVERWRITE)
  381. dwCopyFlags |= SP_COPY_NOOVERWRITE;
  382. if (dwFlags & AIF_NOSKIP)
  383. dwCopyFlags |= SP_COPY_NOSKIP;
  384. if (dwFlags & AIF_WARNIFSKIP)
  385. dwCopyFlags |= SP_COPY_WARNIFSKIP;
  386. if (pfSetupQueueCopy(FileQueue,
  387. szSrcDrv,
  388. lpSrcPath,
  389. lpszSourceFile,
  390. NULL,
  391. NULL,
  392. lpszDestDir,
  393. lpszDestFile,
  394. dwCopyFlags))
  395. {
  396. lpContext = pfSetupInitDefaultQueueCallbackEx(hwnd, INVALID_HANDLE_VALUE, 0, 0, NULL);
  397. hr = S_OK;
  398. //
  399. // SetupCommitFileQueue
  400. if (!pfSetupCommitFileQueue( hwnd, FileQueue,
  401. (dwFlags & AIF_QUIET)?AIFQuietSetupQueueCallback:AIFSetupQueueCallback,
  402. lpContext))
  403. {
  404. hr = HRESULT_FROM_SETUPAPI(GetLastError());
  405. }
  406. pfSetupTermDefaultQueueCallback(lpContext);
  407. }
  408. else
  409. hr = HRESULT_FROM_SETUPAPI(GetLastError());
  410. // SetupCloseFileQueue
  411. pfSetupCloseFileQueue(FileQueue);
  412. if ( SUCCEEDED(hr) &&
  413. InternalNeedReboot( dwRebootCheck, ctx.wOSVer ) )
  414. {
  415. hr = ERROR_SUCCESS_REBOOT_REQUIRED;
  416. }
  417. Cleanup:
  418. RestoreGlobalContext();
  419. return hr;
  420. }
  421. // This callback will display error messages, but will not show any progress dialog
  422. UINT WINAPI AIFSetupQueueCallback(PVOID Context, // context used by the default callback routine
  423. UINT Notification, // queue notification
  424. UINT_PTR Param1, // additional notification information
  425. UINT_PTR Param2 // additional notification information
  426. )
  427. {
  428. switch (Notification)
  429. {
  430. case SPFILENOTIFY_STARTQUEUE:
  431. case SPFILENOTIFY_ENDQUEUE:
  432. case SPFILENOTIFY_STARTSUBQUEUE:
  433. case SPFILENOTIFY_ENDSUBQUEUE:
  434. case SPFILENOTIFY_STARTRENAME:
  435. case SPFILENOTIFY_ENDRENAME:
  436. case SPFILENOTIFY_STARTDELETE:
  437. case SPFILENOTIFY_ENDDELETE:
  438. case SPFILENOTIFY_STARTCOPY:
  439. case SPFILENOTIFY_ENDCOPY:
  440. return FILEOP_DOIT;
  441. default:
  442. return (pfSetupDefaultQueueCallback(Context, Notification, Param1, Param2));
  443. }
  444. }
  445. // This callback will not display any dialog
  446. UINT WINAPI AIFQuietSetupQueueCallback(PVOID Context, // context used by the default callback routine
  447. UINT Notification, // queue notification
  448. UINT_PTR Param1, // additional notification information
  449. UINT_PTR Param2 // additional notification information
  450. )
  451. {
  452. return FILEOP_DOIT;
  453. }
  454. UINT WINAPI MyFileQueueCallback2( PVOID Context,UINT Notification,UINT_PTR parm1,UINT_PTR parm2 )
  455. {
  456. switch(Notification)
  457. {
  458. case SPFILENOTIFY_NEEDMEDIA:
  459. {
  460. CHAR szDrv[5];
  461. PSOURCE_MEDIA psrcMed;
  462. psrcMed = (PSOURCE_MEDIA)parm1;
  463. if ( lstrlen( psrcMed->SourcePath ) > 3 )
  464. {
  465. lstrcpyn( szDrv, psrcMed->SourcePath, 4 );
  466. if ( (szDrv[1] == ':') && (GetDriveType( szDrv ) == DRIVE_REMOVABLE) )
  467. {
  468. CHAR szFile[MAX_PATH];
  469. lstrcpy( szFile, psrcMed->SourcePath );
  470. if ( psrcMed->Tagfile && *psrcMed->Tagfile )
  471. AddPath( szFile, psrcMed->Tagfile );
  472. else
  473. AddPath( szFile, psrcMed->SourceFile );
  474. if ( FileExists( szFile ) )
  475. {
  476. lstrcpy( (PSTR)parm2, psrcMed->SourcePath );
  477. return ( FILEOP_NEWPATH );
  478. }
  479. }
  480. }
  481. }
  482. default:
  483. return ( pfSetupDefaultQueueCallback( Context, Notification, parm1, parm2 ) );
  484. }
  485. }
  486. void MakeRootDir(LPSTR pszPath)
  487. {
  488. LPSTR pTmp;
  489. if (pszPath[1] == ':')
  490. pszPath[3] = '\0';
  491. else if ((pszPath[0] == '\\') && (pszPath[1]=='\\'))
  492. {
  493. pTmp = &pszPath[2];
  494. // Find the sever share separation
  495. while ((*pTmp) && (*pTmp != '\\'))
  496. pTmp = CharNext(pTmp);
  497. if (*pTmp)
  498. {
  499. pTmp = CharNext(pTmp);
  500. // Find the end of the share
  501. while ((*pTmp) && (*pTmp != '\\'))
  502. pTmp = CharNext(pTmp);
  503. if (*pTmp == '\\')
  504. {
  505. pTmp = CharNext(pTmp);
  506. *pTmp ='\0';
  507. }
  508. }
  509. }
  510. }