home *** CD-ROM | disk | FTP | other *** search
/ Netrunner 2004 October / NETRUNNER0410.ISO / regular / ActivePerl-5.8.4.810-MSWin32-x86.msi / _efb1b312a50a4c430be79d686e794252 < prev    next >
Text File  |  2004-06-01  |  18KB  |  692 lines

  1. /* vdir.h
  2.  *
  3.  * (c) 1999 Microsoft Corporation. All rights reserved. 
  4.  * Portions (c) 1999 ActiveState Tool Corp, http://www.ActiveState.com/
  5.  *
  6.  *    You may distribute under the terms of either the GNU General Public
  7.  *    License or the Artistic License, as specified in the README file.
  8.  */
  9.  
  10. #ifndef ___VDir_H___
  11. #define ___VDir_H___
  12.  
  13. /*
  14.  * Allow one slot for each possible drive letter
  15.  * and one additional slot for a UNC name
  16.  */
  17. const int driveCount = ('Z'-'A')+1+1;
  18.  
  19. class VDir
  20. {
  21. public:
  22.     VDir(int bManageDir = 1);
  23.     ~VDir() {};
  24.  
  25.     void Init(VDir* pDir, VMem *pMem);
  26.     void SetDefaultA(char const *pDefault);
  27.     void SetDefaultW(WCHAR const *pDefault);
  28.     char* MapPathA(const char *pInName);
  29.     WCHAR* MapPathW(const WCHAR *pInName);
  30.     int SetCurrentDirectoryA(char *lpBuffer);
  31.     int SetCurrentDirectoryW(WCHAR *lpBuffer);
  32.     inline int GetDefault(void) { return nDefault; };
  33.  
  34.     inline char* GetCurrentDirectoryA(int dwBufSize, char *lpBuffer)
  35.     {
  36.     char* ptr = dirTableA[nDefault];
  37.     while (dwBufSize--)
  38.     {
  39.         if ((*lpBuffer++ = *ptr++) == '\0')
  40.         break;
  41.     }
  42.     return lpBuffer;
  43.     };
  44.     inline WCHAR* GetCurrentDirectoryW(int dwBufSize, WCHAR *lpBuffer)
  45.     {
  46.     WCHAR* ptr = dirTableW[nDefault];
  47.     while (dwBufSize--)
  48.     {
  49.         if ((*lpBuffer++ = *ptr++) == '\0')
  50.         break;
  51.     }
  52.     return lpBuffer;
  53.     };
  54.  
  55.  
  56.     DWORD CalculateEnvironmentSpace(void);
  57.     LPSTR BuildEnvironmentSpace(LPSTR lpStr);
  58.  
  59. protected:
  60.     int SetDirA(char const *pPath, int index);
  61.     void FromEnvA(char *pEnv, int index);
  62.     inline const char *GetDefaultDirA(void)
  63.     {
  64.     return dirTableA[nDefault];
  65.     };
  66.  
  67.     inline void SetDefaultDirA(char const *pPath, int index)
  68.     {
  69.     SetDirA(pPath, index);
  70.     nDefault = index;
  71.     };
  72.     int SetDirW(WCHAR const *pPath, int index);
  73.     inline const WCHAR *GetDefaultDirW(void)
  74.     {
  75.     return dirTableW[nDefault];
  76.     };
  77.  
  78.     inline void SetDefaultDirW(WCHAR const *pPath, int index)
  79.     {
  80.     SetDirW(pPath, index);
  81.     nDefault = index;
  82.     };
  83.     inline const char *GetDirA(int index)
  84.     {
  85.     char *ptr = dirTableA[index];
  86.     if (!ptr) {
  87.         /* simulate the existance of this drive */
  88.         ptr = szLocalBufferA;
  89.         ptr[0] = 'A' + index;
  90.         ptr[1] = ':';
  91.         ptr[2] = '\\';
  92.         ptr[3] = 0;
  93.     }
  94.     return ptr;
  95.     };
  96.     inline const WCHAR *GetDirW(int index)
  97.     {
  98.     WCHAR *ptr = dirTableW[index];
  99.     if (!ptr) {
  100.         /* simulate the existance of this drive */
  101.         ptr = szLocalBufferW;
  102.         ptr[0] = 'A' + index;
  103.         ptr[1] = ':';
  104.         ptr[2] = '\\';
  105.         ptr[3] = 0;
  106.     }
  107.     return ptr;
  108.     };
  109.  
  110.     inline int DriveIndex(char chr)
  111.     {
  112.     if (chr == '\\' || chr == '/')
  113.         return ('Z'-'A')+1;
  114.     return (chr | 0x20)-'a';
  115.     };
  116.  
  117.     VMem *pMem;
  118.     int nDefault, bManageDirectory;
  119.     char *dirTableA[driveCount];
  120.     char szLocalBufferA[MAX_PATH+1];
  121.     WCHAR *dirTableW[driveCount];
  122.     WCHAR szLocalBufferW[MAX_PATH+1];
  123. };
  124.  
  125.  
  126. VDir::VDir(int bManageDir /* = 1 */)
  127. {
  128.     nDefault = 0;
  129.     bManageDirectory = bManageDir;
  130.     memset(dirTableA, 0, sizeof(dirTableA));
  131.     memset(dirTableW, 0, sizeof(dirTableW));
  132. }
  133.  
  134. void VDir::Init(VDir* pDir, VMem *p)
  135. {
  136.     int index;
  137.     DWORD driveBits;
  138.     int nSave;
  139.     char szBuffer[MAX_PATH*driveCount];
  140.  
  141.     pMem = p;
  142.     if (pDir) {
  143.     for (index = 0; index < driveCount; ++index) {
  144.         SetDirW(pDir->GetDirW(index), index);
  145.     }
  146.     nDefault = pDir->GetDefault();
  147.     }
  148.     else {
  149.     nSave = bManageDirectory;
  150.     bManageDirectory = 0;
  151.     driveBits = GetLogicalDrives();
  152.     if (GetLogicalDriveStrings(sizeof(szBuffer), szBuffer)) {
  153.         char* pEnv = GetEnvironmentStrings();
  154.         char* ptr = szBuffer;
  155.         for (index = 0; index < driveCount; ++index) {
  156.         if (driveBits & (1<<index)) {
  157.             ptr += SetDirA(ptr, index) + 1;
  158.             FromEnvA(pEnv, index);
  159.         }
  160.         }
  161.         FreeEnvironmentStrings(pEnv);
  162.     }
  163.     SetDefaultA(".");
  164.     bManageDirectory = nSave;
  165.     }
  166. }
  167.  
  168. int VDir::SetDirA(char const *pPath, int index)
  169. {
  170.     char chr, *ptr;
  171.     int length = 0;
  172.     WCHAR wBuffer[MAX_PATH+1];
  173.     if (index < driveCount && pPath != NULL) {
  174.     length = strlen(pPath);
  175.     pMem->Free(dirTableA[index]);
  176.     ptr = dirTableA[index] = (char*)pMem->Malloc(length+2);
  177.     if (ptr != NULL) {
  178.         strcpy(ptr, pPath);
  179.         ptr += length-1;
  180.         chr = *ptr++;
  181.         if (chr != '\\' && chr != '/') {
  182.         *ptr++ = '\\';
  183.         *ptr = '\0';
  184.         }
  185.         MultiByteToWideChar(CP_ACP, 0, dirTableA[index], -1,
  186.             wBuffer, (sizeof(wBuffer)/sizeof(WCHAR)));
  187.         length = wcslen(wBuffer);
  188.         pMem->Free(dirTableW[index]);
  189.         dirTableW[index] = (WCHAR*)pMem->Malloc((length+1)*2);
  190.         if (dirTableW[index] != NULL) {
  191.         wcscpy(dirTableW[index], wBuffer);
  192.         }
  193.     }
  194.     }
  195.  
  196.     if(bManageDirectory)
  197.     ::SetCurrentDirectoryA(pPath);
  198.  
  199.     return length;
  200. }
  201.  
  202. void VDir::FromEnvA(char *pEnv, int index)
  203. {   /* gets the directory for index from the environment variable. */
  204.     while (*pEnv != '\0') {
  205.     if ((pEnv[0] == '=') && (DriveIndex(pEnv[1]) == index)) {
  206.         SetDirA(&pEnv[4], index);
  207.         break;
  208.     }
  209.     else
  210.         pEnv += strlen(pEnv)+1;
  211.     }
  212. }
  213.  
  214. void VDir::SetDefaultA(char const *pDefault)
  215. {
  216.     char szBuffer[MAX_PATH+1];
  217.     char *pPtr;
  218.  
  219.     if (GetFullPathNameA(pDefault, sizeof(szBuffer), szBuffer, &pPtr)) {
  220.         if (*pDefault != '.' && pPtr != NULL)
  221.         *pPtr = '\0';
  222.  
  223.     SetDefaultDirA(szBuffer, DriveIndex(szBuffer[0]));
  224.     }
  225. }
  226.  
  227. int VDir::SetDirW(WCHAR const *pPath, int index)
  228. {
  229.     WCHAR chr, *ptr;
  230.     char szBuffer[MAX_PATH+1];
  231.     int length = 0;
  232.     if (index < driveCount && pPath != NULL) {
  233.     length = wcslen(pPath);
  234.     pMem->Free(dirTableW[index]);
  235.     ptr = dirTableW[index] = (WCHAR*)pMem->Malloc((length+2)*2);
  236.     if (ptr != NULL) {
  237.         wcscpy(ptr, pPath);
  238.         ptr += length-1;
  239.         chr = *ptr++;
  240.         if (chr != '\\' && chr != '/') {
  241.         *ptr++ = '\\';
  242.         *ptr = '\0';
  243.         }
  244.         WideCharToMultiByte(CP_ACP, 0, dirTableW[index], -1, szBuffer, sizeof(szBuffer), NULL, NULL);
  245.         length = strlen(szBuffer);
  246.         pMem->Free(dirTableA[index]);
  247.         dirTableA[index] = (char*)pMem->Malloc(length+1);
  248.         if (dirTableA[index] != NULL) {
  249.         strcpy(dirTableA[index], szBuffer);
  250.         }
  251.     }
  252.     }
  253.  
  254.     if(bManageDirectory)
  255.     ::SetCurrentDirectoryW(pPath);
  256.  
  257.     return length;
  258. }
  259.  
  260. void VDir::SetDefaultW(WCHAR const *pDefault)
  261. {
  262.     WCHAR szBuffer[MAX_PATH+1];
  263.     WCHAR *pPtr;
  264.  
  265.     if (GetFullPathNameW(pDefault, (sizeof(szBuffer)/sizeof(WCHAR)), szBuffer, &pPtr)) {
  266.         if (*pDefault != '.' && pPtr != NULL)
  267.         *pPtr = '\0';
  268.  
  269.     SetDefaultDirW(szBuffer, DriveIndex((char)szBuffer[0]));
  270.     }
  271. }
  272.  
  273. inline BOOL IsPathSep(char ch)
  274. {
  275.     return (ch == '\\' || ch == '/');
  276. }
  277.  
  278. inline void DoGetFullPathNameA(char* lpBuffer, DWORD dwSize, char* Dest)
  279. {
  280.     char *pPtr;
  281.  
  282.     /*
  283.      * On WinNT GetFullPathName does not fail, (or at least always
  284.      * succeeds when the drive is valid) WinNT does set *Dest to Nullch
  285.      * On Win98 GetFullPathName will set last error if it fails, but
  286.      * does not touch *Dest
  287.      */
  288.     *Dest = '\0';
  289.     GetFullPathNameA(lpBuffer, dwSize, Dest, &pPtr);
  290. }
  291.  
  292. inline bool IsSpecialFileName(const char* pName)
  293. {
  294.     /* specical file names are devices that the system can open
  295.      * these include AUX, CON, NUL, PRN, COMx, LPTx, CLOCK$, CONIN$, CONOUT$
  296.      * (x is a single digit, and names are case-insensitive)
  297.      */
  298.     char ch = (pName[0] & ~0x20);
  299.     switch (ch)
  300.     {
  301.     case 'A': /* AUX */
  302.         if (((pName[1] & ~0x20) == 'U')
  303.         && ((pName[2] & ~0x20) == 'X')
  304.         && !pName[3])
  305.             return true;
  306.         break;
  307.     case 'C': /* CLOCK$, COMx,  CON, CONIN$ CONOUT$ */
  308.         ch = (pName[1] & ~0x20);
  309.         switch (ch)
  310.         {
  311.         case 'L': /* CLOCK$ */
  312.             if (((pName[2] & ~0x20) == 'O')
  313.             && ((pName[3] & ~0x20) == 'C')
  314.             && ((pName[4] & ~0x20) == 'K')
  315.             && (pName[5] == '$')
  316.             && !pName[6])
  317.                 return true;
  318.             break;
  319.         case 'O': /* COMx,  CON, CONIN$ CONOUT$ */
  320.             if ((pName[2] & ~0x20) == 'M') {
  321.             if ((pName[3] >= '1') && (pName[3] <= '9')
  322.                 && !pName[4])
  323.                 return true;
  324.             }
  325.             else if ((pName[2] & ~0x20) == 'N') {
  326.             if (!pName[3])
  327.                 return true;
  328.             else if ((pName[3] & ~0x20) == 'I') {
  329.                 if (((pName[4] & ~0x20) == 'N')
  330.                 && (pName[5] == '$')
  331.                 && !pName[6])
  332.                 return true;
  333.             }
  334.             else if ((pName[3] & ~0x20) == 'O') {
  335.                 if (((pName[4] & ~0x20) == 'U')
  336.                 && ((pName[5] & ~0x20) == 'T')
  337.                 && (pName[6] == '$')
  338.                 && !pName[7])
  339.                 return true;
  340.             }
  341.             }
  342.             break;
  343.         }
  344.         break;
  345.     case 'L': /* LPTx */
  346.         if (((pName[1] & ~0x20) == 'U')
  347.         && ((pName[2] & ~0x20) == 'X')
  348.         && (pName[3] >= '1') && (pName[3] <= '9')
  349.         && !pName[4])
  350.             return true;
  351.         break;
  352.     case 'N': /* NUL */
  353.         if (((pName[1] & ~0x20) == 'U')
  354.         && ((pName[2] & ~0x20) == 'L')
  355.         && !pName[3])
  356.             return true;
  357.         break;
  358.     case 'P': /* PRN */
  359.         if (((pName[1] & ~0x20) == 'R')
  360.         && ((pName[2] & ~0x20) == 'N')
  361.         && !pName[3])
  362.             return true;
  363.         break;
  364.     }
  365.     return false;
  366. }
  367.  
  368. char *VDir::MapPathA(const char *pInName)
  369. {   /*
  370.      * possiblities -- relative path or absolute path with or without drive letter
  371.      * OR UNC name
  372.      */
  373.     char szBuffer[(MAX_PATH+1)*2];
  374.     char szlBuf[MAX_PATH+1];
  375.     int length = strlen(pInName);
  376.  
  377.     if (!length)
  378.     return (char*)pInName;
  379.  
  380.     if (length > MAX_PATH) {
  381.     strncpy(szlBuf, pInName, MAX_PATH);
  382.     if (IsPathSep(pInName[0]) && !IsPathSep(pInName[1])) {   
  383.         /* absolute path - reduce length by 2 for drive specifier */
  384.         szlBuf[MAX_PATH-2] = '\0';
  385.     }
  386.     else
  387.         szlBuf[MAX_PATH] = '\0';
  388.     pInName = szlBuf;
  389.     }
  390.     /* strlen(pInName) is now <= MAX_PATH */
  391.  
  392.     if (pInName[1] == ':') {
  393.     /* has drive letter */
  394.     if (IsPathSep(pInName[2])) {
  395.         /* absolute with drive letter */
  396.         DoGetFullPathNameA((char*)pInName, sizeof(szLocalBufferA), szLocalBufferA);
  397.     }
  398.     else {
  399.         /* relative path with drive letter */
  400.         strcpy(szBuffer, GetDirA(DriveIndex(*pInName)));
  401.         strcat(szBuffer, &pInName[2]);
  402.         if(strlen(szBuffer) > MAX_PATH)
  403.         szBuffer[MAX_PATH] = '\0';
  404.  
  405.         DoGetFullPathNameA(szBuffer, sizeof(szLocalBufferA), szLocalBufferA);
  406.     }
  407.     }
  408.     else {
  409.     /* no drive letter */
  410.     if (IsPathSep(pInName[1]) && IsPathSep(pInName[0])) {
  411.         /* UNC name */
  412.         DoGetFullPathNameA((char*)pInName, sizeof(szLocalBufferA), szLocalBufferA);
  413.     }
  414.     else {
  415.         strcpy(szBuffer, GetDefaultDirA());
  416.         if (IsPathSep(pInName[0])) {
  417.         /* absolute path */
  418.         strcpy(&szBuffer[2], pInName);
  419.         DoGetFullPathNameA(szBuffer, sizeof(szLocalBufferA), szLocalBufferA);
  420.         }
  421.         else {
  422.         /* relative path */
  423.         if (IsSpecialFileName(pInName)) {
  424.             return (char*)pInName;
  425.         }
  426.         else {
  427.             strcat(szBuffer, pInName);
  428.             if (strlen(szBuffer) > MAX_PATH)
  429.             szBuffer[MAX_PATH] = '\0';
  430.  
  431.             DoGetFullPathNameA(szBuffer, sizeof(szLocalBufferA), szLocalBufferA);
  432.         }
  433.         }
  434.     }
  435.     }
  436.  
  437.     return szLocalBufferA;
  438. }
  439.  
  440. int VDir::SetCurrentDirectoryA(char *lpBuffer)
  441. {
  442.     char *pPtr;
  443.     int length, nRet = -1;
  444.  
  445.     pPtr = MapPathA(lpBuffer);
  446.     length = strlen(pPtr);
  447.     if(length > 3 && IsPathSep(pPtr[length-1])) {
  448.     /* don't remove the trailing slash from 'x:\'  */
  449.     pPtr[length-1] = '\0';
  450.     }
  451.  
  452.     DWORD r = GetFileAttributesA(pPtr);
  453.     if ((r != 0xffffffff) && (r & FILE_ATTRIBUTE_DIRECTORY))
  454.     {
  455.     char szBuffer[(MAX_PATH+1)*2];
  456.     DoGetFullPathNameA(pPtr, sizeof(szBuffer), szBuffer);
  457.     SetDefaultDirA(szBuffer, DriveIndex(szBuffer[0]));
  458.     nRet = 0;
  459.     }
  460.  
  461.     return nRet;
  462. }
  463.  
  464. DWORD VDir::CalculateEnvironmentSpace(void)
  465. {   /* the current directory environment strings are stored as '=D:=d:\path' */
  466.     int index;
  467.     DWORD dwSize = 0;
  468.     for (index = 0; index < driveCount; ++index) {
  469.     if (dirTableA[index] != NULL) {
  470.         dwSize += strlen(dirTableA[index]) + 5;  /* add 1 for trailing NULL and 4 for '=D:=' */
  471.     }
  472.     }
  473.     return dwSize;
  474. }
  475.  
  476. LPSTR VDir::BuildEnvironmentSpace(LPSTR lpStr)
  477. {   /* store the current directory environment strings as '=D:=d:\path' */
  478.     int index, length;
  479.     LPSTR lpDirStr;
  480.     for (index = 0; index < driveCount; ++index) {
  481.     lpDirStr = dirTableA[index];
  482.     if (lpDirStr != NULL) {
  483.         lpStr[0] = '=';
  484.         lpStr[1] = lpDirStr[0];
  485.         lpStr[2] = '\0';
  486.         CharUpper(&lpStr[1]);
  487.         lpStr[2] = ':';
  488.         lpStr[3] = '=';
  489.         strcpy(&lpStr[4], lpDirStr);
  490.         length = strlen(lpDirStr);
  491.         lpStr += length + 5; /* add 1 for trailing NULL and 4 for '=D:=' */
  492.         if (length > 3 && IsPathSep(lpStr[-2])) {
  493.         lpStr[-2] = '\0';   /* remove the trailing path separator */
  494.         --lpStr;
  495.         }
  496.     }
  497.     }
  498.     return lpStr;
  499. }
  500.  
  501. inline BOOL IsPathSep(WCHAR ch)
  502. {
  503.     return (ch == '\\' || ch == '/');
  504. }
  505.  
  506. inline void DoGetFullPathNameW(WCHAR* lpBuffer, DWORD dwSize, WCHAR* Dest)
  507. {
  508.     WCHAR *pPtr;
  509.  
  510.     /*
  511.      * On WinNT GetFullPathName does not fail, (or at least always
  512.      * succeeds when the drive is valid) WinNT does set *Dest to Nullch
  513.      * On Win98 GetFullPathName will set last error if it fails, but
  514.      * does not touch *Dest
  515.      */
  516.     *Dest = '\0';
  517.     GetFullPathNameW(lpBuffer, dwSize, Dest, &pPtr);
  518. }
  519.  
  520. inline bool IsSpecialFileName(const WCHAR* pName)
  521. {
  522.     /* specical file names are devices that the system can open
  523.      * these include AUX, CON, NUL, PRN, COMx, LPTx, CLOCK$, CONIN$, CONOUT$
  524.      * (x is a single digit, and names are case-insensitive)
  525.      */
  526.     WCHAR ch = (pName[0] & ~0x20);
  527.     switch (ch)
  528.     {
  529.     case 'A': /* AUX */
  530.         if (((pName[1] & ~0x20) == 'U')
  531.         && ((pName[2] & ~0x20) == 'X')
  532.         && !pName[3])
  533.             return true;
  534.         break;
  535.     case 'C': /* CLOCK$, COMx,  CON, CONIN$ CONOUT$ */
  536.         ch = (pName[1] & ~0x20);
  537.         switch (ch)
  538.         {
  539.         case 'L': /* CLOCK$ */
  540.             if (((pName[2] & ~0x20) == 'O')
  541.             && ((pName[3] & ~0x20) == 'C')
  542.             && ((pName[4] & ~0x20) == 'K')
  543.             && (pName[5] == '$')
  544.             && !pName[6])
  545.                 return true;
  546.             break;
  547.         case 'O': /* COMx,  CON, CONIN$ CONOUT$ */
  548.             if ((pName[2] & ~0x20) == 'M') {
  549.             if ((pName[3] >= '1') && (pName[3] <= '9')
  550.                 && !pName[4])
  551.                 return true;
  552.             }
  553.             else if ((pName[2] & ~0x20) == 'N') {
  554.             if (!pName[3])
  555.                 return true;
  556.             else if ((pName[3] & ~0x20) == 'I') {
  557.                 if (((pName[4] & ~0x20) == 'N')
  558.                 && (pName[5] == '$')
  559.                 && !pName[6])
  560.                 return true;
  561.             }
  562.             else if ((pName[3] & ~0x20) == 'O') {
  563.                 if (((pName[4] & ~0x20) == 'U')
  564.                 && ((pName[5] & ~0x20) == 'T')
  565.                 && (pName[6] == '$')
  566.                 && !pName[7])
  567.                 return true;
  568.             }
  569.             }
  570.             break;
  571.         }
  572.         break;
  573.     case 'L': /* LPTx */
  574.         if (((pName[1] & ~0x20) == 'U')
  575.         && ((pName[2] & ~0x20) == 'X')
  576.         && (pName[3] >= '1') && (pName[3] <= '9')
  577.         && !pName[4])
  578.             return true;
  579.         break;
  580.     case 'N': /* NUL */
  581.         if (((pName[1] & ~0x20) == 'U')
  582.         && ((pName[2] & ~0x20) == 'L')
  583.         && !pName[3])
  584.             return true;
  585.         break;
  586.     case 'P': /* PRN */
  587.         if (((pName[1] & ~0x20) == 'R')
  588.         && ((pName[2] & ~0x20) == 'N')
  589.         && !pName[3])
  590.             return true;
  591.         break;
  592.     }
  593.     return false;
  594. }
  595.  
  596. WCHAR* VDir::MapPathW(const WCHAR *pInName)
  597. {   /*
  598.      * possiblities -- relative path or absolute path with or without drive letter
  599.      * OR UNC name
  600.      */
  601.     WCHAR szBuffer[(MAX_PATH+1)*2];
  602.     WCHAR szlBuf[MAX_PATH+1];
  603.     int length = wcslen(pInName);
  604.  
  605.     if (!length)
  606.     return (WCHAR*)pInName;
  607.  
  608.     if (length > MAX_PATH) {
  609.     wcsncpy(szlBuf, pInName, MAX_PATH);
  610.     if (IsPathSep(pInName[0]) && !IsPathSep(pInName[1])) {   
  611.         /* absolute path - reduce length by 2 for drive specifier */
  612.         szlBuf[MAX_PATH-2] = '\0';
  613.     }
  614.     else
  615.         szlBuf[MAX_PATH] = '\0';
  616.     pInName = szlBuf;
  617.     }
  618.     /* strlen(pInName) is now <= MAX_PATH */
  619.  
  620.     if (pInName[1] == ':') {
  621.     /* has drive letter */
  622.     if (IsPathSep(pInName[2])) {
  623.         /* absolute with drive letter */
  624.         DoGetFullPathNameW((WCHAR*)pInName, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW);
  625.     }
  626.     else {
  627.         /* relative path with drive letter */
  628.         wcscpy(szBuffer, GetDirW(DriveIndex((char)*pInName)));
  629.         wcscat(szBuffer, &pInName[2]);
  630.         if(wcslen(szBuffer) > MAX_PATH)
  631.         szBuffer[MAX_PATH] = '\0';
  632.  
  633.         DoGetFullPathNameW(szBuffer, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW);
  634.     }
  635.     }
  636.     else {
  637.     /* no drive letter */
  638.     if (IsPathSep(pInName[1]) && IsPathSep(pInName[0])) {
  639.         /* UNC name */
  640.         DoGetFullPathNameW((WCHAR*)pInName, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW);
  641.     }
  642.     else {
  643.         wcscpy(szBuffer, GetDefaultDirW());
  644.         if (IsPathSep(pInName[0])) {
  645.         /* absolute path */
  646.         wcscpy(&szBuffer[2], pInName);
  647.         DoGetFullPathNameW(szBuffer, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW);
  648.         }
  649.         else {
  650.         /* relative path */
  651.         if (IsSpecialFileName(pInName)) {
  652.             return (WCHAR*)pInName;
  653.         }
  654.         else {
  655.             wcscat(szBuffer, pInName);
  656.             if (wcslen(szBuffer) > MAX_PATH)
  657.             szBuffer[MAX_PATH] = '\0';
  658.  
  659.             DoGetFullPathNameW(szBuffer, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW);
  660.         }
  661.         }
  662.     }
  663.     }
  664.     return szLocalBufferW;
  665. }
  666.  
  667. int VDir::SetCurrentDirectoryW(WCHAR *lpBuffer)
  668. {
  669.     WCHAR *pPtr;
  670.     int length, nRet = -1;
  671.  
  672.     pPtr = MapPathW(lpBuffer);
  673.     length = wcslen(pPtr);
  674.     if(length > 3 && IsPathSep(pPtr[length-1])) {
  675.     /* don't remove the trailing slash from 'x:\'  */
  676.     pPtr[length-1] = '\0';
  677.     }
  678.  
  679.     DWORD r = GetFileAttributesW(pPtr);
  680.     if ((r != 0xffffffff) && (r & FILE_ATTRIBUTE_DIRECTORY))
  681.     {
  682.     WCHAR wBuffer[(MAX_PATH+1)*2];
  683.     DoGetFullPathNameW(pPtr, (sizeof(wBuffer)/sizeof(WCHAR)), wBuffer);
  684.     SetDefaultDirW(wBuffer, DriveIndex((char)wBuffer[0]));
  685.     nRet = 0;
  686.     }
  687.  
  688.     return nRet;
  689. }
  690.  
  691. #endif    /* ___VDir_H___ */
  692.