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