創建共享目錄需調用 NetShareAdd,但其所在 DLL 不同:
Netapi32.dllSvrapi.dll靜態鏈接對應 .lib 會導致在另一平台啟動失敗(缺少 DLL/導出函數)。解決方案:運行時動態加載 DLL,獲取函數指針調用。
// 函數指針類型
typedef DWORD (WINAPI *NETSHAREADD2K)(LPWSTR, DWORD, LPBYTE, LPDWORD); // NT/2K: Unicode, Level 2
typedef DWORD (WINAPI *NETSHAREADD9X)(const char FAR*, short, const char FAR*, unsigned short); // 9x: ANSI, Level 50
NETSHAREADD2K pNetShareAdd2k = NULL;
NETSHAREADD9X pNetShareAdd9x = NULL;
bool bWinNT = false;
HINSTANCE hDll = NULL;
// 常量
#define NNLEN 80
#define LM20_NNLEN 12
#define SHPWLEN 8
#define STYPE_DISKTREE 0
#define SHI50F_FULL 0x0002
#define NERR_Success 0
#define NERR_BASE 2100
#define NERR_DuplicateShare (NERR_BASE + 18)
#define NERR_RedirectedPath (NERR_BASE + 17)
#define NERR_UnknownDevDir (NERR_BASE + 16)
// 9x 結構 (Level 50)
struct share_info_50 {
char shi50_netname[LM20_NNLEN + 1];
unsigned char shi50_type;
unsigned short shi50_flags;
char FAR *shi50_remark;
char FAR *shi50_path;
char shi50_rw_password[SHPWLEN + 1];
char shi50_ro_password[SHPWLEN + 1];
};
// 2K 結構 (Level 2)
struct SHARE_INFO_2 {
LPWSTR shi2_netname;
DWORD shi2_type;
LPWSTR shi2_remark;
DWORD shi2_permissions;
DWORD shi2_max_uses;
DWORD shi2_current_uses;
LPWSTR shi2_path;
LPWSTR shi2_passwd;
};
bool __fastcall InitApi() {
OSVERSIONINFO info = { sizeof(info) };
GetVersionEx(&info);
bWinNT = (info.dwPlatformId == VER_PLATFORM_WIN32_NT);
if (bWinNT) {
hDll = LoadLibrary("Netapi32.dll");
if (hDll) pNetShareAdd2k = (NETSHAREADD2K)GetProcAddress(hDll, "NetShareAdd");
} else {
hDll = LoadLibrary("Svrapi.dll");
if (hDll) pNetShareAdd9x = (NETSHAREADD9X)GetProcAddress(hDll, "NetShareAdd");
}
return (bWinNT ? pNetShareAdd2k : pNetShareAdd9x) != NULL;
}
String __fastcall MyPathToNetShare(String strPath, String strNetName,
String strPassword, String strRemark) {
if (!InitApi()) return "函數獲取錯誤!";
if (!bWinNT) { // Windows 9x
share_info_50 *pBuf = (share_info_50*)malloc(sizeof(share_info_50));
if (!pBuf) return "內存分配失敗!";
strcpy(pBuf->shi50_netname, strNetName.c_str());
pBuf->shi50_type = STYPE_DISKTREE;
pBuf->shi50_flags = SHI50F_FULL;
pBuf->shi50_remark = strRemark.c_str();
pBuf->shi50_path = strPath.c_str();
strcpy(pBuf->shi50_rw_password, strPassword.c_str());
strcpy(pBuf->shi50_ro_password, strPassword.c_str());
DWORD nStatus = pNetShareAdd9x(NULL, 50, (char FAR*)pBuf, sizeof(share_info_50));
free(pBuf);
FreeLibrary(hDll);
return (nStatus == NERR_Success) ? "添加成功!" : "錯誤碼: " + String(nStatus);
}
else { // Windows 2000/NT
// 提升權限(需要 SE_SECURITY_PRIVILEGE 或管理員)
HANDLE hToken;
TOKEN_PRIVILEGES tk;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tk.Privileges[0].Luid); // 注意:原代碼用 SE_SHUTDOWN_NAME 可能不夠
tk.PrivilegeCount = 1;
tk.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tk, 0, NULL, 0);
SHARE_INFO_2 si2 = {0};
si2.shi2_path = StringToOleStr(strPath);
si2.shi2_remark = StringToOleStr(strRemark);
si2.shi2_netname = StringToOleStr(strNetName);
si2.shi2_passwd = StringToOleStr(strPassword);
si2.shi2_type = STYPE_DISKTREE;
si2.shi2_permissions = 0; // ACCESS_READ | ACCESS_WRITE...
si2.shi2_max_uses = -1;
si2.shi2_current_uses = 0;
DWORD dwParamErr;
DWORD nas = pNetShareAdd2k(NULL, 2, (LPBYTE)&si2, &dwParamErr);
FreeLibrary(hDll);
switch (nas) {
case NERR_Success: return "設置成功!";
case ERROR_ACCESS_DENIED: return "拒絕訪問! (需管理員權限)";
case NERR_DuplicateShare: return "共享名已存在!";
case NERR_UnknownDevDir: return "路徑不存在!";
default: return "未知錯誤: " + String(nas);
}
}
}
void __fastcall TForm1::Button1Click(TObject *Sender) {
ShowMessage(MyPathToNetShare("C:\\ShareDir", "MyShare", "", "共享說明"));
}
LoadLibrary + GetProcAddress 解決平台差異,核心技巧。char*),2K 用 Unicode (LPWSTR),StringToOleStr (SysAllocString) 轉換 BSTR,用完需 SysFreeString(此處簡化未釋放,生產代碼必須釋放)。#pragma pack(push, 1) 確保與系統定義一致,防止參數錯位。requireAdministrator 或檢查權限)。NetShareAdd (Netapi32.dll 統一),但需處理 UAC、共享權限 ACL (SID/ACE)。Win32_Share.Create) 或 PowerShell (New-SmbShare) 更高層抽象。動態加載 NetShareAdd 是解決 Win9x/2K 跨平台創建共享的經典方案。理解平台差異、字符集、結構體、權限模型,舉一反三可應用於其他跨版本系統 API 調用(如 NetUserAdd、NetServerEnum 等)。